コード例 #1
0
    def predict_corners(self, new_corners):
        '''
        If in new_corners are Nones then this function tries to predict where
        not found corners are
        @param new_corners:
        '''
        db.db_break()
        new_corners = self._improve_corners(new_corners)
        self.validate_corners(new_corners)
        corners = filter(lambda x: x is not None, new_corners)
        def cmp(x, y):
            if  x.similarity > y.similarity:
                return  1
            else: return - 1
        corners = sorted(corners, cmp)
        self.avg_sim = reduce(lambda x, y: x + y.similarity, corners, 0)
        while len(corners) > 0:
            ncorners = list(new_corners)
            self.avg_sim /= len(corners)
            self._predict_corners(ncorners)
            if all(ncorners):
                if cv.CheckContourConvexity([x.p for x in ncorners]) == 1:
                    le = len(ncorners)
                    for i,c in enumerate(ncorners):
                        n= (i+1)%le
                        ncorners[n].prev = c.p
                        c.next = ncorners[n].p
                    for c in ncorners:c.measure()
                    return ncorners
            last = corners[-1]
            new_corners[last.id] = None
            self.avg_sim = self.avg_sim * len(corners) - last.similarity
            corners.remove(last)

        return None
コード例 #2
0
def is_square(contour):
    """
    Squareness checker

    Square contours should:
        -have 4 vertices after approximation, 
        -have relatively large area (to filter out noisy contours)
        -be convex.
        -have angles between sides close to 90deg (cos(ang) ~0 )
    Note: absolute value of an area is used because area may be
    positive or negative - in accordance with the contour orientation
    """

    area = math.fabs( cv.ContourArea(contour) )
    isconvex = cv.CheckContourConvexity(contour)
    s = 0
    if len(contour) == 4 and area > 1000:
        for i in range(1, 4):
            # find minimum angle between joint edges (maximum of cosine)
            pt1 = contour[i]
            pt2 = contour[i-1]
            pt0 = contour[i-2]

            t = math.fabs(angle(pt0, pt1, pt2))
            if s <= t:s = t

        # if cosines of all angles are small (all angles are ~90 degree) 
        # then its a square
        if s < 0.3:return True

    return False       
コード例 #3
0
    def _check_rectangle(self, rect, scale_factor):
        '''
        Checks if rectangle is a good square marker
        @param rect:
        '''
        if cv.CheckContourConvexity(rect) != 1:
            return False, 'conv'
        area = abs(cv.ContourArea(rect))
        if area < SQ_SIZE:
            return False, 'area %d' % area

        orientation, code = self._decode_rect(rect)

        if orientation == self.FAILED:
            return False, 'no_corner: ' + str(code)
        else:
            return True, (code, orientation)
コード例 #4
0
    def __init__(self, poly, depth):
        self.depth = depth
        self.points = []
        self.angles = [.0]
        self.touching = []
        self.children = []
        self.parents = []
        xavg = []
        yavg = []
        xmin = ymin = xmax = ymax = None

        for j in range(poly.total):
            ptr = cv.GetSeqElem(poly, j)
            #point = ctypes.cast(_ptr, cv.Point.CAST )
            #x = point.contents.x; y = point.contents.y
            point = cv.Point(pointer=ptr, cast=True)
            x = point.x
            y = point.y
            p = Point(x, y)

            if self.points:
                a = math.degrees(self.points[-1].angle(p))
                self.angles.append(a)

            self.points.append(p)
            xavg.append(x)
            yavg.append(y)
            if j == 0:
                xmin = xmax = x
                ymin = ymax = y
            else:
                if x < xmin: xmin = x
                if x > xmax: xmax = x
                if y < ymin: ymin = y
                if y > ymax: ymax = y

        self.avariance = .0
        self.avariance_points = [.0, .0]
        if self.angles:
            print(self.angles)
            prev = self.angles[0]
            for a in self.angles[1:]:
                v = abs(prev - a)
                self.avariance_points.append(v)
                self.avariance += v
                prev = a
            #print 'variance', self.avariance
            #print 'variance-points', self.avariance_points
            #print 'len len', len(self.points), len(self.avariance_points)

        n = len(self.points)

        self.weight = (sum(xavg) / float(n), sum(yavg) / float(n))
        self.width = xmax - xmin
        self.height = ymax - ymin
        self.center = (int(xmin + (self.width / 2)),
                       int(ymin + (self.height / 2)))
        self.rectangle = ((xmin, ymin), (xmax, ymax))

        self.dwidth = xmax - xmin
        self.dheight = ymax - ymin
        self.dcenter = (xmin + (self.dwidth / 2), ymin + (self.dheight / 2))
        self.drectangle = ((xmin, ymin), (xmax, ymax))

        self.defects = []
        self.center_defects = None

        self.convex = cv.CheckContourConvexity(poly)
        if not self.convex:
            T = 80
            dxavg = []
            dyavg = []
            hull = cv.ConvexHull2(poly, self.storage_hull, 1, 0)
            defects = cv.ConvexityDefects(poly, hull, self.storage_defects)

            n = defects.total
            for j in range(n):
                D = cv.ConvexityDefect(pointer=cv.GetSeqElem(defects, j),
                                       cast=True)
                s = D.start.contents
                e = D.end.contents
                d = D.depth_point.contents
                start = (s.x, s.y)
                end = (e.x, e.y)
                depth = (d.x, d.y)

                ## ignore large defects ##
                if abs(end[0] -
                       depth[0]) > T or abs(end[1] - depth[1]) > T or abs(
                           start[0] - end[0]) > T or abs(start[1] -
                                                         end[1]) > T:
                    continue

                dxavg.append(depth[0])
                dyavg.append(depth[1])
                self.defects.append((start, end, depth))

            xmin = ymin = 999999
            xmax = ymax = -1
            if self.defects:
                n = len(self.defects)
                self.center_defects = (int(sum(dxavg) / float(n)),
                                       int(sum(dyavg) / float(n)))
                for j, f in enumerate(self.defects):
                    s, e, d = f
                    if s[0] < xmin: xmin = s[0]
                    if e[0] < xmin: xmin = e[0]
                    if s[0] > xmax: xmax = s[0]
                    if e[0] > xmax: xmax = e[0]
                    if s[1] < ymin: ymin = s[1]
                    if e[1] < ymin: ymin = e[1]
                    if s[1] > ymax: ymax = s[1]
                    if e[1] > ymax: ymax = e[1]

                self.dwidth = xmax - xmin
                self.dheight = ymax - ymin
                self.dcenter = (xmin + (self.dwidth / 2),
                                ymin + (self.dheight / 2))
                self.drectangle = ((xmin, ymin), (xmax, ymax))

        cv.ClearMemStorage(self.storage_hull)
        cv.ClearMemStorage(self.storage_defects)
