def test_distance_of_0_0_from_flat_line_yintercept_is_zero(self): x = LineModel(0, 1, -3) test_point = Point(0, 0) distance_actual = x.compute_distance(test_point) distance_expected = 3 self.assertEqual(distance_actual, distance_expected) pass
def test_distance_of_origin_from_slope_45degrees_yintercept_is_zero(self): x = LineModel(-1, 1, 0) test_origin = Point(0, 0) distance_actual = x.compute_distance(test_origin) distance_expected = 0 self.assertEqual(distance_actual, distance_expected) pass
def test_distance_of_1_0_from_slope_45degrees_yintercept_is_zero(self): x = LineModel(-1, 1, 0) test_point = Point(1, 0) distance_actual = x.compute_distance(test_point) distance_expected = 1 / math.sqrt(2) self.assertEqual(distance_actual, distance_expected) pass
def test_x_y_intercept_45_degrees_1_0(self): line = LineModel(-1, 1, 1) xintercept_actual = line.xintercept() xintercept_expected = 1 yintercept_actual = line.yintercept() yintercept_expected = -1 self.assertEqual(xintercept_actual, xintercept_expected) self.assertEqual(yintercept_actual, yintercept_expected)
def test_x_y_intercept_90_degrees_5_inf(self): line = LineModel(1, 0, -5) xintercept_actual = line.xintercept() xintercept_expected = 5 yintercept_actual = line.yintercept() yintercept_expected = math.inf self.assertEqual(xintercept_actual, xintercept_expected) self.assertEqual(yintercept_actual, yintercept_expected)
def test_x_y_intercept_0_degrees_inf_5(self): line = LineModel(0, 1, -5) xintercept_actual = line.xintercept() xintercept_expected = math.inf yintercept_actual = line.yintercept() yintercept_expected = 5 self.assertEqual(xintercept_actual, xintercept_expected) self.assertEqual(yintercept_actual, yintercept_expected)
def test_generate_points_from_line_90_degrees_passing_through_5_0(self): line = LineModel(1, 0, -5) x1 = 20 x2 = 40 y1 = 10 y2 = 30 new_points = LineModel.generate_points_from_line(line, x1, y1, x2, y2) for p in new_points: print("Testing point=%s" % (p)) self.assertTrue(p.Y >= y1) self.assertTrue(p.Y <= y2)
def test_generate_points_from_line_45_degrees_passing_through_0_0(self): line = LineModel(-1, 1, 0) x1 = 20 x2 = 40 y1 = 10 y2 = 30 new_points = LineModel.generate_points_from_line(line, x1, y1, x2, y2) for p in new_points: print("Testing point=%s" % (p)) self.assertTrue(p.X >= x1) self.assertTrue(p.X <= x2)
def compute_average_distance(self, model: LineModel, points: list) -> float: lst_distances = list() for p in points: distance = model.compute_distance(p) lst_distances.append(distance) mean = statistics.mean(lst_distances) return mean
def create_model(self, points: list) -> LineModel: mean_x = 0 mean_y = 0 for p in points: mean_x += p.X mean_y += p.Y mean_x = mean_x / len(points) mean_y = mean_y / len(points) slope_numerator = 0 slope_denominator = 0 slope = 0 #use the formula for least squares for p in points: slope_numerator += (p.X - mean_x) * (p.Y - mean_y) slope_denominator += (p.X - mean_x) * (p.X - mean_x) if (math.fabs(slope_denominator) < 0.001): #perpendicular line x_intercept = mean_x #equation (1)x + (0)y + (-xintercept) + 1 vertical_line_a = 1 vertical_line_b = 0 vertical_line_c = -x_intercept model = LineModel(vertical_line_a, vertical_line_b, vertical_line_c) return model slope = slope_numerator / slope_denominator y_intercept = mean_y - (slope * mean_x) line_a = slope line_b = -1 line_c = y_intercept # standard form of line equation # ------------------------------ # y=mx+c # mx - y + c=0 # ax + by + c=0 # slope= -a/b # yint= -c/b # model = LineModel(line_a, line_b, line_c) return model
def test_add_points_to_line(self): model = LineModel.create_line_from_2points(0, 0, 100, 100) test_point1 = Point(1, 0) test_point2 = Point(2, 0) model.points.append(test_point1) model.points.append(test_point2) self.assertTrue(test_point1 in model.points) self.assertTrue(test_point2 in model.points) self.assertTrue(len(model.points) == 2)
def test_projection_of_points_on_line_with_slope_45degrees_through_origin( self): line = LineModel(-1, 1, 0) test_point1 = Point(4, 0) expected_projected1 = Point(2, 2) test_point2 = Point(0, 4) expected_projected2 = Point(2, 2) lst_inputs = [test_point1, test_point2] lst_expected = [expected_projected1, expected_projected2] lst_actual = LineModel.compute_projection_of_points(line, lst_inputs) for index in range(0, len(lst_inputs)): actual = lst_actual[index] expected = lst_expected[index] self.assertAlmostEqual(actual.X, expected.X, 0.1) self.assertAlmostEqual(actual.Y, expected.Y, 0.1)
def compute_mean_squared_distance(self, model: LineModel, points: list) -> float: lst_distances = list() for p in points: distance = model.compute_distance(p) lst_distances.append(distance**2) sum_of_squared_distances = sum(lst_distances) sqroot = sum_of_squared_distances**0.5 mean = sqroot / len(lst_distances) return mean
def test_create_line_from_start_and_end_vertical_line(self): start_x = 1 start_y = 5 end_x = 1 end_y = 25 model = LineModel.create_line_from_2points(start_x, start_y, end_x, end_y) expected_B = 0 expected_x_intercept = start_x self.assertAlmostEqual(model.B, 0) self.assertAlmostEqual(model.C / model.A, -expected_x_intercept)
def get_inliers_from_model(self, model: LineModel, points_old_inliers: list) -> list: lst_inliers = list() for p in self.points: if ((p in points_old_inliers) == True): continue distance_from_model: float = model.compute_distance(p) if (distance_from_model > self.threshold_error): continue lst_inliers.append(p) return lst_inliers
def test_generate_points_at_regular_intervals_stline(self): start_x = 0 start_y = 1 end_x = 10 end_y = 11 model = LineModel.create_line_from_2points(start_x, start_y, end_x, end_y) slope = -model.A / model.B yintercept = -model.C / model.B gap = 5 new_points = LineModel.generate_points_at_regular_intervals_stline( start_x, start_y, end_x, end_y, gap) count_of_new_points = len(new_points) self.assertTrue(count_of_new_points > 0) self.assertTrue(count_of_new_points < 4) for new_point in new_points: new_x = new_point.X new_y = new_point.Y expected_y = slope * new_x + yintercept self.assertAlmostEqual(new_y, expected_y)
def test_create_line_from_start_and_end_horizontal_line(self): start_x = 0 start_y = 1 end_x = 1 end_y = 2 model = LineModel.create_line_from_2points(start_x, start_y, end_x, end_y) #equation ax+by+c=0 #slope=-a/b #yinter=-c/b expected_slope = 1 expected_y_intercept = 1 self.assertAlmostEqual(model.A / model.B, -expected_slope) self.assertAlmostEqual(model.C / model.B, -expected_y_intercept)
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_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)
def test_display_polar(self): line = LineModel(-1, 1, 1) s = line.display_polar() print(s)
def test_construction(self): x = LineModel(100, 200, 300) self.assertEqual(x.A, 100) self.assertEqual(x.B, 200) self.assertEqual(x.C, 300) pass