def get_all_hough_lines(image, min_angle, max_angle, min_separation_distance, min_separation_angle): angles = np.deg2rad(np.arange(min_angle, max_angle, 0.5)) hough, angles, distances = hough_line(image, angles) Debug.save_image("hough", "accumulator", normalize(hough)) _, peak_angles, peak_distances = \ hough_line_peaks(hough, angles, distances, num_peaks=150, threshold=0.2*np.amax(hough), min_distance=min_separation_distance, min_angle=min_separation_angle) lines = [ get_line_endpoints_in_image(image, angle, radius) for angle, radius in zip(peak_angles, peak_distances) ] if Debug.active: peak_angle_idxs = [ np.where(angles == angle)[0][0] for angle in peak_angles ] peak_rho_idxs = [ np.where(distances == distance)[0][0] for distance in peak_distances ] peak_coords = zip(peak_rho_idxs, peak_angle_idxs) peaks = np.zeros(hough.shape) for coord in peak_coords: peaks[coord] = 1 Debug.save_image("hough", "accumulator_peaks", peaks) if Record.active: # Thought get_max_theta_idx might be a useful way to filter # real meanlines from spurious meanlines, but it's not # reliable when the image is saturated with incorrect # meanlines. Filtering lines based on the ROI angle # was more effective. # max_theta_idx = get_max_theta_idx(hough) # Record.record("theta_mode", angles[max_theta_idx]) # in radians average_meanline_angle = np.mean(peak_angles) std_deviation_meanline_angle = np.std(peak_angles) Record.record("average_meanline_angle", float("%.4f" % average_meanline_angle)) Record.record("std_deviation_meanline_angle", float("%.4f" % std_deviation_meanline_angle)) return lines
def get_max_theta_idx(hough): ''' Returns the column (theta) of the hough transform with the most above-threshold bins. ''' thresh_hough = threshold_hough(hough, 0.2 * np.amax(hough)) Debug.save_image("hough", "thresholded_accumulator", normalize(thresh_hough)) # find the column with the most above-threshold bins sum_thresh_hough = np.sum(thresh_hough, axis=0) max_theta_idx = np.argmax(sum_thresh_hough) return max_theta_idx
def detect_meanlines(masked_image, corners, scale=1): padding = PARAMS["trace-spacing"](scale) / 2 timeStart("bound image") # effectively shrink the roi by a distance **padding** top_bound = padding + np.amax( [corners["top_left"][1], corners["top_right"][1]]) bottom_bound = -padding + np.amin( [corners["bottom_left"][1], corners["bottom_right"][1]]) left_bound = padding + np.amax( [corners["bottom_left"][0], corners["top_left"][0]]) right_bound = -padding + np.amin( [corners["top_right"][0], corners["bottom_right"][0]]) # mask all image values outside of this shrunken roi bounded_image = masked_image.copy() bounded_image[:top_bound, :] = ma.masked bounded_image[bottom_bound:, :] = ma.masked bounded_image[:, :left_bound] = ma.masked bounded_image[:, right_bound:] = ma.masked timeEnd("bound image") Debug.save_image("meanlines", "bounded_image", bounded_image.filled(0)) timeStart("threshold image") black_and_white_image = otsu_threshold_image(bounded_image) timeEnd("threshold image") Debug.save_image("meanlines", "thresholded_image", black_and_white_image) timeStart("remove small objects") filtered_image = remove_small_objects(black_and_white_image, PARAMS["small-object-size"](scale)) timeEnd("remove small objects") Debug.save_image("meanlines", "filtered_image", filtered_image) timeStart("get hough lines") roi_top_angle = np.rad2deg( points_to_rho_theta(corners["top_left"], corners["top_right"])[1]) angle_padding = 2 # degrees min_angle = roi_top_angle - angle_padding max_angle = roi_top_angle + angle_padding min_separation_distance = int((2.0 / 3) * PARAMS["trace-spacing"](scale)) lines = get_all_hough_lines( filtered_image, min_angle=min_angle, max_angle=max_angle, min_separation_distance=min_separation_distance, min_separation_angle=5) timeEnd("get hough lines") print "found %s meanlines" % len(lines) Record.record("num_meanlines", len(lines)) if Debug.active: debug_image = gray2rgb(np.copy(masked_image)) line_coords = [ skidraw.line(line[0][1], line[0][0], line[1][1], line[1][0]) for line in lines ] for line in line_coords: rr, cc = line mask = (rr >= 0) & (rr < debug_image.shape[0]) & (cc >= 0) & ( cc < debug_image.shape[1]) debug_image[rr[mask], cc[mask]] = [1.0, 0, 0] Debug.save_image("meanlines", "meanlines", debug_image) return lines