コード例 #5
0
def findSquares4(img, storage):
    N = 11
    sz = (img.width & -2, img.height & -2)
    timg = cv.CloneImage(img)
    # make a copy of input image
    gray = cv.CreateImage(sz, 8, 1)
    pyr = cv.CreateImage((sz.width / 2, sz.height / 2), 8, 3)
    # create empty sequence that will contain points -
    # 4 points per square (the square's vertices)
    squares = cv.CreateSeq(0, sizeof_CvSeq, sizeof_CvPoint, storage)
    squares = CvSeq_CvPoint.cast(squares)

    # select the maximum ROI in the image
    # with the width and height divisible by 2
    subimage = cv.GetSubRect(timg, cv.Rect(0, 0, sz.width, sz.height))

    # down-scale and upscale the image to filter out the noise
    cv.PyrDown(subimage, pyr, 7)
    cv.PyrUp(pyr, subimage, 7)
    tgray = cv.CreateImage(sz, 8, 1)
    # find squares in every color plane of the image
    for c in range(3):
        # extract the c-th color plane
        channels = [None, None, None]
        channels[c] = tgray
        cv.Split(subimage, channels[0], channels[1], channels[2], None)
        for l in range(N):
            # hack: use Canny instead of zero threshold level.
            # Canny helps to catch squares with gradient shading
            if (l == 0):
                # apply Canny. Take the upper threshold from slider
                # and set the lower to 0 (which forces edges merging)
                cv.Canny(tgray, gray, 0, thresh, 5)
                # dilate canny output to remove potential
                # holes between edge segments
                cv.Dilate(gray, gray, None, 1)
            else:
                # apply threshold if l!=0:
                #     tgray(x, y) = gray(x, y) < (l+1)*255/N ? 255 : 0
                cv.Threshold(tgray, gray, (l + 1) * 255 / N, 255,
                             cv.CV_THRESH_BINARY)

            # find contours and store them all as a list
            count, contours = cv.FindContours(gray, storage, sizeof_CvContour,
                                              cv.CV_RETR_LIST,
                                              cv.CV_CHAIN_APPROX_SIMPLE,
                                              (0, 0))

            if not contours:
                continue

            # test each contour
            for contour in contours.hrange():
                # approximate contour with accuracy proportional
                # to the contour perimeter
                result = cv.ApproxPoly(contour, sizeof_CvContour, storage,
                                       cv.CV_POLY_APPROX_DP,
                                       cv.ContourPerimeter(contours) * 0.02, 0)
                # square contours should have 4 vertices after approximation
                # relatively large area (to filter out noisy contours)
                # and be convex.
                # Note: absolute value of an area is used because
                # area may be positive or negative - in accordance with the
                # contour orientation
                if (result.total == 4 and abs(cv.ContourArea(result)) > 1000
                        and cv.CheckContourConvexity(result)):
                    s = 0
                    for i in range(5):
                        # find minimum angle between joint
                        # edges (maximum of cosine)
                        if (i >= 2):
                            t = abs(
                                angle(result[i], result[i - 2], result[i - 1]))
                            if s < t:
                                s = t
                    # if cosines of all angles are small
                    # (all angles are ~90 degree) then write quandrange
                    # vertices to resultant sequence
                    if (s < 0.3):
                        for i in range(4):
                            squares.append(result[i])

    return squares