def show_validation(M, nb_it, PY_before, PY_after): ''' Plots the landmarks corresponding to the mean shape in the model coordinate frame and the landmarks corresponding to the current points in the model coordinate frame @param M: the model for the tooth @param nb_it: the number of this iteration @param PY_before: the current points for the target tooth before validation in the model coordinate frame @param PY_after: the current points for the target tooth after validation in the model coordinate frame ''' mxs, mys = mu.extract_coordinates(M) mxs = mu.make_circular(mxs) mys = mu.make_circular(mys) rxs, rys = mu.extract_coordinates(PY_before) rxs = mu.make_circular(rxs) rys = mu.make_circular(rys) gxs, gys = mu.extract_coordinates(PY_after) gxs = mu.make_circular(gxs) gys = mu.make_circular(gys) pyplot.figure(1) # x coordinates , y coordinates pyplot.plot(mxs, mys, '-+b') pyplot.plot(rxs, rys, '-+r') pyplot.plot(gxs, gys, '-+g') txt = 'Model Coordinate Frame - Iteration: ' + str(nb_it) pyplot.title(txt) pyplot.xlabel('x\'') pyplot.ylabel('y\'') pyplot.gca().invert_yaxis() pyplot.axis('equal') pyplot.show()
def mark_results(img, PS, color_lines=np.array( [np.array([0, 0, 255]), np.array([0, 255, 0])]), color_init=np.array([0, 255, 255]), color_mid=np.array([255, 0, 255]), color_end=np.array([255, 255, 0])): for p in range(PS.shape[0]): pxs, pys = mu.extract_coordinates(PS[p, :]) for k in range(c.get_nb_landmarks()): px = int(pxs[k]) py = int(pys[k]) if (k == c.get_nb_landmarks() - 1): px_succ = int(pxs[0]) py_succ = int(pys[0]) else: px_succ = int(pxs[(k + 1)]) py_succ = int(pys[(k + 1)]) cv2.line(img, (px, py), (px_succ, py_succ), color_lines[p]) for p in range(PS.shape[0]): pxs, pys = mu.extract_coordinates(PS[p, :]) for k in range(c.get_nb_landmarks()): px = int(pxs[k]) py = int(pys[k]) if (k == 0): img[py, px] = color_init elif (k == c.get_nb_landmarks() - 1): img[py, px] = color_end else: img[py, px] = color_mid return img
def create_landmarks_and_models_images(color_init=np.array([0,255,255]), color_mid=np.array([255,0,255]), color_end=np.array([255,255,0]), color_line=np.array([0,0,255]), color_model_line=np.array([255,0,0]), method=''): ''' Stores all the preprocessed images corresponding to the given method with the landmarks of the training samples and models (transformed to the image coordinate system) marked. @param color_init: the BGR color for the first landmark @param color_mid: the BGR color for all landmarks except the first and last landmark @param color_end: the BGR color for the last landmark @param color_line: the BGR color for the line between two consecutive landmarks of the training samples @param color_model_line: the BGR color for the line between two consecutive landmarks of the models @param method: the method used for preproccesing ''' for i in c.get_trainingSamples_range(): fname = c.get_fname_vis_pre(i, method) img = cv2.imread(fname) for j in range(c.get_nb_teeth()): xs, ys = mu.extract_coordinates(XS[j,(i-1),:]) mxs, mys = mu.extract_coordinates(mu.full_align_with(MS[j], XS[j,(i-1),:])) for k in range(c.get_nb_landmarks()): x = int(xs[k] - offsetX) y = int(ys[k] - offsetY) mx = int(mxs[k] - offsetX) my = int(mys[k] - offsetY) if (k == c.get_nb_landmarks()-1): x_succ = int(xs[0] - offsetX) y_succ = int(ys[0] - offsetY) mx_succ = int(mxs[0] - offsetX) my_succ = int(mys[0] - offsetY) else: x_succ = int(xs[(k+1)] - offsetX) y_succ = int(ys[(k+1)] - offsetY) mx_succ = int(mxs[(k+1)] - offsetX) my_succ = int(mys[(k+1)] - offsetY) cv2.line(img, (x,y), (x_succ,y_succ), color_line) cv2.line(img, (mx,my), (mx_succ,my_succ), color_model_line) for k in range(c.get_nb_landmarks()): x = int(xs[k] - offsetX) y = int(ys[k] - offsetY) mx = int(mxs[k] - offsetX) my = int(mys[k] - offsetY) if (k == 0): img[y,x] = color_init img[my,mx] = color_init elif (k == c.get_nb_landmarks()-1): img[y,x] = color_end img[my,mx] = color_end else: img[y,x] = color_mid img[my,mx] = color_mid fname = c.get_fname_vis_ff_landmarks_and_models(i, method) cv2.imwrite(fname, img)
def classify_positives(method=''): XS = l.create_full_XS() for s in c.get_trainingSamples_range(): trainingSamples = c.get_trainingSamples_range() trainingSamples.remove(s) try: info_name_upper = c.get_dir_prefix() + 'data/Visualizations/Classified Samples/info' + method + str(s) + '-u' + '.txt' info_name_lower = c.get_dir_prefix() + 'data/Visualizations/Classified Samples/info' + method + str(s) + '-l' + '.txt' info_file_upper = open(info_name_upper, "w") info_file_lower = open(info_name_lower, "w") for i in trainingSamples: s = '' if (i < 10): s = '0' img_name = s + str(i) + '.png' min_y = min_x = float("inf") max_y = max_x = 0 for j in range(0, c.get_nb_teeth()/2): x_coords, y_coords = mu.extract_coordinates(XS[j, i-1, :]) for k in range(c.get_nb_landmarks()): if x_coords[k] < min_x: min_x = x_coords[k] if x_coords[k] > max_x: max_x = x_coords[k] if y_coords[k] < min_y: min_y = y_coords[k] if y_coords[k] > max_y: max_y = y_coords[k] line = 'rawdata/' + method + img_name + ' 1 ' + str(int(min_x - fu.offsetX)) + ' ' + str(int(min_y - fu.offsetY)) + ' ' + str(int(max_x - min_x)) + ' ' + str(int(max_y - min_y)) + '\n' info_file_upper.write(line) min_y = min_x = float("inf") max_y = max_x = 0 for j in range(c.get_nb_teeth()/2, c.get_nb_teeth()): x_coords, y_coords = mu.extract_coordinates(XS[j, i-1, :]) for k in range(c.get_nb_landmarks()): if x_coords[k] < min_x: min_x = x_coords[k] if x_coords[k] > max_x: max_x = x_coords[k] if y_coords[k] < min_y: min_y = y_coords[k] if y_coords[k] > max_y: max_y = y_coords[k] line = 'rawdata/' + method + img_name + ' 1 ' + str(int(min_x - fu.offsetX)) + ' ' + str(int(min_y - fu.offsetY)) + ' ' + str(int(max_x - min_x)) + ' ' + str(int(max_y - min_y)) + '\n' info_file_lower.write(line) finally: info_file_upper.close() info_file_lower.close()
def plot_landmarks(X, nr_trainingSample=1, nr_tooth=1, closed_curve=False): ''' Plots the landmarks corresponding to the given training sample in the image coordinate frame. @param X: the training samples @param nr_trainingSample: the training sample to select @param nr_tooth: the number of the tooth (just used for the title of the plot) @param closed_curve: must the curve be closed ''' xCoords, yCoords = mu.extract_coordinates(X[(nr_trainingSample - 1), :]) if (closed_curve): xCoords = mu.make_circular(xCoords) yCoords = mu.make_circular(yCoords) pyplot.figure(1) pyplot.title('Training sample nr: ' + str(nr_trainingSample) + ' | ' + 'Tooth nr: ' + str(nr_tooth)) # x coordinates , y coordinates pyplot.plot(xCoords, yCoords, '-+r') pyplot.gca().invert_yaxis() pyplot.axis('equal') pyplot.xlabel('x') pyplot.ylabel('y') pyplot.show()
def store_plotted_landmarks(closed_curve=False): ''' Stores the plots of the landmarks corresponding to all the training samples and all the teeth in the image coordinate frame in seperate plots for each training sample, for each tooth. The scale and limits of the axes are the same for each plot. @param closed_curve: must the curve be closed ''' XS = l.create_full_XS() (ymin, ymax, xmin, xmax) = pre.learn_offsets_safe(XS) for j in range(XS.shape[0]): for i in range(XS.shape[1]): xCoords, yCoords = mu.extract_coordinates(XS[j, i, :]) if (closed_curve): xCoords = mu.make_circular(xCoords) yCoords = mu.make_circular(yCoords) pyplot.figure() pyplot.title('Training sample nr: ' + str((i + 1)) + ' | ' + 'Tooth nr: ' + str((j + 1))) # x coordinates , y coordinates pyplot.plot(xCoords, yCoords, '-+r') pyplot.axis([xmin, xmax, ymin, ymax]) pyplot.gca().set_aspect('equal', adjustable='box') pyplot.xlabel('x') pyplot.ylabel('y') pyplot.gca().invert_yaxis() fname = c.get_fname_vis_landmark((i + 1), (j + 1)) pyplot.savefig(fname, bbox_inches='tight') #You get a runtime warning if you open more than 20 figures #Closing comes with a performance penalty pyplot.close()
def learn_offsets(XS): ''' Learns the minimal y coordinate, maximal y coordinate, minimal x coordinate and maximal x coordinate for the training samples. @param XS: the samples with dimensions: (nb_teeth x nb_trainingSamples x nb_dim) @return the learned minimal y coordinate, learned maximal y coordinate, learned minimal x coordinate and learned maximal x coordinate for the training samples. ''' xmin = ymin = float("inf") xmax = ymax = 0 for j in range(XS.shape[0]): for i in range(XS.shape[1]): xCoords, yCoords = mu.extract_coordinates(XS[j,i,:]) #looping twice with one check has approximately same #complexity as looping once with two checks xmin = min(xmin, np.amin(xCoords)) xmax = max(xmax, np.amax(xCoords)) #looping twice with one check has approximately same #complexity as looping once with two checks ymin = min(ymin, np.amin(yCoords)) ymax = max(ymax, np.amax(yCoords)) return (ymin, ymax, xmin, xmax)
def limit(img, P): pxs, pys = mu.extract_coordinates(P) pys[pys < 0] = 0 pys[pys >= img.shape[0]] = img.shape[0] - 1 pxs[pxs < 0] = 0 pxs[pxs >= img.shape[1]] = img.shape[1] - 1 P = mu.zip_coordinates(pxs, pys) return P
def store_plotted_vary_mode_param(closed_curve=False): ''' Stores the plots of the effects of varying one mode parameter / shape parameter in -3 s.d. / -2 s.d. / -1 s.d. / M / +1 s.d. / +2 s.d. / +3 s.d. in the model coordinate frame for all the teeth. @param closed_curve: must the curve be closed ''' for t in c.get_teeth_range(): M, Y = pa.PA(l.create_full_X(nr_tooth=t)) E, W, MU = pca.pca_percentage(Y) YS = np.zeros(np.array([E.shape[0], 7, c.get_nb_dim()])) for e in range(YS.shape[0]): se = math.sqrt(E[e]) C = np.zeros(W.shape[1]) C[e] = 1 j = 0 for i in range(-3, 4): YS[e, j, :] = pca.reconstruct(W, C * i * se, M) j += 1 (ymin, ymax, xmin, xmax) = pre.learn_offsets(YS) ymin -= 0.01 ymax += 0.01 xmin -= 0.01 xmax += 0.01 for e in range(YS.shape[0]): pyplot.figure() for j in range(1, YS.shape[1] + 1): xCoords, yCoords = mu.extract_coordinates(YS[e, (j - 1), :]) if (closed_curve): xCoords = mu.make_circular(xCoords) yCoords = mu.make_circular(yCoords) # x coordinates , y coordinates pyplot.subplot(1, 7, j) pyplot.plot(xCoords, yCoords, '-+r') pyplot.axis([xmin, xmax, ymin, ymax]) pyplot.gca().set_aspect('equal', adjustable='box') if j == 1: pyplot.ylabel('y\'') if j == 4: pyplot.title('Tooth nr: ' + str(t) + ' | ' + 'Eigenvalue: ' + str(E[e])) pyplot.xlabel('x\'') frame = pyplot.gca() if j % 2 == 0: frame.axes.get_xaxis().set_ticks([]) else: frame.axes.get_xaxis().set_ticks([xmin, xmax]) pyplot.gca().invert_yaxis() #pyplot.subplots_adjust(right=1) fname = c.get_fname_vis_pca(t, (e + 1)) pyplot.savefig(fname, bbox_inches='tight') pyplot.close()
def create_profile_normals_images(k=5, color_init=np.array([0,255,255]), color_mid=np.array([255,0,255]), color_end=np.array([255,255,0]), color_line=np.array([255,0,0]), color_profile_point=np.array([0,255,0]), method=''): ''' Stores all the preprocessed images corresponding to the given method with the landmarks of the models (transformed to the image coordinate system) and the points along the profile normals marked. @param k: the number of profile points along either side of the profile normal and profile tangent @param color_init: the BGR color for the first landmark @param color_mid: the BGR color for all landmarks except the first and last landmark @param color_end: the BGR color for the last landmark @param color_line: the BGR color for the line between two consecutive landmarks @param color_profile_point: the BGR color for the profile points @param method: the method used for preproccesing ''' for i in c.get_trainingSamples_range(): fname = c.get_fname_vis_pre(i, method) img = cv2.imread(fname) for j in range(c.get_nb_teeth()): xs, ys = mu.extract_coordinates(mu.full_align_with(MS[j], XS[j,(i-1),:])) for h in range(c.get_nb_landmarks()): x = int(xs[h] - offsetX) y = int(ys[h] - offsetY) if (h == c.get_nb_landmarks()-1): x_succ = int(xs[0] - offsetX) y_succ = int(ys[0] - offsetY) else: x_succ = int(xs[(h+1)] - offsetX) y_succ = int(ys[(h+1)] - offsetY) cv2.line(img, (x,y), (x_succ,y_succ), color_line) for h in range(c.get_nb_landmarks()): x = int(xs[h] - offsetX) y = int(ys[h] - offsetY) tx, ty, nx, ny = ff.create_ricos(img, h, xs, ys) for n in range(-k, k+1): kx = round(x + n * nx) ky = round(y + n * ny) img[ky, kx] = color_profile_point for t in range(-k, k+1): kx = round(x + t * tx) ky = round(y + t * ty) img[ky, kx] = color_profile_point if (h == 0): img[y,x] = color_init elif (h == c.get_nb_landmarks()-1): img[y,x] = color_end else: img[y,x] = color_mid fname = c.get_fname_vis_ff_profile_normals(i, method) cv2.imwrite(fname, img)
def create_negatives(method=''): XS = l.create_full_XS() for i in c.get_trainingSamples_range(): fname = c.get_fname_vis_pre(i, method) img = cv2.imread(fname) s = '' if (i < 10): s = '0' min_y = min_x = float("inf") max_y = max_x = 0 for j in range(0, c.get_nb_teeth()/2): x_coords, y_coords = mu.extract_coordinates(XS[j, i-1, :]) for k in range(c.get_nb_landmarks()): if x_coords[k] < min_x: min_x = x_coords[k] if x_coords[k] > max_x: max_x = x_coords[k] if y_coords[k] < min_y: min_y = y_coords[k] if y_coords[k] > max_y: max_y = y_coords[k] fname = c.get_dir_prefix() + 'data/Visualizations/Classified Samples/' + method + str(s) + str(i) + '-l' + '.png' cv2.imwrite(fname, img[max_y-fu.offsetY+1:,:]) min_y = min_x = float("inf") max_y = max_x = 0 for j in range(c.get_nb_teeth()/2, c.get_nb_teeth()): x_coords, y_coords = mu.extract_coordinates(XS[j, i-1, :]) for k in range(c.get_nb_landmarks()): if x_coords[k] < min_x: min_x = x_coords[k] if x_coords[k] > max_x: max_x = x_coords[k] if y_coords[k] < min_y: min_y = y_coords[k] if y_coords[k] > max_y: max_y = y_coords[k] fname = c.get_dir_prefix() + 'data/Visualizations/Classified Samples/' + method + str(s) + str(i) + '-u' + '.png' cv2.imwrite(fname, img[:min_y-fu.offsetY,:])
def display_landmarks(X, nr_trainingSample=1, color=np.array([0, 0, 255])): ''' Displays the landmarks corresponding to the given training sample on the corresponding radiograph in the image coordinate frame. @param X: the training samples @param nr_trainingSample: the training sample to select @param color: the color used for displaying ''' img = cv2.imread(c.get_fname_radiograph(nr_trainingSample)) xCoords, yCoords = mu.extract_coordinates(X[(nr_trainingSample - 1), :]) for i in range(c.get_nb_landmarks()): #y coordinate , x coordinate img[yCoords[i], xCoords[i], :] = color #cv2.imshow("test", img) # writing instead of showing, because the displayed image is too large cv2.imwrite("test.tif", img)
def create_individual_bboxes(method=''): XS = l.create_full_XS() IBS = np.zeros((XS.shape[0], XS.shape[1], 4)) for j in range(XS.shape[0]): for i in range(XS.shape[1]): min_y = min_x = float("inf") max_y = max_x = 0 x_coords, y_coords = mu.extract_coordinates(XS[j,i,:]) for k in range(x_coords.shape[0]): if x_coords[k] < min_x: min_x = x_coords[k] if x_coords[k] > max_x: max_x = x_coords[k] if y_coords[k] < min_y: min_y = y_coords[k] if y_coords[k] > max_y: max_y = y_coords[k] IBS[j,i,0] = min_x - fu.offsetX IBS[j,i,1] = max_x - fu.offsetX IBS[j,i,2] = min_y - fu.offsetY IBS[j,i,3] = max_y - fu.offsetY return IBS
def create_partial_GS(trainingSamples, XS, MS, level=0, offsetX=0, offsetY=0, k=5, method=''): ''' Creates the matrix GNS which contains for each tooth, for each of the given training samples, for each landmark, a normalized sample (along the profile normal through the landmarks). Creates the matrix GTS which contains for each tooth, for each of the given training samples, for each landmark, a normalized sample (along the profile tangent through the landmarks). @param trainingSamples: the number of the training samples (not the test training samples!) @param XS: contains for each tooth, for each training sample, all landmarks (in the image coordinate frame) @param MS: contains for each tooth, the tooth model (in the model coordinate frame) @param level: the current level @param offsetX: the possible offset in x direction (used when working with cropped images and non-cropped landmarks) @param offsetY: the possible offset in y direction (used when working with cropped images and non-cropped landmarks) @param k: the number of pixels to sample either side for each of the model points along the profile normal @param method: the method used for preprocessing @return The matrix GNS which contains for each tooth, for each of the given training samples, for each landmark, a normalized sample (along the profile normal through that landmark). The matrix GTS which contains for each tooth, for each of the given training samples, for each landmark, a normalized sample (along the profile tangent through that landmark). ''' GNS = np.zeros((c.get_nb_teeth(), len(trainingSamples), c.get_nb_landmarks(), 2 * k + 1)) GTS = np.zeros((c.get_nb_teeth(), len(trainingSamples), c.get_nb_landmarks(), 2 * k + 1)) for j in range(c.get_nb_teeth()): index = 0 for i in trainingSamples: # model of tooth j from model coordinate frame to image coordinate frame xs, ys = mu.extract_coordinates( mu.full_align_with(MS[j], XS[j, index, :])) fname = c.get_fname_vis_pre(i, method) img = cv2.imread(fname) pyramid = gip.get_gaussian_pyramid_at(img, level) GN, GT = create_G(pyramid, k, xs, ys, offsetX, offsetY) GNS[j, index, :] = GN GTS[j, index, :] = GT index += 1 return GNS, GTS
def multi_resolution_search(img, P, tooth_index, fitting_function=1, show=False): ''' Fits the tooth corresponding to the given tooth index in the given image. @param img: the image @param P: the start points for the target tooth @param tooth_index: the index of the the target tooth (used in MS, EWS, fs) @param fitting_function: the fitting function used * 0: fitting function along profile normal through landmark + fitting function along profile gradient through landmark * 1: fitting function along profile normal through landmark * 2: fitting function along profile gradient through landmark @param show: must the intermediate results (after each iteration) be displayed @return The fitted points for the tooth corresponding to the given tooth index and the number of iterations used. ''' nb_it = 0 level = max_level pyramids = gip.get_gaussian_pyramids(img, level) # Compute model point positions in image at coarsest level P = np.around(np.divide(P, 2**level)) while (level >= 0): nb_it += 1 pxs, pys = mu.extract_coordinates(P) for i in range(c.get_nb_landmarks()): tx, ty, nx, ny = ff.create_ricos(pyramids[level], i, pxs, pys) f_optimal = float("inf") if (fitting_function == 0): rn = rt = range(-(m - k), (m - k) + 1) elif (fitting_function == 1): rn = range(-(m - k), (m - k) + 1) rt = [0] else: rn = [0] rt = range(-(m - k), (m - k) + 1) for n in rn: for t in rt: x = round(pxs[i] + n * nx + t * tx) y = round(pys[i] + n * ny + t * ty) try: fn = fns[level][tooth_index][i](ff.normalize_Gi( ff.create_Gi(pyramids[level], k, x, y, nx, ny))) ft = fts[level][tooth_index][i](ff.normalize_Gi( ff.create_Gi(pyramids[level], k, x, y, tx, ty))) except (IndexError): continue f = fu.evaluate_fitting(fn=fn, ft=ft, fitting_function=fitting_function) if f < f_optimal: f_optimal = f cx = x cy = y pxs[i] = cx pys[i] = cy P_new = validate(pyramids[level], tooth_index, mu.zip_coordinates(pxs, pys), nb_it, show) nb_close_points = nb_closest_points(P, P_new) P = P_new # Repeat unless more than pclose of the points are found close to the current position # or nmax iterations have been applied at this resolution print 'Level:' + str(level) + ', Iteration: ' + str( nb_it) + ', Ratio: ' + str( (2 * nb_close_points / float(P.shape[0]))) converged = (2 * nb_close_points / float(P.shape[0]) >= pclose) if (converged or nb_it >= max_it): if (level > 0): level -= 1 nb_it = 0 P = P * 2 else: break return P