def test_large_circle_50X50_no_noise_2(self): folder_script = os.path.dirname(__file__) filename_input = "NoisyCircle_x_6_y_-30_r_118.162.png" file_noisy_line = os.path.join(folder_script, "./data/", filename_input) np_image = skimage.io.imread(file_noisy_line, as_gray=True) lst_points = Util.create_points_from_numpyimage(np_image) helper = GradientDescentCircleFitting(None, lst_points, learningrate=0.4, iterations=5000) result: CircleModel = helper.FindBestFittingCircle() # #Superimpose the new line over the image # folder_results = os.path.join(folder_script, "../out/") count_of_files = len(os.listdir(folder_results)) filename_results = ("%s.%d.png" % (__name__, count_of_files)) file_result = os.path.join(folder_results, filename_results) new_points = CircleModel.generate_points_from_circle(result) np_superimposed = Util.superimpose_points_on_image( np_image, new_points, 100, 255, 100) skimage.io.imsave(file_result, np_superimposed) delta = 10 self.assertAlmostEquals(result.R, +118.0, delta=delta) self.assertAlmostEquals(result.X, +06.0, delta=delta) self.assertAlmostEquals(result.Y, -30.0, delta=delta) pass
def test_large_circle_50X50_no_noise_1(self): folder_script=os.path.dirname(__file__) filename_input="NoisyCircle_x_-10_y_-14.png" file_noisy_line=os.path.join(folder_script,"./data/",filename_input) np_image=skimage.io.imread(file_noisy_line,as_gray=True) lst_points=Util.create_points_from_numpyimage(np_image) helper=BullockCircleFitting(lst_points) result:CircleModel =helper.FindBestFittingCircle() # #Superimpose the new line over the image # folder_results=os.path.join(folder_script,"../out/") count_of_files=len(os.listdir(folder_results)) filename_results=("%s.%d.png" % (__name__,count_of_files) ) file_result=os.path.join(folder_results,filename_results) new_points=CircleModel.generate_points_from_circle(result) np_superimposed=Util.superimpose_points_on_image(np_image,new_points,100,255,100) skimage.io.imsave(file_result,np_superimposed) delta=2 self.assertAlmostEquals(result.R, 48.0, delta=delta); self.assertAlmostEquals(result.X, -10.0, delta=delta); self.assertAlmostEquals(result.Y, -14.0, delta=delta); pass
def test_run_with_100x100_image(self): # #get a list of points # folder_script=os.path.dirname(__file__) filename_input="Line_100x100.png" file_noisy_line=os.path.join(folder_script,"./data/",filename_input) np_image=skimage.io.imread(file_noisy_line,as_gray=True) lst_points=Util.create_points_from_numpyimage(np_image) # #initialize RansalHelper # helper1=RansacLineHelper() helper1.add_points(lst_points) helper1.max_iterations=20 helper1.min_points_for_model=2 helper1.threshold_error=10 helper1.threshold_inlier_count=3 result_model=helper1.run() print("RANSAC-complete") print("Found model %s , polar=%s" % (result_model,result_model.display_polar())) # #Superimpose the new line over the image # folder_results=os.path.join(folder_script,"../out/") count_of_files=len(os.listdir(folder_results)) filename_results=("%s.Run.%d.png" % (filename_input,count_of_files) ) file_result=os.path.join(folder_results,filename_results) x_lower=0 x_upper=np_image.shape[1]-1 y_lower=0 y_upper=np_image.shape[0]-1 # #Superimpose a line over the inliers only # new_points=Util.generate_plottable_points_from_projection_of_points(result_model,result_model.points) np_superimposed=Util.superimpose_points_on_image(np_image,new_points,100,255,100) skimage.io.imsave(file_result,np_superimposed) #11 inlier points in total which give us the good model self.assertEqual(len(result_model.points),11) # #No of detected inliers must be more than or equal to threshold # self.assertTrue(len(result_model.points) >= helper1.threshold_inlier_count,"Number of inliers should be >= threshold") # #There should be no-duplicates in the RANSAC inlier points # set_ids=set(map(lambda x: x.ID, result_model.points)) list_ids=list(map(lambda x: x.ID, result_model.points)) self.assertEqual(len(set_ids),len(list_ids),"Inliers should be unique") # #All the RANSAC linlier points must be within the threshold distance from the RANSAC line # for inlier_pt in result_model.points: distance=result_model.compute_distance(inlier_pt) self.assertTrue(distance < helper1.threshold_error,"Distance of inlier from RANSAC line must be less than threshold")
def run(filename, threshold, inlier, sampling_fraction=0.25, matplot=False): print("Going to process file:%s" % (filename)) folder_script = os.path.dirname(__file__) file_noisy_circle = os.path.join(folder_script, "./input/", filename) try: np_image = skimage.io.imread(file_noisy_circle, as_gray=True) # #Iterate over all cells of the NUMPY array and convert to array of Point classes # lst_all_points = Util.create_points_from_numpyimage(np_image) # #begin RANSAC # helper = RansacCircleHelper() helper.threshold_error = threshold helper.threshold_inlier_count = inlier helper.add_points(lst_all_points) helper.sampling_fraction = sampling_fraction best_model = helper.run() print("RANSAC-complete") if (best_model == None): print( "ERROR! Could not find a suitable model. Try altering ransac-threshold and min inliner count" ) return # #Generate an output image with the model circle overlayed on top of original image # now = datetime.datetime.now() filename_result = ("%s-%s.png" % (filename, now.strftime("%Y-%m-%d-%H-%M-%S"))) file_result = os.path.join(folder_script, "./out/", filename_result) #Load input image into array np_image_result = skimage.io.imread(file_noisy_circle, as_gray=True) new_points = CircleModel.generate_points_from_circle(best_model) np_superimposed = Util.superimpose_points_on_image( np_image_result, new_points, 100, 255, 100) #Save new image skimage.io.imsave(file_result, np_superimposed) print("Results saved to file:%s" % (file_result)) print("------------------------------------------------------------") if (matplot == True): plot_new_points_over_existing_points( lst_all_points, new_points, "Outcome of RANSAC algorithm", "Original points", "RANSAC") except Exception as e: tb = traceback.format_exc() print("Error:%s while doing RANSAC on the file: %s , stack=%s" % (str(e), filename, str(tb))) print("------------------------------------------------------------") pass
def test_run_with_very_simple_image(self): # #get a list of points # folder_script=os.path.dirname(__file__) filename_input="Line_50x30.png" file_noisy_line=os.path.join(folder_script,"./data/",filename_input) np_image=skimage.io.imread(file_noisy_line,as_gray=True) lst_points=Util.create_points_from_numpyimage(np_image) # #initialize RansalHelper # helper1=RansacLineHelper() helper1.add_points(lst_points) helper1.max_iterations=1000 #10000 did not work helper1.min_points_for_model=2 helper1.threshold_error=3 #10 helper1.threshold_inlier_count=3 result_model=helper1.run() print("RANSAC-complete") print("Found model %s , polar=%s" % (result_model,result_model.display_polar())) # #Superimpose the new line over the image # folder_results=os.path.join(folder_script,"../out/") count_of_files=len(os.listdir(folder_results)) filename_results=("Line_50x30.%d.png" % (count_of_files) ) file_result=os.path.join(folder_results,filename_results) x_lower=0 x_upper=np_image.shape[1]-1 y_lower=0 y_upper=np_image.shape[0]-1 new_points=LineModel.generate_points_from_line(result_model,x_lower,y_lower,x_upper,y_upper) np_superimposed=Util.superimpose_points_on_image(np_image,new_points,100,255,100) skimage.io.imsave(file_result,np_superimposed) # #Asserts! # x_intercept=result_model.xintercept() y_intercept=result_model.yintercept() self.assertTrue ( x_intercept > 30,"X intercept below threshold") self.assertTrue ( x_intercept < 50,"X intercept above threshold") self.assertTrue ( y_intercept > 30,"Y intercept above threshold") self.assertTrue ( y_intercept < 45,"Y intercept below threshold") self.assertTrue(len(result_model.points),5) for pt in result_model.points: distance_from_line=result_model.compute_distance(pt) self.assertTrue(distance_from_line <= helper1.threshold_error)
def run_image2matplot(filename): folder_script = os.path.dirname(__file__) absolute_path = os.path.join(folder_script, "./input/", filename) try: np_image = skimage.io.imread(absolute_path, as_gray=True) lst_all_points = Util.create_points_from_numpyimage(np_image) plot_new_points_over_existing_points(lst_all_points, [], "Input data", "Original points", "") lrate = 0.3 iterations = 5000 helper = GradientDescentCircleFitting(None, points=lst_all_points, learningrate=lrate, iterations=iterations) start_time = time.time() model: CircleModel = helper.FindBestFittingCircle() new_points = CircleModel.generate_points_from_circle(model) plot_new_points_over_existing_points( lst_all_points, new_points, "Gradient descent circle fitting", "Original points", "Gradient descent") except Exception as e: tb = traceback.format_exc() print("Error:%s while doing RANSAC on the file: %s , stack=%s" % (str(e), filename, str(tb))) print("------------------------------------------------------------") pass pass
def test_run_method_LargeCircle1_50X50_NoNoise(self): # #get a list of points # folder_script = os.path.dirname(__file__) filename_input = "NoisyCircle_x_-10_y_-14.png" file_noisy_circle = os.path.join(folder_script, "./data/", filename_input) np_image = skimage.io.imread(file_noisy_circle, as_gray=True) lst_points = Util.create_points_from_numpyimage(np_image) # #initialize RansalHelper # helper = RansacCircleHelper() helper.gradient_descent_max_iterations = 1000 helper.learning_rate = 0.3 helper.threshold_error = 5 helper.threshold_inlier_count = 15 #helper.max_iterations=400 #100 helper.add_points(lst_points) best_model = helper.run() self.superimpose_circle_over_original_image(file_noisy_circle, best_model) # #Assertions # delta = 15 self.assertAlmostEqual(best_model.X, -2, delta=delta) self.assertAlmostEqual(best_model.Y, -5, delta=delta) self.assertAlmostEqual(best_model.R, 37, delta=delta) pass
def test_run_method_hand_drawn_circle(self): # #get a list of points # folder_script = os.path.dirname(__file__) filename_input = "NoisyCircle-HandDrawn-001.png" file_noisy_line = os.path.join(folder_script, "./data/", filename_input) np_image = skimage.io.imread(file_noisy_line, as_gray=True) lst_points = Util.create_points_from_numpyimage(np_image) # #initialize RansalHelper # helper = RansacCircleHelper() helper.threshold_error = 20 helper.threshold_inlier_count = 5 helper.add_points(lst_points) best_model = helper.run() # #Superimpose the new line over the image # self.superimpose_circle_over_original_image(file_noisy_line, best_model) # #Assertions # delta = 15 self.assertAlmostEqual(best_model.X, 89, delta=delta) self.assertAlmostEqual(best_model.Y, 78, delta=delta) self.assertAlmostEqual(best_model.R, 45, delta=delta)
def run(self, image): print( f"Going to run RANSAC on a patch square with dimension:{self.patchdimension} and stride:{self.patchstride}" ) self._image = image xtractor = ImagePatchExtractor(self.image, self._cropdimension, self._stride) patch_results: PatchResults = xtractor.extract_patches() patchcount_x = patch_results.patch_indices.shape[1] patchcount_y = patch_results.patch_indices.shape[0] good_patches: List[_PatchAnalysis] = list() for x in range(0, patchcount_x): for y in range(0, patchcount_y): patchinfo: PatchInfo = patch_results.get_patch_xy(x, y) img_patchregion = patchinfo.image lst_all_points = Util.create_points_from_numpyimage( img_patchregion) line = self.find_line_using_ransac(lst_all_points, img_patchregion) if (line == None): continue print("Got a line X=%d Y=%d , line=%s" % (x, y, str(line))) #add to a collection of patch regions+ransacline patch_analysis_result = _PatchAnalysis(patchinfo, lst_all_points, line) good_patches.append(patch_analysis_result) pass print("Total interesting patches with lines found = %d" % (len(good_patches))) #you have all the patches that yielded some lines, superimpose on the original for good_patch in good_patches: print(str(good_patch)) self.__superimpose(good_patches)
def test_when_points_are_superimposed_over_image_array_and_saved_the_new_image_must_contain_the_new_points( self): folder_script = os.path.dirname(__file__) filename = "Util_unittest.png" file_noisy_line = os.path.join(folder_script, "./data/", filename) np_image = skimage.io.imread(file_noisy_line, as_gray=True) file_result = os.path.join(folder_script, "../out/", filename) new_points = list() # #Superimpose some points # new_points.append(Point(0, 0)) new_points.append(Point(2, 2)) new_points.append(Point(3, 3)) new_points.append(Point(4, 4)) color_red = 100 color_green = 255 color_blue = 90 np_newimage = Util.superimpose_points_on_image(np_image, new_points, color_red, color_green, color_blue) skimage.io.imsave(file_result, np_newimage) #Read the image back and test the points np_newimage2 = skimage.io.imread(file_result, as_gray=False) height = np_newimage.shape[0] for p in new_points: x = p.X y = height - p.Y - 1 self.assertEqual(np_newimage2[y][x][0], color_red) self.assertEqual(np_newimage2[y][x][1], color_green) self.assertEqual(np_newimage2[y][x][2], color_blue) pass self.assertGreater(len(new_points), 1)
def __generate_xy_from_custom_function(self,image_array): max_distance=self._max_distance_consecutive_points x_start=0 width=image_array.shape[1] height=image_array.shape[0] x_end=width y_origin=height/2 delta_x=width*0.25 #an approx gap to being with x_last=x_start y_last=self.__InvokeAnyFunction(x_last ,width=width,height=height)+y_origin #add a new private functoin and property to decide which type of curve pts_new=list(); while(x_last<x_end): gap=delta_x while(True): x_new=x_last+gap y_new=self.__InvokeAnyFunction(x_new,width=width,height=height)+y_origin dsquare=(x_new-x_last)**2 + (y_new-y_last)**2 d=dsquare**0.5 if (d <= max_distance): pt_new=Point(x_new,y_new) pts_new.append(pt_new) x_last=x_new y_last=y_new break else: gap=gap*0.5 #reduce the gap and try again continue image_result=Util.superimpose_points_on_image(image_array,pts_new, 0,0,0) return image_result pass
def run_image2image(filename): print("Going to fit circle in the file:%s" % (filename)) folder_script = os.path.dirname(__file__) absolute_path = os.path.join(folder_script, "./input/", filename) try: np_image = skimage.io.imread(absolute_path, as_gray=True) lst_all_points = Util.create_points_from_numpyimage(np_image) lrate = 0.3 iterations = 5000 helper = GradientDescentCircleFitting(None, points=lst_all_points, learningrate=lrate, iterations=iterations) start_time = time.time() model: CircleModel = helper.FindBestFittingCircle() print("--- %s seconds for gradient descent algo ---" % (time.time() - start_time)) # #Generate an output image with the model circle overlayed on top of original image # now = datetime.datetime.now() filename_result = ("gradient-descent-%s.png" % (filename)) file_result = os.path.join(folder_script, "./out/", filename_result) #Load input image into array np_image_result = skimage.io.imread(absolute_path, as_gray=True) new_points = CircleModel.generate_points_from_circle(model) np_superimposed = Util.superimpose_points_on_image( np_image_result, new_points, 100, 255, 100) #Save new image skimage.io.imsave(file_result, np_superimposed) print("Results saved to file:%s" % (file_result)) print("------------------------------------------------------------") except Exception as e: tb = traceback.format_exc() print("Error:%s while doing RANSAC on the file: %s , stack=%s" % (str(e), filename, str(tb))) print("------------------------------------------------------------") pass pass
def __superimpose(self, patches): lst_allpoints_from_all_patches = list() image_height = self.image.shape[0] for patch in patches: try: ransac_points: List[Point] = patch.ransacline.points plottable_points = Util.generate_plottable_points_from_projection_of_points( patch.ransacline, patch.ransacline.points) for plottable_point in plottable_points: new_x = patch.patchinfo.topleft.X + plottable_point.X #new_y=patch.patchinfo.topleft.Y + plottable_point.Y #new_y=(image_height-patch.patchinfo.topleft.Y) + plottable_point.Y new_y = (image_height - patch.patchinfo.topleft.Y - self._cropdimension) + plottable_point.Y translated_point = Point(new_x, new_y) lst_allpoints_from_all_patches.append(translated_point) except Exception as e: print("Exception while superimposing %s" % (patch.patchinfo)) pass np_superimposed_patches = Util.superimpose_points_on_image( self._image, lst_allpoints_from_all_patches, 100, 255, 100) skimage.io.imsave(self.OutputImageFile, np_superimposed_patches) pass
def test_generate_plottable_linear_points_between_twopoints(self): pt_start = Point(1, 1) pt_end = Point(20, 20) unit = Vector.create_vector_from_2points(pt_start, pt_end).UnitVector new_points = Util.generate_plottable_points_between_twopoints( pt_start, pt_end) distance_start_end = Point.euclidean_distance(pt_start, pt_end) for new_point in new_points: distance_from_start = Point.euclidean_distance(pt_start, new_point) self.assertTrue(distance_from_start < distance_start_end) new_unit = Vector.create_vector_from_2points(pt_start, new_point).UnitVector dot_product = Vector.dot_product(new_unit, unit) self.assertAlmostEquals(dot_product, 1.0, delta=0.1)
def superimpose_circle_over_original_image(self, original_image_file, circle): np_image = skimage.io.imread(original_image_file, as_gray=True) folder_script = os.path.dirname(__file__) folder_results = os.path.join(folder_script, "../out/") count_of_files = len(os.listdir(folder_results)) filename_results = ("%s.%d.png" % (__name__, count_of_files)) file_result = os.path.join(folder_results, filename_results) new_points = CircleModel.generate_points_from_circle(circle, distance=2) np_superimposed = Util.superimpose_points_on_image( np_image, new_points, 255, 255, 0) skimage.io.imsave(file_result, np_superimposed)
def test_get_extreme_colinear_points(self): pt1 = Point(1, 1) pt2 = Point(2, 2) pt3 = Point(3, 3) pt4 = Point(4, 4) pt5 = Point(5, 5) pt6 = Point(6, 6) lst_randomsequence = [pt6, pt1, pt5, pt2, pt4, pt3] (point1, point2 ) = Util.get_terminal_points_from_coliner_points(lst_randomsequence) results = [point1, point2] self.assertTrue(pt1 in results) self.assertTrue(pt6 in results) pass
def test_create_points_from_numpyimage(self): pass folder_script = os.path.dirname(__file__) filename = "Util_unittest.png" file_noisy_line = os.path.join(folder_script, "./data/", filename) np_image = skimage.io.imread(file_noisy_line, as_gray=True) height = np_image.shape[0] width = np_image.shape[1] lst_points = Util.create_points_from_numpyimage(np_image) np_shape = np_image.shape self.assertEqual(len(lst_points), 3) for pt_any in lst_points: if pt_any.X == 0 and pt_any.Y == height - 1: pass elif (pt_any.X == width - 1 and pt_any.Y == height - 1): pass elif (pt_any.X == width - 1 and pt_any.Y == 0): pass else: raise Exception("Point '%s' was not expected." % (pt_any))
def run_ransac(filename): folder_script = os.path.dirname(__file__) #Images which did not generate good results: # NoisyImage_3.png # NoisyLine-Gaussian-sp-0.80.111.png file_noisy_line = os.path.join(folder_script, "./input/", filename) np_image = skimage.io.imread(file_noisy_line, as_gray=True) # #Iterate over all cells of the NUMPY array and convert to array of Point classes # lst_all_points = Util.create_points_from_numpyimage(np_image) # #begin RANSAC # ransac_maxiterations = 12000 #12000 #6000 #12000 worked well ransac_minpoints = 5 #5 worked well #2 gave very bad results #20 worked well ransac_threshold = 5 #25 worked well for 'NoisyLine-Gaussian-sp-0.80.104.png' 15 and 5 did not #Nothing worked well for 'NoisyLine-Gaussian-sp-0.80.111.png" , tried increasing to 35 #3 for first set when points were much closer #5 produced too much deviation ransac_mininliers = 10 helper = RansacLineHelper() helper.max_iterations = ransac_maxiterations helper.min_points_for_model = ransac_minpoints helper.threshold_error = ransac_threshold helper.threshold_inlier_count = ransac_mininliers helper.add_points(lst_all_points) model = helper.run() #Display the model , you could render over the original picture print("-------------------------------------") print("RANSAC-complete") print("Found model %s , polar=%s" % (model, model.display_polar())) # #Generate an output image with the model line # filename_noextension = no_extension = os.path.splitext(filename)[0] now = datetime.datetime.now() filename_result = ("%s-%s.result.png") % ( filename_noextension, now.strftime("%Y-%m-%d-%H-%M-%S")) file_result = os.path.join(folder_script, "./out/", filename_result) #Load input image into array np_image_result = skimage.io.imread(file_noisy_line, as_gray=True) new_points = LineModel.generate_points_from_line( model, 0, 0, np_image_result.shape[1] - 1, np_image_result.shape[0] - 1) np_superimposed = Util.superimpose_points_on_image(np_image_result, new_points, 100, 255, 100) #Save new image skimage.io.imsave(file_result, np_superimposed)
# num_points = 30 if (random.randint(0, 1) == 0): #generate a line starting from a random point at the bottom edge and going up to a random point on the top edge start_x = random.random() * (img_width - 1) start_y = 0 end_x = random.random() * (img_width - 1) end_y = img_height - 1 else: #generate a line starting from a random point on the left edge and going up to a random point on the right edge start_x = 0 start_y = random.random() * (img_height - 1) end_x = img_width - 1 end_y = random.random() * (img_height - 1) image_with_line = Util.plot_line_2darray(image_noisy, start_x, start_y, end_x, end_y, num_points) image_result = image_with_line # #Save the image to disk # folder_script = os.path.dirname(__file__) folder_results = os.path.join(folder_script, "./out/") count_of_files = len(os.listdir(folder_results)) filename = ("NoisyImage.%d.png" % count_of_files) file_result = os.path.join(folder_script, "./out/", filename) skimage.io.imsave(file_result, image_result) print("Image saved to fileL%s" % (file_result)) #
angles = np.linspace(0, 2.0 * 3.141, num_points) for angle in angles: x = math.sin(angle) * r + centerx y = math.cos(angle) * r + centery newpoint = Point(x, y) pts_on_circle.append(newpoint) return pts_on_circle pass print("Generating noisy circle at center (x,y,radius) (%d,%d,%d)" % (center_x, center_y, radius)) lst_circle = generate_points_for_circle(center_x, center_y, radius, circle_density) image_result = Util.add_points_to_monoimage(image_noisy, lst_circle, use_black=True) # #Save the image to disk # folder_script = os.path.dirname(__file__) folder_results = os.path.join(folder_script, "./out/") count_of_files = len(os.listdir(folder_results)) filename = "NoisyCircle_x_%d_y_%d_r_%d_d_%.2f_sp_%.2f_w_%d_h_%d.%d.png" % ( center_x, center_y, radius, circle_density, salt_pepper_ratio, img_width, img_height, count_of_files) file_result = os.path.join(folder_script, "./out/", filename) skimage.io.imsave(file_result, image_result) print("Image saved to fileL%s" % (file_result))