Exemplo n.º 1
0
def contour_points(largest_contour, image):
    hull = cv2.convexHull(largest_contour)
    drawing = np.zeros(image.shape, np.uint8)
    cv2.drawContours(drawing, [largest_contour], 0, (0, 255, 0), 2)
    #cv2.drawContours(drawing, [hull], 0, (0, 0, 255), 3)
    hull = cv2.convexHull(largest_contour, returnPoints=False)
    defects = cv2.convexityDefects(largest_contour, hull)
    # draw furthest left,top and right point
    point_list = []
    # detect fingers middle defects
    k = 1
    for i in range(defects.shape[0]):
        s, e, f, d = defects[i, 0]
        start = tuple(largest_contour[s][0])
        end = tuple(largest_contour[e][0])
        far = tuple(largest_contour[f][0])
        angle = calculateAngle(far, start, end)
        if d > 10000 and angle <= math.pi / 2:
            if (k == 1):
                cv2.circle(drawing, start, 8, (147, 20, 255), -1)
                point_list.append(start)
            cv2.circle(drawing, end, 8, (147, 20, 255), -1)
            point_list.append(far)
            point_list.append(end)
            cv2.circle(drawing, far, 5, [255, 0, 0], -1)
            k += 1

    return drawing, point_list
Exemplo n.º 2
0
def count(thresholded, segmented):
    # find the convex hull of the segmented hand region
    hull = cv2.convexHull(segmented, returnPoints=False)
    defects = cv2.convexityDefects(segmented, hull)

    # Bascially indicates how much finger is visible in screen
    countDefects = 0

    for i in range(defects.shape[0]):
        # Returns start point, end point, farthest point, approximate distance to farthest point
        s, e, f, d = defects[i, 0]
        start = tuple(segmented[s][0])
        end = tuple(segmented[e][0])
        far = tuple(segmented[f][0])

        a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
        b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2)
        c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2)

        # This angle is used while hand is moving around
        angle = (math.acos((b**2 + c**2 - a**2) / (2 * b * c)) * 180) / 3.14

        # If angle < 90 degree then treat as a finger
        if angle <= 90:
            countDefects += 1

    return (countDefects + 1)
Exemplo n.º 3
0
def func(ImgNo, defThr=127):
    img = cv2.imread(impDef.select_img(ImgNo))
    img1 = img.copy()
    imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    ret, thr = cv2.threshold(imgray, defThr, 255, 0)
    contours, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    cnt = contours[0]

    # Convex Hull만을 찾기 위해 contours 1개만을 인자로 입력
    hull = cv2.convexHull(cnt)
    cv2.drawContours(img, [hull], 0, (0, 0, 255), 2)

    # Convexity Defects를 찾기위해 2번째 인자로 returnPoints = False를 지정해야 함
    # (cnt, returnPoints = False) 인자로 주어진 cnt를 분석하여 Convex Hull을 이루는 모든 좌표를 리턴하는 것이 아니라,
    # 원래 Contour와 Convex Hull이 만나는 부부의 Contour 인덱스를 리턴함.
    # 즉 별의 꼭지점에 해당하는 5군데를 리턴함.
    hull = cv2.convexHull(cnt, returnPoints=False)
    defects = cv2.convexityDefects(cnt, hull)

    for i in range(defects.shape[0]):
        sp, ep, fp, dist = defects[i, 0]
        start = tuple(cnt[sp][0])
        end = tuple(cnt[ep][0])
        farthest = tuple(cnt[fp][0])

        cv2.circle(img, farthest, 5, (0, 255, 0), -1)

    cv2.imshow('defects', img)
    impDef.close_window()
Exemplo n.º 4
0
    def convexityDetectionImg(self):
        try:
            img = cv2.imread(self.filename)
            img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            ret, thresh = cv2.threshold(img_gray, 127, 255, 0)
            contours, hierarchy = cv2.findContours(thresh, 2, 1)
            cnt = contours[0]

            hull = cv2.convexHull(cnt, returnPoints=False)
            defects = cv2.convexityDefects(cnt, hull)

            for i in range(defects.shape[0]):
                s, e, f, d = defects[i, 0]
                start = tuple(cnt[s][0])
                end = tuple(cnt[e][0])
                far = tuple(cnt[f][0])
                cv2.line(img, start, end, [0, 255, 0], 2)
                cv2.circle(img, far, 5, [0, 0, 255], -1)

            cv2.imwrite('img/dist/disbukey.png', img,
                        [cv2.IMWRITE_JPEG_QUALITY, 100])
            cv2.waitKey(0)
            cv2.destroyAllWindows()
        except:
            pass
