Exemple #1
0
 def test_generate_points_from_circle_model_center_at_0_0_radius_1(self):
     center_x = 0
     center_y = 0
     radius = 1.0
     model = CircleModel(center_x, center_y, radius)
     points = CircleModel.generate_points_from_circle(model)
     pt: Point
     for pt in points:
         distance_from_center = math.sqrt((pt.X - center_x)**2 +
                                          (pt.Y - center_y)**2)
         self.assertAlmostEqual(distance_from_center, radius, 2)
Exemple #2
0
    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
Exemple #3
0
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
Exemple #4
0
    def test_When_get_inliers_and_3_inliers_and_1_outlier_and_no_exclusion_list(
            self):
        #arrange
        p1 = Point(+1.4, 0.0)
        p2 = Point(+0.0, 1.4)
        p3 = Point(-1.4, 0.0)
        p_outlier = Point(-10, 0)
        list_of_points = list()
        list_of_points.append(p1)
        list_of_points.append(p2)
        list_of_points.append(p3)
        list_of_points.append(p_outlier)

        model = CircleModel(0, 0, 1)
        helper = RansacCircleHelper()
        helper.threshold_error = 0.5
        helper.add_points(list_of_points)

        #act
        inliers, model_score = helper.get_inliers(model, [])

        #assert
        expected_score = ((0.4 / 1.4) + (0.4 / 1.4) + (0.4 / 1.4)) / 3.0
        self.assertAlmostEquals(model_score, expected_score, delta=0.1)
        self.assertEquals(len(inliers), 3)
        self.assertTrue(p1 in inliers)
        self.assertTrue(p2 in inliers)
        self.assertTrue(p3 in inliers)
        self.assertFalse(p_outlier in inliers)
    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
Exemple #6
0
    def test_When_get_inliers_and_all_points_on_circumfrence_and_no_exclusion_list(
            self):
        #arrange
        p1 = Point(+1, 0)
        p2 = Point(+0, 1)
        p3 = Point(-1, 0)
        list_of_points = list()
        list_of_points.append(p1)
        list_of_points.append(p2)
        list_of_points.append(p3)

        model = CircleModel(0, 0, 1)
        helper = RansacCircleHelper()
        helper.threshold_error = 0.2
        helper.add_points(list_of_points)

        #act
        inliers, model_score = helper.get_inliers(model, [])

        #assert
        self.assertAlmostEquals(model_score, 0.0, delta=0.1)
        self.assertEquals(len(inliers), 3)
        self.assertTrue(p1 in inliers)
        self.assertTrue(p2 in inliers)
        self.assertTrue(p3 in inliers)
Exemple #7
0
    def test_generate_model_from_3points_straight_line(self):
        p_0 = Point(0, 33)
        p_1 = Point(9, 30)
        p_2 = Point(12, 29)

        try:
            c1 = CircleModel.GenerateModelFrom3Points(p_0, p_1, p_2)
            self.fail("Expected exception was not thrown")
        except:
            #Exception was expected
            pass
Exemple #8
0
    def test_generate_points_from_circle_model_center_at_0_0_radius_10(self):
        center_x = 0
        center_y = 0
        radius = 100.0
        distance = 5
        model = CircleModel(center_x, center_y, radius)
        points = CircleModel.generate_points_from_circle(model,
                                                         distance=distance)
        pt: Point
        for pt in points:
            distance_from_center = math.sqrt((pt.X - center_x)**2 +
                                             (pt.Y - center_y)**2)
            self.assertAlmostEqual(distance_from_center, radius, 2)

        #compare distance
        for index in range(1, len(points)):
            point1 = points[index]
            point2 = points[index - 1]
            actual_distance = Point.euclidean_distance(point1, point2)
            self.assertAlmostEqual(distance, actual_distance, delta=2)
Exemple #9
0
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
Exemple #10
0
    def test_GenerateModelFrom3pmodels_PassingThrough_1_1_And_0_2_minus1_1(
            self):
        p_1_0 = Point(1, 1)
        p_0_0 = Point(0, 2)
        p_minus1_0 = Point(-1, 1)

        c1 = CircleModel.GenerateModelFrom3Points(p_0_0, p_1_0, p_minus1_0)
        #Assert on radius
        self.assertAlmostEquals(c1.R, 1.0, 1)
        #Assert on center X,Y
        self.assertAlmostEquals(c1.X, 0.0, 1)
        self.assertAlmostEquals(c1.Y, 1.0, 1)
