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_G(img, k, xs, ys, offsetX=0, offsetY=0): ''' Sample along the profile normal and profile tangent k pixels either side for each of the given model points (xs[i], ys[i]) in the given image to create the matrix G, which contains for each landmark a normalized sample. @param img: the image @param k: the number of pixels to sample either side for each of the given model points (xs[i], ys[i]) along the profile normal @param i: the index of the model point @param xs: x positions of the model points in the image @param ys: y positions of the model points in the image @param offsetX: the possible offset in x direction (used when working with cropped images and non-cropped xs & ys) @param offsetY: the possible offset in y direction (used when working with cropped images and non-cropped xs & ys) @return The matrix GN, which contains for each landmark a normalized sample (sampled along the profile normal through the landmarks). The matrix GT, which contains for each landmark a normalized sample (sampled along the profile tangent through the landmarks). ''' GN = np.zeros((c.get_nb_landmarks(), 2 * k + 1)) GT = np.zeros((c.get_nb_landmarks(), 2 * k + 1)) for i in range(c.get_nb_landmarks()): x = xs[i] - offsetX y = ys[i] - offsetY tx, ty, nx, ny = create_ricos(img, i, xs, ys) GN[i, :] = normalize_Gi(create_Gi(img, k, x, y, nx, ny)) GT[i, :] = normalize_Gi(create_Gi(img, k, x, y, tx, ty)) return GN, GT
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 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 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 draw_landmark(event, x, y, flags, param): if (event == cv2.EVENT_LBUTTONDOWN and count < c.get_nb_landmarks()): global img, count, landmarks landmarks[(2 * count)] = float(x) landmarks[(2 * count + 1)] = float(y) if count > 0: xp = int(landmarks[(2 * count - 2)]) yp = int(landmarks[(2 * count - 1)]) cv2.line(img, (xp, yp), (x, y), (0, 0, 255)) cv2.circle(img, (x, y), 2, (0, 0, 255), -1) count += 1 if count == c.get_nb_landmarks(): xp = int(landmarks[0]) yp = int(landmarks[1]) cv2.line(img, (x, y), (xp, yp), (0, 0, 255))
def create_fitting_functions(GNS, GTS): ''' Creates the fitting function for each tooth, for each landmark. @param GNS: 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) @param GTS: 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) @return The fitting functions for each tooth, for each landmark. ''' fns = [[ get_fitting_function(tooth, landmark, GNS) for landmark in range(c.get_nb_landmarks()) ] for tooth in range(c.get_nb_teeth())] fts = [[ get_fitting_function(tooth, landmark, GTS) for landmark in range(c.get_nb_landmarks()) ] for tooth in range(c.get_nb_teeth())] return fns, fts
def create_fitting_functions_for_multiple_levels(L_GNS, L_GTS): ''' Creates the fitting function for each level, for each tooth, for each landmark. @param L_GNS: the matrix L_GNS which contains for each level, for each tooth, for each of the given training samples, for each landmark, a normalized sample (along the profile normal through that landmark) @param L_GTS: the matrix L_GTS which contains for each level, for each tooth, for each of the given training samples, for each landmark, a normalized sample (along the profile tangent through that landmark) @return The fitting functions for each level, for each tooth, for each landmark. ''' l_fns = [[[ get_fitting_function(tooth, landmark, L_GNS[level, :]) for landmark in range(c.get_nb_landmarks()) ] for tooth in range(c.get_nb_teeth())] for level in range(L_GNS.shape[0])] l_fts = [[[ get_fitting_function(tooth, landmark, L_GTS[level, :]) for landmark in range(c.get_nb_landmarks()) ] for tooth in range(c.get_nb_teeth())] for level in range(L_GTS.shape[0])] return l_fns, l_fts
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 create_partial_GS_for_multiple_levels(trainingSamples, XS, MS, nb_levels=1, offsetX=0, offsetY=0, k=5, method=''): ''' Creates the matrix L_GNS which contains for each level, 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 L_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 nb_levels: the number of levels @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 L_GNS which contains for each level, 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 L_GTS which contains for each level, for each tooth, for each of the given training samples, for each landmark, a normalized sample (along the profile tangent through that landmark). ''' L_GNS = np.zeros((nb_levels, c.get_nb_teeth(), len(trainingSamples), c.get_nb_landmarks(), 2 * k + 1)) L_GTS = np.zeros((nb_levels, c.get_nb_teeth(), len(trainingSamples), c.get_nb_landmarks(), 2 * k + 1)) for i in range(nb_levels): GNS, GTS = create_partial_GS(trainingSamples, np.around(np.divide(XS, 2**i)), MS, i, offsetX=round(float(offsetX) / 2**i), offsetY=round(float(offsetY) / 2**i), k=k, method=method) L_GNS[i, :] = GNS L_GTS[i, :] = GTS return L_GNS, L_GTS
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 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