Exemplo n.º 5
0
def find_second_contours(base_out, output):
    contours = cv2.findContours(base_out, cv2.RETR_CCOMP,
                                cv2.CHAIN_APPROX_TC89_KCOS)
    contours_map = {}
    for idx in range(0, len(contours[1])):
        area = cv2.contourArea(contours[1][idx])
        contours_map[idx] = {'area': area, 'contour': contours[1][idx]}
        pass

    contours_map = sorted(contours_map.items(), key=lambda d: d[1]['area'])
    for idx in range(1, 3):
        id = -idx
        max_contours = contours_map[id][1]['contour']
        hulls = cv2.convexHull(max_contours, returnPoints=False)
        pts_index = cv2.convexityDefects(contour=max_contours,
                                         convexhull=hulls)
        pts = []
        for v in pts_index:
            pts.append(max_contours[v[0][0]])
            pts.append(max_contours[v[0][1]])

        ndpts = np.zeros((len(pts), 1, 2), np.int32)
        for idx in range(0, len(pts)):
            ndpts[idx] = pts[idx]

        cv2.drawContours(output, ndpts, -1, (0, 255, 0), cv2.FILLED,
                         cv2.LINE_AA)

    return output
Exemplo n.º 6
0
def ConvexHull_Cal(contour):

    IsTriangle = lambda a, b, c: a + b > c and a + c > b and b + c > a  #任意两边和必须大于第三边

    point_list = []
    convex_angle_ls = []
    concave_angle_ls = []

    epsilon = 0.003 * cv2.arcLength(contour, True)
    contour = cv2.approxPolyDP(contour, epsilon, True)  #轮廓近似,Douglas-Peucker算法
    hull = cv2.convexHull(contour, returnPoints=False)
    defects = cv2.convexityDefects(contour, hull)
    _, radius = cv2.minEnclosingCircle(contour)

    if defects is not None:
        for i in range(defects.shape[0]):
            s, e, f, _ = defects[i, 0]
            sta = tuple(contour[s][0])
            end = tuple(contour[e][0])
            far = tuple(contour[f][0])
            point_list.append([sta, far, end])

    #下面的角边标示含义见文件夹里的图片说明
    if len(point_list) >= 2:
        for it_1, it_2 in zip(point_list, point_list[1:] + point_list[:1]):
            CA = scfun.Eucledian_Distance(it_1[1], it_1[2])  #far to end
            AB = scfun.Eucledian_Distance(it_1[2], it_2[1])  #end to next far
            #凸包的角度
            if radius <= CA + AB < 2 * radius:
                BC = scfun.Eucledian_Distance(it_1[1],
                                              it_2[1])  #far to 2nd far,为底边
                if IsTriangle(CA, AB, BC):
                    angle = acos((CA**2 + AB**2 - BC**2) / (2 * CA * AB))
                    convex_angle_ls.append(angle)
            #凹陷的角度
            DC = scfun.Eucledian_Distance(it_1[0], it_1[1])  #sta to far
            if radius <= DC + CA < 2 * radius:
                DA = scfun.Eucledian_Distance(it_1[0],
                                              it_1[2])  #sta to end,为底边
                if IsTriangle(DC, CA, DA):
                    angle = acos((CA**2 + DC**2 - DA**2) / (2 * CA * DC))
                    concave_angle_ls.append(angle)

        convex_angle = [x for x in convex_angle_ls
                        if pi / 18 <= x <= pi / 6]  #凸包角度:10度至30度
        convex_len = len(convex_angle)
        concave_angle = [
            x for x in concave_angle_ls if pi / 18 <= x <= pi / 3.5
        ]
        concave_len = len(concave_angle)

        result = [convex_len, concave_len]

    else:
        result = [0, 0]

    return result