Exemple #11
0
    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)
Exemple #12
0
 def FindBestFittingCircle(self)->CircleModel:
     seed_circle:CircleModel=None
     if (self._modelhint == None):
         seed_circle=self.GenerateSeedCircle()
     else:
         seed_circle=self._modelhint;
     for i in range(0,self._max_iterations):
         #mse=self.ComputeMse(seed_circle)
         derivative_radius,derivative_cx,derivative_cy=self.ComputeDerivativesOfMse(seed_circle)
         new_cx=-1*self._learningrate*derivative_cx + seed_circle.X
         new_cy=-1*self._learningrate*derivative_cy + seed_circle.Y
         new_radius=-1*self._learningrate*derivative_radius + seed_circle.R
         seed_circle=CircleModel(new_cx,new_cy,new_radius)
     return seed_circle
     pass
Exemple #13
0
    def GenerateSeedCircle(self)->CircleModel:
        all_x=list(map(lambda c: c.X, self._points))
        all_y=list(map(lambda c: c.Y, self._points))

        center_x=sum(all_x)/len(all_x)
        center_y=sum(all_y)/len(all_y)
        
        min_x=min(all_x)
        max_x=max(all_x)

        min_y=min(all_y)
        max_y=max(all_y)

        radius=abs(max_x-min_x)/2 + abs(max_y-min_y)/2
        model=CircleModel(center_x, center_y, radius)
        return model
Exemple #14
0
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
Exemple #15
0
    def FindBestFittingCircle(self) -> CircleModel:
        self.compute_mean()
        self.shift_all_points()

        Su = sum(self._shifted_x)
        Sv = sum(self._shifted_y)
        Suu = self.compute_suu()
        Svv = self.compute_svv()
        Suv = self.compute_suv()

        Suuu = self.compute_suuu()
        Svvv = self.compute_svvv()
        Suvv = self.compute_Suvv()
        Svuu = self.compute_Svuu()
        #simulatenous equations
        #   suu*x + suv*y = c
        #   suv*x + svv*y = c
        #   uc=x (center of circle, shifted about mean)
        #   vc=y (center of circle, shifted about mean)
        #   c1 = 1/2 * (Suuu+Suvv)
        #   c2 = 1/2 * (Svvv+Svuu)
        #   a1 = suu
        #   b1 = suv
        #   a2 = suv
        #   b2 = svv

        C1 = (1 / 2) * (Suuu + Suvv)
        C2 = (1 / 2) * (Svvv + Svuu)
        Uc = (C2 * Suv - C1 * Svv) / (Suv * Suv - Suu * Svv)
        Vc = (C1 * Suv - C2 * Suu) / (Suv * Suv - Suu * Svv)
        alpha = Uc**2 + Vc**2 + (Suu + Svv) / len(self._points)

        real_x = self._mean_x + Uc
        real_y = self._mean_y + Vc
        radius = alpha**0.5

        model = CircleModel(real_x, real_y, radius)
        return model
