Ejemplo n.º 1
0
    def connectCircles(self):
        """
        Private method.
        Computes a list with connections between circle centres.
        For every couple of centres (a, b) such that a is not b:
               if there's no centre c such that ((dist(a,c) < dist(a,b)) and (dist(c, b) < dist(a, c)))
               then add the vector (a,b) to the connection with the indices of the centres a and b
        self.prepareGraph must be called before this one
        """
        keypoints = self._circles
        circles_dict = {}
        vectors_dict = {}

        subdiv = cv2.Subdiv2D()
        subdiv.initDelaunay(self._bounds)
        for i in range(len(keypoints)):
            keypoint = keypoints[i]
            if not self._noise_circles[i]:  # If the circle i is not a noisy circle
                key = (float(keypoint[0]), float(keypoint[1]))
                circles_dict[key] = i
                subdiv.insert(key)

        triangle_list = subdiv.getTriangleList()
        edge_list = subdiv.getEdgeList()
        # An edge is the coordinates of two points. 1st coordinate = (edge[0], edge[1]), 2nd = (edge[2], edge[3])
        for edge in edge_list:
            pt1 = (edge[0], edge[1])
            pt2 = (edge[2], edge[3])
            if self.checkInBounds(pt1) and self.checkInBounds(pt2):
                vectors_dict[(pt1, pt2)] = geom.vectorize(pt1, pt2)
                vectors_dict[(pt2, pt1)] = geom.vectorize(pt2, pt1)

        for triangle in triangle_list:
            pt1 = (triangle[0], triangle[1])
            pt2 = (triangle[2], triangle[3])
            pt3 = (triangle[4], triangle[5])
            if self.checkInBounds(pt1) and self.checkInBounds(pt2) and self.checkInBounds(pt3):
                dist1 = geom.point_distance(pt1, pt2)
                dist2 = geom.point_distance(pt2, pt3)
                dist3 = geom.point_distance(pt3, pt1)
                max_dist = max(dist1, dist2, dist3)
                if max_dist == dist1:
                    if (pt1, pt2) in vectors_dict and (pt2, pt1) in vectors_dict:
                        vectors_dict.pop((pt1, pt2))
                        vectors_dict.pop((pt2, pt1))
                elif max_dist == dist2:
                    if (pt2, pt3) in vectors_dict and (pt3, pt2) in vectors_dict:
                        vectors_dict.pop((pt2, pt3))
                        vectors_dict.pop((pt3, pt2))
                else:
                    if (pt1, pt3) in vectors_dict and (pt3, pt1) in vectors_dict:
                        vectors_dict.pop((pt3, pt1))
                        vectors_dict.pop((pt1, pt3))
        vectors = []
        indices = []
        for (pt1, pt2) in vectors_dict:
            vectors.append(vectors_dict[(pt1, pt2)])
            indices.append((circles_dict[pt1], circles_dict[pt2]))
        self._original_arc_vectors = vectors
        self._original_arc_indices = indices
Ejemplo n.º 2
0
 def filterConnections(self):
     """
     For every existing connection, check that there's minimum "min_similar_vectors" other vectors with the same
     values (Same value following the threshold). If it's True, keep the connection, otherwise discard it
     """
     filtered_arc_vectors = []
     filtered_arc_indices = []
     if self._min_similar_vectors > len(self._original_arc_vectors):
         raise self._exception
     if len(self._original_arc_vectors) > 0:
         space_tree = KDTree(self._original_arc_vectors)
         for j, connection in enumerate(self._original_arc_vectors):
             nearest_neighbours = space_tree.query(connection, self._min_similar_vectors)[1]
             if (geom.point_distance(connection, self._original_arc_vectors[nearest_neighbours
                                                         [(self._min_similar_vectors - 1)]])) <= self._pixel_error_margin:
                 filtered_arc_vectors.append(connection)
                 filtered_arc_indices.append(self._original_arc_indices[j])
     self._filtered_arc_vectors = filtered_arc_vectors
     self._filtered_arc_indices = filtered_arc_indices
Ejemplo n.º 3
0
    def detectFrontHoles(self, distance, sloped=False, res=DEFAULT_RESOLUTION, tries=1, debug=False):
        """
        :param distance: The distance between the robot and the connect4
        :type distance: float
        :param sloped: True if the connect4 is sloped or in an unknown position
        :type sloped: bool
        :param res: the resolution of the image
        :type res: int
        :param tries: the number of success the algorithm must perform to mark the Connect 4 as detected
        :type tries: int
        :param debug: if True, displays image of the current detection
        :type debug: bool
        Detect the front holes in the next image of the "next_img_func".
        If the connect 4 is not found in one attempt, the whole detection fails (see the 'tries' parameter).
        """
        last_0_0_coord = None
        if res == 640:
            i_res = 2
        else:
            i_res = 1
        for i in range(tries):
            if self.cam_no == -1:
                self.img = self.next_img_func(0, res=i_res)  # We detect the front holes using the top camera
            else:
                self.img = self.next_img_func(self.cam_no, res=i_res)
            self.circles = []
            if not self.front_holes_detection_prepared:
                self.prepareFrontHolesDetection(distance, sloped, res)
            elif self.distance != distance or self.sloped != sloped:
                self.min_radius, self.max_radius = self.computeMinMaxRadius(distance, sloped)
            gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
            gray = cv2.GaussianBlur(gray, (3, 3), 0)
            gray = cv2.medianBlur(gray, 3)

            circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, self.min_dist,
                                       param1=self.param1, param2=self.param2, minRadius=self.min_radius,
                                       maxRadius=self.max_radius)
            if circles is not None:

                self.circles = circles[0]
                self.front_hole_detector.runDetection(self.circles, pixel_error_margin=self.pixel_error_margin,
                                                      img=self.img)
                if debug:
                    img2 = draw_circles(self.img, self.circles)
                    cv2.imshow("Circles detected", img2)
                    cv2.imshow("Original picture", self.img)
                (cur_0_0_coord, cur_1_0_coord) = cv2.perspectiveTransform(
                    np.float32(np.array([self.front_hole_detector.reference_mapping[(0, 0)],
                                         self.front_hole_detector.reference_mapping[(1, 0)]])).reshape(1, -1, 2),
                    self.front_hole_detector.homography).reshape(-1, 2)
                if last_0_0_coord is not None:

                    vertical_max_dist = geom.point_distance(cur_0_0_coord, cur_1_0_coord)
                    # If the distance between two board detection exceed 3/4 * distance between two rows,
                    #    the detection is considered as unstable because two different grids have been detected
                    if geom.point_distance(cur_0_0_coord, last_0_0_coord) > 0.75 * vertical_max_dist:
                        raise FrontHolesGridNotFoundException(
                            "The detection was not stable as it detected two different boards during {0} attempt(s)"
                                .format(str(i)))
                last_0_0_coord = cur_0_0_coord
                if debug:
                    cv2.imshow("Perspective", self.front_hole_detector.getPerspective())
                    if cv2.waitKey(1) == 27:
                        print "Esc pressed : exit"
                        cv2.destroyAllWindows()
                        raise FrontHolesGridNotFoundException("The detection was interrupted")
            else:
                raise FrontHolesGridNotFoundException(
                    "The detection was not stable as it lost the board after {0} attempt(s)".format(str(i)))