Exemplo n.º 7
0
def Gestures_Detect(hand, sample_list, fourier_des_ls):
    ndefects = 0

    sign, large_cout = Find_Contour(hand, sample_list, fourier_des_ls)
    if sign == False:
        ndefects = 11  #返回contours为空的信息,只作调试用
        center = tuple([a // 2 for a in reversed(hand.shape)])  #返回图像的中心坐标
        return hand, ndefects, center

    black2 = np.ones(hand.shape, np.uint8)  #创建黑色幕布
    cv2.drawContours(black2, large_cout, -1, (255, 255, 255), 2)  #绘制白色轮廓
    cv2.imshow('large_cout', black2)

    hull = cv2.convexHull(large_cout, returnPoints=False)
    defects = cv2.convexityDefects(large_cout, hull)
    _, radius = cv2.minEnclosingCircle(large_cout)

    if defects is not None:
        for i in range(defects.shape[0]):
            s, e, f, _ = defects[i, 0]
            sta = tuple(large_cout[s][0])
            end = tuple(large_cout[e][0])
            far = tuple(large_cout[f][0])
            B = scfun.Eucledian_Distance(sta, far)
            C = scfun.Eucledian_Distance(end, far)
            #过滤掉角边太短的角
            if B + C > radius:
                A = scfun.Eucledian_Distance(sta, end)  #底边
                angle = acos((B**2 + C**2 - A**2) / (2 * B * C))

                if angle <= pi / 2.5:
                    ndefects += 1
    else:
        ndefects = 12
    '''
    test=scfun.Fourier_Descriptor(large_cout[:,0,:],Normalize=True)
    similar=scfun.Eucledian_Distance(test,fourier_des_ls[0])
    print('{:.5f}  {:.5f}'.format(similar,log(similar)))
    '''
    M = cv2.moments(large_cout)
    center = (int(M['m10'] / M['m00']), int(M['m01'] / M['m00']))  #手部的质心坐标

    x, y, w, h = cv2.boundingRect(large_cout)

    hand = cv2.cvtColor(hand, cv2.COLOR_GRAY2BGR)  #将灰度图像转换为BGR以显示绿色方框
    hand = cv2.rectangle(hand, (x, y), (x + w, y + h), (0, 255, 0), 2)

    return hand, ndefects, center
Exemplo n.º 8
0
def calculateFingers(max_contour, drawing, img):
    hull = cv2.convexHull(max_contour, returnPoints=False)
    if len(hull) > 3:
        defects = cv2.convexityDefects(max_contour, hull)
        if type(defects) != type(None):
            cnt = 0
            for i in range(defects.shape[0]):  # calculate the angle
                s, e, f, _ = defects[i][0]
                start = tuple(max_contour[s][0])
                end = tuple(max_contour[e][0])
                far = tuple(max_contour[f][0])
                angle = calculateAngle(far, start, end)

                if angle <= math.pi / 2:
                    cnt += 1
                    cv2.circle(drawing, far, 8, [211, 84, 0], -1)
            return cnt
    return 0
Exemplo n.º 9
0
def contour_points(largest_contour, image):
    hull = cv2.convexHull(largest_contour)
    drawing = image
    cv2.drawContours(drawing, [hull], 0, (0, 0, 255), 3)
    hull = cv2.convexHull(largest_contour, returnPoints=False)
    defects = cv2.convexityDefects(largest_contour, hull)
    # draw furthest left,top and right point
    point_list = []
    # detect fingers middle defects
    k = 1
    deffect_count = 0
    if defects is not None:
        for i in range(defects.shape[0]):
            s, e, f, d = defects[i, 0]
            start = tuple(largest_contour[s][0])
            end = tuple(largest_contour[e][0])
            far = tuple(largest_contour[f][0])
            angle = calculateAngle(far, start, end)

            if d > 20000 and angle <= math.pi / 2:
                #if d > 70000 and angle <= math.pi/2:
                #print(d)
                if (k == 1):
                    '''
                    cv2.circle(drawing, start, 30, (147, 20, 255), -1)
                    point_list.append(start)
                cv2.circle(drawing, end, 30, (147, 20, 255), -1)
                cv2.circle(drawing,far,30,[255,0,0],-1)
                '''
                    cv2.circle(drawing, start, 10, (147, 20, 255), -1)
                    point_list.append(start)
                cv2.circle(drawing, end, 10, (147, 20, 255), -1)
                cv2.circle(drawing, far, 10, [255, 0, 0], -1)

                k += 1
                deffect_count += 1
        #drawing = cv2.putText(drawing, str(deffect_count), (1800, 200), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, 5 ,(0,0,255), 10, cv2.LINE_AA)   #AVS
        drawing = cv2.putText(drawing, str(deffect_count), (650, 150),
                              cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, 5, (0, 0, 255),
                              10, cv2.LINE_AA)
    return drawing, point_list, deffect_count
Exemplo n.º 10
0
def detectGesture(contours, res, hull):
    cnt = 0
    if len(hull) > 3:
        defects = cv.convexityDefects(res, hull)
        if type(defects) != type(None):  # avoid crashing.   (BUG not found)
            for i in range(defects.shape[0]):  # calculate the angle
                s, e, f, d = defects[i][0]
                start = tuple(res[s][0])
                end = tuple(res[e][0])
                far = tuple(res[f][0])
                a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
                b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2)
                c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2)
                angle = math.acos(
                    (b**2 + c**2 - a**2) / (2 * b * c))  # cosine theorem
                if angle <= math.pi / 2:  # angle less than 90 degree, treat as fingers
                    cnt += 1
            if cnt == 0:
                hhArea, ratio = calculateAreas(contours)
                if ratio > 0.9:  #extra verification
                    if hhArea < 17500:
                        return ("fist")
                    if hhArea > 17500:
                        return ("palm")
                if ratio < 0.8 and hhArea > 22000:
                    return ("call")
                else:
                    return (cnt + 1)
            elif cnt == 1:
                hhArea, ratio = calculateAreas(contours)
                if ratio > 0.65 and hhArea > 23000:
                    return ("vulcan")
                return (cnt + 1)
            elif cnt == 2:
                hhArea, ratio = calculateAreas(contours)
                if ratio < 0.7 and hhArea > 29000:
                    return ("rock")
                return (cnt + 1)
            else:
                return (cnt + 1)
