def detect1(img):
    """
    :param img: Detection based on green filter + center of mass
    :return:
    """
    hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
    mask = cv2.inRange(hsv, HSV_G_low, HSV_G_upp)
    imshow("d1:mask", mask.astype(np.uint8))

    contours, hierarchy = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    """ get every contour point (=APPROX_NONE), so we can use perimeter to
    approximate object center of mass"""

    img_poly = img.copy()
    for contour in contours:
        for point in contour:
            x,y = point[0] # each point is a [[x,y]] element. Just remove wrapping array
            cv2.circle(img_poly, (x,y), 1, (255,0,255))

        ''' center from perimeter '''
        m = cv2.moments(contour)
        m00 = m['m00']
        if m00 > 0:
            cx = int(m['m10']/m00)
            cy = int(m['m01']/m00)
            cv2.circle(img_poly, (cx,cy), 2, (255,0,0), -1)

        ''' center from area '''
        (x,y,w,h) = cv2.boundingRect(contour)
        roi = mask[y:y+h,x:x+w]
        m = cv2.moments(roi)
        cx = int(m['m10']/m['m00'])
        cy = int(m['m01']/m['m00'])
        cv2.circle(img_poly, (x+cx,y+cy), 2, (0,0,255), -1)

    imshow("d1:arrow vertex", img_poly)
def detect3(img, debug=True):
    mark_list = detectGreenArrows(img)
    if len(mark_list) == 0: return

    if debug:
        draw = img.copy()
        for mark in mark_list:
            cv2.drawContours(draw, [mark[2]], -1, (255,0,255))
            cv2.circle(draw, mark[0], 2, (255,255,255), -1)

            (x,y,w,h) = mark[1]
            cv2.rectangle(draw, (x,y), (x+w,y+h), (100,100,100))
            r = int(max(w,h)*YELLOW_SEARCH_AREA_RATIO)
            cv2.circle(draw, mark[0], r, (255,255,255), 1)
        imshow('d3: detectGreenArrows', draw)

    corners_list = np.asarray(detectYellowCorners(img))
    if len(corners_list) == 0: return

    ''' marriage problem'''
    count=0
    for mark in mark_list:
        count+=1; print 'mark[%d]'%(count)
        center = np.asarray(mark[0])
        radius = max(mark[1][2], mark[1][3])
        radius = np.ceil(radius*YELLOW_SEARCH_AREA_RATIO)

        diff = corners_list - center
        dist = np.linalg.norm(diff, axis=1)
        condition = dist < radius
        passing = corners_list[condition] # or condition.nonzero()

        print 'passing corners:',len(passing)

        if debug:
            for point in passing:
                cv2.circle(draw, tuple(point), 2, (255,255,255), -1)
            imshow('d3: detectCorners', draw)

        if len(passing) >= 4:
            sorted = adrian_rosebrock.order_points(passing[0:4])
            scale=200
            ref = np.array([ (0,0), (1,0), (1,1), (0,1) ])*scale

            tf = rectification.calculePerspectiveTransform(sorted, ref)
            img_rect = cv2.warpPerspective(img, tf, (scale,scale))

            if debug:
                for point in passing:
                    cv2.circle(draw, tuple(point), 2, (255,255,255), -1)
                imshow('d3: mark[%d]'%(count), img_rect)
def detect2(img):
    hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
    mask = cv2.inRange(hsv, HSV_Y_low, HSV_Y_upp)
    imshow("d2:mask", mask.astype(np.uint8))

    ''' median blur to drop salt noise
    dilate op. to avoidmedian cutoff '''
    k_cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))
    mask = cv2.dilate(mask, k_cross)
    imshow("d2:dilate", mask)
    mask = cv2.medianBlur(mask, 3)
    imshow("d2:median", mask)

    img_poly = img.copy()

    detected_corners = []
    contours, hierarchy = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    for contour in contours:
        ''' center from perimeter '''
        m = cv2.moments(contour)
        m00 = m['m00']
        if m00 > 0:
            cx = int(m['m10']/m00)
            cy = int(m['m01']/m00)
            cv2.circle(img_poly, (cx,cy), 3, (0,0,255), -1)
            detected_corners.append( (cx,cy) )
    imshow("d2:yellow corners", img_poly)

    ''' group marks '''
    print 'yellow corners detected:', len(detected_corners)
    if len(detected_corners) >= 4:
        take4 = detected_corners[0:4]
        ''' sort it
        use (0,0) distance to known tl and br points'''
        tld = np.Inf
        brd = 0
        img_poly = img_poly.copy()
        for point in take4:
            cv2.circle(img_poly, point, 3, (255,0,0), -1)
            d = np.linalg.norm(point)
            if d<tld:
                tld=d,
                tl=point
            if d>brd:
                brd=d
                br=point
        take4.remove(tl)
        take4.remove(br)

        cv2.line(img_poly, tl, br, (0,255,255))
        imshow("d2:points", img_poly)

        ''' use cross-product to detect side position '''
        for pt in take4:
            v1 = (br[0]-tl[0], br[1]-tl[1], 0)
            v2 = (pt[0]-tl[0], pt[1]-tl[1], 0)
            sign = np.cross(v1,v2)[2]
            if sign < 0:
                ne=pt
            else:
                po=pt

        return
        """ ne or po can be undefined. This is due:
        1) 4 selected points could be bad (impossible configuration)
        2) distance to (0,0) is not 100% stable to perspective nor rotations (like roll)
        """

        sorted = np.array([ tl, po, br, ne ])
        ref = np.array([ (0,0), (0,100), (100,100), (100,0) ])

        tf = rectification.calculePerspectiveTransform(sorted, ref)
        img_rect = cv2.warpPerspective(img, tf, (100,100))

        imshow("d2:rectified", img_rect)