Exemple #16
0
    def run(self) -> CircleModel:
        self.validate_hyperparams()

        #
        #generate trigrams of points - find some temporary model to hold this model
        #
        print("Generating trigrams")
        trigrams = self.generate_trigam_from_points()
        print("Generating trigrams complete. Count=%d" % (len(trigrams)))
        #
        #for ever triagram find circle model
        #   find the circle that passes through those points
        #   Determine model goodness score
        #
        tri: TrigramOfPoints
        lst_trigram_scores = list()
        #
        all_trigram_indices = list(range(0, len(trigrams)))
        fraction = self.sampling_fraction
        random_count = int(len(all_trigram_indices) * fraction)
        random_trigram_indices = random.sample(all_trigram_indices,
                                               random_count)
        #for trig_index in range(0,len(trigrams)):
        progress_count = 0
        count_of_trigrams_with_poor_inliers = 0

        #scope for improvement of performance by multithreading
        #if you use a 200X200 image, with salt peper ration of 0.85 and sample fraction of 0.2 then you can generate ample load to test multi-threading
        #
        for trig_index in random_trigram_indices:
            progress_count += 1
            tri = trigrams[trig_index]
            if (trig_index % 100 == 0):
                print(
                    "PROGRESS:Processing trigram %d of %d, shortlisted=%d  poor inliers=%d"
                    % (progress_count, len(random_trigram_indices),
                       len(lst_trigram_scores),
                       count_of_trigrams_with_poor_inliers))
            try:
                temp_circle = CircleModel.GenerateModelFrom3Points(
                    tri.P1, tri.P2, tri.P3)
            except Exception as e:
                print("Could not generate Circle model. Error=%s" % (str(e)))
                continue

            inliers, goodness_score = self.get_inliers(
                temp_circle, [tri.P1, tri.P2, tri.P3])
            count_inliers = len(inliers)
            if (count_inliers < self.threshold_inlier_count):
                #print("Skipping because of poor inlier count=%d and this is less than threshold=%f)" % (count_inliers, self.threshold_inlier_count))
                count_of_trigrams_with_poor_inliers += 1
                continue
            result = (temp_circle, inliers, tri)

            lst_trigram_scores.append(result)
        #
        #Sort trigrams with lowest error
        #
        sorted_trigram_inliercount = sorted(lst_trigram_scores,
                                            key=lambda x: len(x[1]),
                                            reverse=True)
        if (len(sorted_trigram_inliercount) == 0):
            print(
                "Finished building shortlist of trigrams. No trigrams found. Quitting"
            )
            return
        print(
            "Finished building shortlist of trigrams. Count=%d, Max inlier count=%d"
            % (len(sorted_trigram_inliercount),
               len(sorted_trigram_inliercount[0][1])))
        lst_results_gdescent = list()
        jobs = []
        for index in range(0, len(sorted_trigram_inliercount)):
            t = sorted_trigram_inliercount[index]
            model = t[0]
            inliers = t[1]
            trigram: TrigramOfPoints = t[2]
            new_points = list()
            new_points.extend(inliers)
            new_points.append(trigram.P1)
            new_points.append(trigram.P2)
            new_points.append(trigram.P3)
            new_thread = threading.Thread(
                target=self.find_model_using_gradient_descent2,
                args=(model, new_points, lst_results_gdescent))
            jobs.append(new_thread)

        for j in jobs:
            j.start()

        #Wait for all threads to finish!
        for j in jobs:
            j.join()

        if (len(lst_results_gdescent) == 0):
            return None

        if (len(lst_results_gdescent) == 0):
            return None
        lst_results_gdescent_sortedby_inlier_count = sorted(
            lst_results_gdescent, key=lambda x: len(x[1]), reverse=True)
        max_inliers = len(lst_results_gdescent_sortedby_inlier_count[0][1])
        lst_all_results_with_highest_inlier_count = list(
            filter(lambda x: len(x[1]) >= max_inliers,
                   lst_results_gdescent_sortedby_inlier_count))
        lst_results_best_inlier_best_goodness = sorted(
            lst_all_results_with_highest_inlier_count,
            key=lambda x: (x[2]),
            reverse=False)

        best_model = lst_results_best_inlier_best_goodness[0][0]
        return best_model
Exemple #17
0
 def test_String_Representation_Must_Have_Center_And_Radius(self):
     c1 = CircleModel(100.1, 200.2, 300.3)
     display = str(c1)
     self.assertTrue(display.find("X=100.1") >= 0)
     self.assertTrue(display.find("Y=200.2") >= 0)
     self.assertTrue(display.find("R=300.3") >= 0)
Exemple #18
0
 def test_When_Constructed_All_Properties_Must_Be_Initialized(self):
     c1 = CircleModel(100.1, 200.2, 300.3)
     self.assertAlmostEquals(100.1, c1.X)
     self.assertAlmostEquals(200.2, c1.Y)
     self.assertAlmostEquals(300.3, c1.R)