Exemplo n.º 11
0
def compute_convex_hull(contours, max_contour_index, PATH):
    # Convex Hull
    for subdir, dirs, files in os.walk(PATH):
        i = 0
        for file in files:
            file_path = subdir + os.sep + file
            img = cv2.imread(file_path, 1)
            blurred_img = apply_gaussian_blurring(img, 9, 9)
            grayscale_img = cv2.cvtColor(blurred_img, cv2.COLOR_BGR2GRAY)
            _, binary_img = cv2.threshold(src=grayscale_img,
                                          thresh=50,
                                          maxval=255,
                                          type=cv2.THRESH_BINARY)
            contours, hierachy = cv2.findContours(image=binary_img,
                                                  mode=cv2.RETR_TREE,
                                                  method=cv2.CHAIN_APPROX_NONE)
            max_contour_index = get_max_contour(contours=contours)
            hull = cv2.convexHull(contours[max_contour_index],
                                  returnPoints=True)
            if (i < 5):
                cv2.drawContours(img, [hull], 0, (255, 0, 0), 1)
                # cv2.imshow('Convex Hull_{}'.format(i), img)
            i += 1

    # Convexity defects
    hull_ints = cv2.convexHull(contours[max_contour_index], returnPoints=False)
    hull_points = cv2.convexHull(contours[max_contour_index],
                                 returnPoints=True)
    defects = cv2.convexityDefects(contours[max_contour_index], hull_ints)

    for i in range(defects.shape[0]):
        s, e, f, d = defects[i, 0]
        start = tuple(contours[max_contour_index][s][0])
        end = tuple(contours[max_contour_index][e][0])
        far = tuple(contours[max_contour_index][f][0])
        cv2.line(img, start, end, [0, 255, 0], 2)
        cv2.circle(img, far, 2, [0, 0, 255], -1)

    cv2.imshow('Convexity defects', img)
Exemplo n.º 12
0
def calculateFingers(res, drawing):  # count fingers and draw
    hull = cv2.convexHull(
        res,
        returnPoints=False)  # find the convex hull, and get the angular point
    if len(hull) > 3:
        defects = cv2.convexityDefects(res, hull)  # convexity defect
        if type(defects) != type(None):  # avoid crashing
            cnt = 0
            for i in range(defects.shape[0]):  # calculate the angle
                s, e, f, d = defects[i][0]
                start = tuple(res[s][0])
                end = tuple(res[e][0])
                far = tuple(res[f][0])
                a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
                b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2)
                c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2)
                angle = math.acos(
                    (b**2 + c**2 - a**2) /
                    (2 * b * c))  # compute the angle of each hull side
                if angle <= math.pi / 2:  # if angle less than 90 degree, treat as fingers and draw
                    cnt += 1
                    cv2.circle(drawing, far, 8, [211, 84, 0], -1)
            return True, cnt
    return False, 0
Exemplo n.º 13
0
     approx= cv2.approxPolyDP(cnt,epsilon,True)
    
     
 #make convex hull around hand
     hull = cv2.convexHull(cnt)
     
  #define area of hull and area of hand
     areahull = cv2.contourArea(hull)
     areacnt = cv2.contourArea(cnt)
   
 #find the percentage of area not covered by hand in convex hull
     arearatio=((areahull-areacnt)/areacnt)*100
 
  #find the defects in convex hull with respect to hand
     hull = cv2.convexHull(approx, returnPoints=False)
     defects = cv2.convexityDefects(approx, hull)
     
 # l = no. of defects
     l=0
     
 #code for finding no. of defects due to fingers
     for i in range(defects.shape[0]):
         s,e,f,d = defects[i,0]
         start = tuple(approx[s][0])
         end = tuple(approx[e][0])
         far = tuple(approx[f][0])
         pt= (100,180)
         
         
         # find length of all sides of triangle
         a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
Exemplo n.º 14
0
        kernel = numpy.ones((5, 5), numpy.uint8)  # erosion kernel
        mask = cv2.erode(silhouette, kernel,
                         iterations=1)  # mask creation by erosion

        contours, hierarchy = cv2.findContours(
            silhouette, cv2.RETR_TREE,
            cv2.CHAIN_APPROX_SIMPLE)  # find contours of silhouette
        contours = max(
            contours,
            key=lambda x: cv2.contourArea(x))  # pick out biggest contour

        hull = cv2.convexHull(contours, returnPoints=False,
                              clockwise=True)  # construct convex hull
        hull[::-1].sort(
            axis=0)  # sort hull (fix for BUG in the convexHull function)
        defects = cv2.convexityDefects(contours,
                                       hull)  # get indices of defects

        #----------------------------------------------------------------------------
        # Finger gap detection and Affline transformations
        #----------------------------------------------------------------------------
        cnt = 0
        finger_gaps = []

        for i in range(
                defects.shape[0]):  # loop over number of rows in defects
            s, e, f, d = defects[i][0]
            start = tuple(contours[s][0])
            end = tuple(contours[e][0])
            far = tuple(contours[f][0])
            a = numpy.sqrt((end[0] - start[0])**2 +
                           (end[1] - start[1])**2)  # distance formula
Exemplo n.º 15
0
def main():
    """
    Main function of the program.
    """
    # Capture the video from the default camera
    defaultCamera = 0
    capturedVideo = cv2.VideoCapture(defaultCamera)

    # Initialization of the background subtractor
    backgroundSubtractor = cv2.createBackgroundSubtractorMOG2(
        detectShadows=True)

    if not capturedVideo.isOpened():
        print('Error: Unable to open file')
        exit(0)

    # Top-left and bottom-right points of the region of interest rectangle:

    # Low resolution webcam
    regionOfInterestPoint1 = (330, 10)
    regionOfInterestPoint2 = (630, 310)

    # Medium resolution webcam
    # regionOfInterestPoint1 = (800, 30)
    # regionOfInterestPoint2 = (1250, 530)

    # Constant tuple with the two learning rates for the background
    #  subtractor
    learningRates = (0.3, 0)

    # Initialization of the current learning rate
    currentLearningRate = learningRates[0]

    # Boolean that stores if the user wants to count the raised fingers or not
    countHandFingers = True

    # Boolean that stores if the user wants to detect hand gestures or not
    detectHandGestures = True

    # Boolean that stores if the user wants to draw with the index finger or not
    indexFingerDrawing = False

    # List that stores the trace of the current stroke of the drawing
    currentStroke = list()

    # List that stores the entire drawing
    currentDrawing = list()

    # Boolean that stores if the user wants to see the help info or not
    showHelp = True

    while True:
        # Read the data from the captured video
        returntErrorValue, capturedFrame = capturedVideo.read()
        if not returntErrorValue:
            print('Error: Unable to get data')
            exit(0)

        # Window showing the mirrored captured video and the region of interest
        #  marked with a blue rectangle
        capturedFrame = cv2.flip(capturedFrame, 1)
        cv2.rectangle(capturedFrame,
                      regionOfInterestPoint1,
                      regionOfInterestPoint2,
                      color=(255, 0, 0))
        cv2.imshow('WebCam', capturedFrame)

        # Window showing the region of interest only
        regionOfInterest = capturedFrame[
            regionOfInterestPoint1[1]:regionOfInterestPoint2[1],
            regionOfInterestPoint1[0]:regionOfInterestPoint2[0], :].copy()
        # cv2.imshow('Region of Interest', regionOfInterest)

        # Window showing the background subtraction applied
        foregroundMask = backgroundSubtractor.apply(regionOfInterest, None,
                                                    currentLearningRate)
        # cv2.imshow('Foreground Mask', foregroundMask)

        # Window showing the gray threshold applied
        returntErrorValue, blackAndWhite = cv2.threshold(
            foregroundMask, 200, 255, cv2.THRESH_BINARY)
        cv2.imshow('Black and White', blackAndWhite)

        # Window showing the hand contour
        contours = cv2.findContours(blackAndWhite, cv2.RETR_EXTERNAL,
                                    cv2.CHAIN_APPROX_SIMPLE)[0]
        contourWindow = regionOfInterest.copy()

        if len(contours) > 0 and currentLearningRate != learningRates[0]:
            handContour = getLargerContour(contours)
            cv2.drawContours(contourWindow,
                             handContour,
                             contourIdx=-1,
                             color=(0, 255, 0),
                             thickness=3)
        else:
            handContour = None

        cv2.imshow('Contour', contourWindow)

        # Window showing the hand's convex hull
        convexHullWindow = regionOfInterest.copy()

        if handContour is not None:
            handConvexHull = cv2.convexHull(handContour)
            cv2.drawContours(convexHullWindow, [handConvexHull],
                             contourIdx=0,
                             color=(255, 0, 0),
                             thickness=3)
        else:
            handConvexHull = None

        cv2.imshow('Convex Hull', convexHullWindow)

        # Window showing the fingers' convexity defects
        convexityDefectsWindow = regionOfInterest.copy()

        if handContour is not None:
            handConvexHull = cv2.convexHull(handContour,
                                            clockwise=False,
                                            returnPoints=False)
            tempPythonList = list(handConvexHull)
            tempPythonList.sort(reverse=True, key=lambda element: element[0])
            handConvexHull = numpy.array(tempPythonList)
            handConvexityDefects = cv2.convexityDefects(
                handContour, handConvexHull)
            fingerConvexityDefects = list()

            if handConvexityDefects is not None:
                for currentConvexityDefect in range(len(handConvexityDefects)):
                    startIndex, endIndex, farIndex, distanceToConvexHull \
                        = handConvexityDefects[currentConvexityDefect][0]

                    startPoint = tuple(handContour[startIndex][0])
                    endPoint = tuple(handContour[endIndex][0])
                    farPoint = tuple(handContour[farIndex][0])

                    depth = distanceToConvexHull / 256.0

                    if depth > 80.0:
                        # angleOfCurrentConvexityDefect = angle(
                        #     startPoint, endPoint, farPoint)
                        cv2.line(convexityDefectsWindow,
                                 startPoint,
                                 endPoint,
                                 color=(255, 0, 0),
                                 thickness=2)
                        cv2.circle(convexityDefectsWindow,
                                   farPoint,
                                   radius=5,
                                   color=(0, 0, 255),
                                   thickness=-1)
                        fingerConvexityDefects.append(
                            (startPoint, endPoint, farPoint))

        else:
            handConvexHull = None
            handConvexityDefects = None

        cv2.imshow('Convexity Defects', convexityDefectsWindow)

        # Window showing the hand's bounding rectangle
        boundingRectangleWindow = regionOfInterest.copy()

        if handContour is not None:
            handBoundingRectangle = cv2.boundingRect(handContour)

            boundingRectanglePoint1 = (handBoundingRectangle[0],
                                       handBoundingRectangle[1])
            boundingRectanglePoint2 = (handBoundingRectangle[0] +
                                       handBoundingRectangle[2],
                                       handBoundingRectangle[1] +
                                       handBoundingRectangle[3])

            cv2.rectangle(boundingRectangleWindow,
                          boundingRectanglePoint1,
                          boundingRectanglePoint2,
                          color=(0, 0, 255),
                          thickness=3)
        else:
            handBoundingRectangle = None
            boundingRectanglePoint1 = None
            boundingRectanglePoint2 = None

        cv2.imshow('Bounding Rectangle', boundingRectangleWindow)

        # Window showing the user side functionalities
        mainWindow = regionOfInterest.copy()

        if handContour is not None:
            numberOfFingers = countFingers(fingerConvexityDefects,
                                           handBoundingRectangle)

            if countHandFingers:
                mainWindow = printFingers(numberOfFingers, mainWindow)

            if detectHandGestures:
                handGesture = detectHandGesture(numberOfFingers,
                                                fingerConvexityDefects,
                                                handBoundingRectangle)
                mainWindow = printGestures(handGesture, mainWindow)

            if indexFingerDrawing:
                currentStroke = fingerDrawing(currentStroke, handContour,
                                              mainWindow)

            mainWindow = printStroke(currentStroke, mainWindow)

            for stroke in currentDrawing:
                mainWindow = printStroke(stroke, mainWindow)

        if showHelp:
            mainWindow = printHelp(mainWindow)

        if currentLearningRate == learningRates[0]:
            mainWindow = printLearning(mainWindow)

        cv2.imshow('Main Window', mainWindow)

        keyboard = cv2.waitKey(1)

        # Key used for swaping between the two learning rates
        if keyboard & 0xFF == ord('s'):
            currentLearningRate = swapLearningRate(currentLearningRate,
                                                   learningRates)

        # Key used for swaping between counting the raised fingers or not
        if keyboard & 0xFF == ord('f'):
            countHandFingers = not countHandFingers

        # Key used for swaping between detecting hand gestures or not
        if keyboard & 0xFF == ord('g'):
            detectHandGestures = not detectHandGestures

        # Key used for swaping between drawing with the index finger or not
        if keyboard & 0xFF == ord('d'):
            indexFingerDrawing = not indexFingerDrawing

            if not indexFingerDrawing:
                currentDrawing.append(currentStroke[:])
                currentStroke.clear()

        # Key used for cleaning the last stroke
        if keyboard & 0xFF == ord('c'):
            currentDrawing.pop()

        # Key used for cleaning the entire drawing
        if keyboard & 0xFF == ord('x'):
            currentDrawing.clear()

        # Key used for swaping between showing the help info or not
        if keyboard & 0xFF == ord('h'):
            showHelp = not showHelp

        # Key used for finishing the program execution
        if keyboard & 0xFF == ord('q'):
            break

    capturedVideo.release()
    cv2.destroyAllWindows()
Exemplo n.º 16
0
            contours,
            key=lambda x: cv2.contourArea(x))  #find contour with max ar

        x, y, w, h = cv2.boundingRect(
            contour)  #make boundry rectangle arnd the contour
        cv2.rectangle(crop_img, (x, y), (x + w, y + h), (0, 0, 255), 0)

        hull = cv2.convexHull(contour)  #convex hull find

        draw = np.zeros(crop_img, np.uint8)  #draw the contour
        cv2.drawContours(draw, [contour], -1, (0, 255, 0), 0)
        cv2.drawContours(draw[hull], -1, (0, 0, 255), 0)

        hull = cv2.convexHull(contour,
                              returnPoints=False)  #find convexity defects
        defects = cv2.convexityDefects(contour, hull)

        count_defects = 0  #using cosine rule to find the change in angle if hand is moved,from start to end point.

        for i in range(defects.shape[0]):
            s, e, f, d = defects[i, 0]
            start = tuple(contour[s][0])
            end = tuple(contour[e][0])
            far = tuple(contour[f][0])

            a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
            b = math.sqrt((end[0] - start[0])**2 + (far[1] - start[1])**2)
            c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2)
            angle = (math.acos(
                (b**2 + c**2 - a**2) / (2 * b * c)) * 180) / 3.14
# coding: utf-8
import numpy as np
from cv2 import cv2
import matplotlib.pyplot as plt

img = cv2.imread(r'pictures\star.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, 2, 1)
cnt = contours[0]

hull = cv2.convexHull(cnt, returnPoints=False)
# Remember we have to pass returnPoints = False while finding convex hull, in order to find convexity defects.
defects = cv2.convexityDefects(cnt, hull)
# It returns an array where each row contains these values - [ start point, end point, farthest point, approximate distance to farthest point ].

dist = cv2.pointPolygonTest(cnt, (50, 50), True)
# This function finds the shortest distance between a point (50, 50) in the image and a contour. It returns the distance which is negative when point is outside the contour, positive when point is inside and zero if point is on the contour.
# In the function, third argument is measureDist. If it is True, it finds the signed distance. If False, it finds whether the point is inside or outside or on the contour (it returns +1, -1, 0 respectively). Making it False gives about 2-3X speedup.

for i in range(defects.shape[0]):
    s, e, f, d = defects[i, 0]
    start = tuple(cnt[s][0])
    end = tuple(cnt[e][0])
    far = tuple(cnt[f][0])
    cv2.line(img, start, end, [0, 255, 0], 2)
    cv2.circle(img, far, 5, [0, 0, 255], -1)

cv2.namedWindow("img", 0)
cv2.imshow('img', img)
cv2.waitKey(0)
Exemplo n.º 18
0
def getContours(imgCon, imgMatch):
    contours, _ = cv2.findContours(imgCon, cv2.RETR_EXTERNAL,
                                   cv2.CHAIN_APPROX_NONE)
    imgCon = cv2.cvtColor(imgCon, cv2.COLOR_GRAY2BGR)
    bigCon = 0
    myCounter = 0
    data = 0
    myPos = np.zeros(4)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if (area > 1000):
            cv2.drawContours(imgCon, cnt, -1, (255, 0, 255), 3)
            cv2.drawContours(imgMatch, cnt, -1, (255, 0, 255), 3)
            peri = cv2.arcLength(cnt, True)
            approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
            # APPROXIMATED BOUNDING BOX
            x, y, w, h = cv2.boundingRect(approx)
            ex = 10
            cv2.rectangle(imgCon, (x - ex, y - ex), (x + w + ex, y + h + ex),
                          (0, 255, 0), 5)
            # CONVEX HULL &amp; CONVEXITY DEFECTS OF THE HULL
            hull = cv2.convexHull(cnt, returnPoints=False)
            defects = cv2.convexityDefects(cnt, hull)
            bigCon += 1

            for i in range(defects.shape[0]):  # calculate the angle
                s, e, f, _ = defects[i][0]
                start = tuple(cnt[s][0])
                end = tuple(cnt[e][0])
                far = tuple(cnt[f][0])
                a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
                b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2)
                c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2)
                angle = math.acos(
                    (b**2 + c**2 - a**2) / (2 * b * c))  # cosine theorem
                if angle <= math.pi // 1.7:  # angle less than  degree, treat as fingers
                    myPos[myCounter] = far[0]
                    myCounter += 1
                    cv2.circle(imgCon, far, 5, [0, 255, 0], -1)
                    cv2.circle(imgMatch, far, 5, [0, 255, 0], -1)

            # SENDING COMMANDS BASED ON FINGERS
            if (myCounter == 4):
                FingerCount = "Five"
                data = 5
            elif (myCounter == 3):
                FingerCount = "Four"
                data = 4
            elif (myCounter == 2):
                FingerCount = "Three"
                data = 3
            elif (myCounter == 1):
                FingerCount = "Two"
                data = 2
            elif (myCounter == 0):
                aspectRatio = w / h
                if aspectRatio < 0.6:
                    FingerCount = "One"
                    data = 1
                else:
                    FingerCount = "Zero"
                    data = 0
            cv2.putText(imgMatch, FingerCount, (50, 50),
                        cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 2)
    return imgCon, imgMatch, data
def gestos_mano():
    cap = cv2.VideoCapture(0)
    # cap = cv2.VideoCapture(1)

    bg = None
    # COLORES PARA VISUALIZACIÓN
    color_start = (204, 204, 0)
    color_end = (204, 0, 204)
    color_far = (255, 0, 0)
    color_start_far = (204, 204, 0)
    color_far_end = (204, 0, 204)
    color_start_end = (0, 255, 255)
    color_contorno = (0, 255, 0)
    color_ymin = (0, 130, 255)  # Punto más alto del contorno
    # color_angulo = (0,255,255)
    # color_d = (0,255,255)
    color_fingers = (0, 255, 255)

    while True:
        ret, frame = cap.read()
        if ret == False: break
        # Redimensionar la imagen para que tenga un ancho de 640
        frame = imutils.resize(frame, width=640)
        frame = cv2.flip(frame, 1)
        frameAux = frame.copy()

        if bg is not None:

            # Determinar la región de interés
            ROI = frame[50:300, 380:600]
            cv2.rectangle(frame, (380 - 2, 50 - 2), (600 + 2, 300 + 2),
                          color_fingers, 1)
            grayROI = cv2.cvtColor(ROI, cv2.COLOR_BGR2GRAY)

            # Región de interés del fondo de la imagen
            bgROI = bg[50:300, 380:600]

            # Determinar la imagen binaria (background vs foreground)
            dif = cv2.absdiff(grayROI, bgROI)
            _, th = cv2.threshold(dif, 30, 255, cv2.THRESH_BINARY)
            th = cv2.medianBlur(th, 7)

            # Encontrando los contornos de la imagen binaria
            cnts, _ = cv2.findContours(th, cv2.RETR_EXTERNAL,
                                       cv2.CHAIN_APPROX_SIMPLE)
            cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:1]
            for cnt in cnts:
                # Encontrar el centro del contorno
                M = cv2.moments(cnt)
                if M["m00"] == 0: M["m00"] = 1
                x = int(M["m10"] / M["m00"])
                y = int(M["m01"] / M["m00"])
                cv2.circle(ROI, tuple([x, y]), 5, (0, 255, 0), -1)

                # Punto más alto del contorno
                ymin = cnt.min(axis=1)
                cv2.circle(ROI, tuple(ymin[0]), 5, color_ymin, -1)

                # Contorno encontrado a través de cv2.convexHull
                hull1 = cv2.convexHull(cnt)
                cv2.drawContours(ROI, [hull1], 0, color_contorno, 2)

                # Defectos convexos
                hull2 = cv2.convexHull(cnt, returnPoints=False)
                defects = cv2.convexityDefects(cnt, hull2)

                # Seguimos con la condición si es que existen defectos convexos
                if defects is not None:
                    inicio = [
                    ]  # Contenedor en donde se almacenarán los puntos iniciales de los defectos convexos
                    fin = [
                    ]  # Contenedor en donde se almacenarán los puntos finales de los defectos convexos
                    fingers = 0  # Contador para el número de dedos levantados
                    for i in range(defects.shape[0]):

                        s, e, f, d = defects[i, 0]
                        start = cnt[s][0]
                        end = cnt[e][0]
                        far = cnt[f][0]
                        # Encontrar el triángulo asociado a cada defecto convexo para determinar ángulo
                        a = np.linalg.norm(far - end)
                        b = np.linalg.norm(far - start)
                        c = np.linalg.norm(start - end)

                        angulo = np.arccos(
                            (np.power(a, 2) + np.power(b, 2) - np.power(c, 2))
                            / (2 * a * b))
                        angulo = np.degrees(angulo)
                        angulo = int(angulo)

                        # Se descartarán los defectos convexos encontrados de acuerdo a la distnacia
                        # entre los puntos inicial, final y más alelago, por el ángulo y d
                        if np.linalg.norm(start - end
                                          ) > 20 and angulo < 90 and d > 12000:
                            # Almacenamos todos los puntos iniciales y finales que han sido
                            # obtenidos
                            inicio.append(start)
                            fin.append(end)

                            # Visualización de distintos datos obtenidos
                            # cv2.putText(ROI,'{}'.format(angulo),tuple(far), 1, 1.5,color_angulo,2,cv2.LINE_AA)
                            # cv2.putText(ROI,'{}'.format(d),tuple(far), 1, 1.1,color_d,1,cv2.LINE_AA)
                            cv2.circle(ROI, tuple(start), 5, color_start, 2)
                            cv2.circle(ROI, tuple(end), 5, color_end, 2)
                            cv2.circle(ROI, tuple(far), 7, color_far, -1)
                            # cv2.line(ROI,tuple(start),tuple(far),color_start_far,2)
                            # cv2.line(ROI,tuple(far),tuple(end),color_far_end,2)
                            # cv2.line(ROI,tuple(start),tuple(end),color_start_end,2)
                    # Si no se han almacenado puntos de inicio (o fin), puede tratarse de
                    # 0 dedos levantados o 1 dedo levantado
                    if len(inicio) == 0:
                        minY = np.linalg.norm(ymin[0] - [x, y])
                        if minY >= 110:
                            fingers = fingers + 1
                            cv2.putText(ROI, '{}'.format(fingers),
                                        tuple(ymin[0]), 1, 1.7,
                                        (color_fingers), 1, cv2.LINE_AA)

                    # Si se han almacenado puntos de inicio, se contará el número de dedos levantados
                    for i in range(len(inicio)):
                        fingers = fingers + 1
                        cv2.putText(ROI, '{}'.format(fingers),
                                    tuple(inicio[i]), 1, 1.7, (color_fingers),
                                    1, cv2.LINE_AA)
                        if i == len(inicio) - 1:
                            fingers = fingers + 1
                            cv2.putText(ROI, '{}'.format(fingers),
                                        tuple(fin[i]), 1, 1.7, (color_fingers),
                                        1, cv2.LINE_AA)

                    # Se visualiza el número de dedos levantados en el rectángulo izquierdo
                    if fingers == 0:
                        cv2.putText(frame, 'Auxilio', (390, 45), 1, 2,
                                    (color_fingers), 2, cv2.LINE_AA)
                    else:
                        if fingers == 1:
                            cv2.putText(frame, 'Estoy bien!', (390, 45), 1, 2,
                                        (color_fingers), 2, cv2.LINE_AA)

                        else:
                            if fingers == 2:
                                if angulo > 60:
                                    cv2.putText(frame, 'Tengo hambre',
                                                (390, 45), 1, 2,
                                                (color_fingers), 2,
                                                cv2.LINE_AA)
                                else:
                                    if angulo < 40:
                                        cv2.putText(frame, 'Tengo sueño',
                                                    (390, 45), 1, 2,
                                                    (color_fingers), 2,
                                                    cv2.LINE_AA)
                            else:
                                if fingers == 3:
                                    cv2.putText(frame, 'Te quiero', (390, 45),
                                                1, 2, (color_fingers), 2,
                                                cv2.LINE_AA)
                                else:
                                    if fingers == 4:
                                        cv2.putText(frame, 'Gesto desconocido',
                                                    (300, 45), 1, 2,
                                                    (color_fingers), 2,
                                                    cv2.LINE_AA)
                                    else:
                                        cv2.putText(frame, 'Hola mundo!',
                                                    (300, 45), 1, 2,
                                                    (color_fingers), 2,
                                                    cv2.LINE_AA)

            cv2.imshow('th', th)
        cv2.imshow('Frame', frame)
        k = cv2.waitKey(20)
        if k == ord('i'):
            bg = cv2.cvtColor(frameAux, cv2.COLOR_BGR2GRAY)
        if k == 27:
            break

    cap.release()
    cv2.destroyAllWindows()