ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OpenCV를 사용하여 손 검출 및 인식하기(Hand Detection and Recognition using OpenCV)
    OpenCV/OpenCV Python 강좌 2019. 9. 24. 22:14




    OpenCV를 사용하여 손을 검출 및 인식하는 방법에 대해 다룹니다. 


    현재 두가지 방법으로 코드가 작성되었습니다. 


    Background Subtraction을 사용한 방법과 HSV 공간에서 살색을 검출한 방법입니다.  




    Background Subtraction를 사용한 경우 






    import cv2 as cv
    import numpy as np
    import os


    def detect(img, cascade):
        rects = cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30),
                                        flags=cv.CASCADE_SCALE_IMAGE)
        if len(rects) == 0:
            return []
        rects[:,2:] += rects[:,:2]
        return rects

    def removeFaceAra(img, cascade):
      gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
      gray = cv.equalizeHist(gray)
      rect = detect(gray, cascade)

      return rect

    def findMaxArea(contours):
         
      max_contour = None
      max_area = -1


      for contour in contours:
        area = cv.contourArea(contour)

        x,y,w,h = cv.boundingRect(contour)

        if (w*h)*0.4 > area:
            continue

        if w > h:
            continue

        if area > max_area:
          max_area = area
          max_contour = contour
     
      if max_area < 10000:
        max_area = -1

      return max_area, max_contour


    def distanceBetweenTwoPoints(start, end):
       
      x1,y1 = start
      x2,y2 = end

      return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))


    def calculateAngle(A, B):

      A_norm = np.linalg.norm(A)
      B_norm = np.linalg.norm(B)
      C = np.dot(A,B)

      angle = np.arccos(C/(A_norm*B_norm))*180/np.pi
      return angle


    def getFingerPosition(max_contour, img_result, debug):
      points1 = []


      # STEP 6-1
      M = cv.moments(max_contour)

      cx = int(M['m10']/M['m00'])
      cy = int(M['m01']/M['m00'])


      max_contour = cv.approxPolyDP(max_contour,0.02*cv.arcLength(max_contour,True),True)
      hull = cv.convexHull(max_contour)

      for point in hull:
        if cy > point[0][1]:
          points1.append(tuple(point[0]))

      if debug:
        cv.drawContours(img_result, [hull], 0, (0,255,0), 2)
        for point in points1:
          cv.circle(img_result, tuple(point), 15, [ 0, 0, 0], -1)


      # STEP 6-2
      hull = cv.convexHull(max_contour, returnPoints=False)
      defects = cv.convexityDefects(max_contour, hull)

      if defects is None:
        return -1,None

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

        angle = calculateAngle( np.array(start) - np.array(far), np.array(end) - np.array(far))

        if angle < 90:
          if start[1] < cy:
            points2.append(start)
         
          if end[1] < cy:
            points2.append(end)

      if debug:
        cv.drawContours(img_result, [max_contour], 0, (255, 0, 255), 2)
        for point in points2:
          cv.circle(img_result, tuple(point), 20, [ 0, 255, 0], 5)


      # STEP 6-3
      points = points1 + points2
      points = list(set(points))


      # STEP 6-4
      new_points = []
      for p0 in points:
       
        i = -1
        for index,c0 in enumerate(max_contour):
          c0 = tuple(c0[0])

          if p0 == c0 or distanceBetweenTwoPoints(p0,c0)<20:
            i = index
            break

        if i >= 0:
          pre = i - 1
          if pre < 0:
            pre = max_contour[len(max_contour)-1][0]
          else:
            pre = max_contour[i-1][0]
         
          next = i + 1
          if next > len(max_contour)-1:
            next = max_contour[0][0]
          else:
            next = max_contour[i+1][0]


          if isinstance(pre, np.ndarray):
            pre = tuple(pre.tolist())
          if isinstance(next, np.ndarray):
            next = tuple(next.tolist())


          angle = calculateAngle( np.array(pre) - np.array(p0), np.array(next) - np.array(p0))    

          if angle < 90:
            new_points.append(p0)
     
      return 1,new_points

    def process(img_bgr, img_binary, debug):
       
      img_result = img_bgr.copy()

      # # STEP 1
      # img_bgr = removeFaceAra(img_bgr, cascade)


      # # STEP 2
      # img_binary = make_mask_image(img_bgr)


      # # STEP 3
      # kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
      # img_binary = cv.morphologyEx(img_binary, cv.MORPH_CLOSE, kernel, 1)
      # if debug:
      #   cv.imshow("Binary", img_binary)


      # STEP 4
      contours, hierarchy = cv.findContours(img_binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

      if debug:
        for cnt in contours:
          cv.drawContours(img_result, [cnt], 0, (255, 0, 0), 3
       

      # STEP 5
      max_area, max_contour = findMaxArea(contours) 

      if max_area == -1:
        return img_result

      if debug:
        cv.drawContours(img_result, [max_contour], 0, (0, 0, 255), 3


      # STEP 6
      ret,points = getFingerPosition(max_contour, img_result, debug)
     

      # STEP 7
      if ret > 0 and len(points) > 0
        for point in points:
          cv.circle(img_result, point, 20, [ 255, 0, 255], 5)

      return img_result



    current_file_path = os.path.dirname(os.path.realpath(__file__))
    cascade = cv.CascadeClassifier(cv.samples.findFile(current_file_path + "\haarcascade_frontalface_alt.xml"))
    cap = cv.VideoCapture('hand.avi')


    #  http://layer0.authentise.com/segment-background-using-computer-vision.html
    fgbg = cv.createBackgroundSubtractorMOG2(varThreshold=200, detectShadows=0)

    index = 0

    while(1):
        index = index + 1

        ret, frame = cap.read()
        if ret == False:
            break;

        frame = cv.flip(frame, 1)
       
        blur = cv.GaussianBlur(frame, (5,5), 0)
        rect = removeFaceAra(frame, cascade)

        fgmask = fgbg.apply(blur, learningRate=0)

        kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
        fgmask = cv.morphologyEx(fgmask, cv.MORPH_CLOSE, kernel, 2)
       

        height,width = frame.shape[:2]
        for x1, y1, x2, y2 in rect:
            cv.rectangle(fgmask, (x1-10, 0), (x2+10, height), (0,0,0), -1)
       
     
        img_result = process(frame, fgmask, debug=False)


        cv.imshow('mask', fgmask)
        cv.imshow('result', img_result)


        key = cv.waitKey(30) & 0xff
        if key == 27:
            break

    cap.release()
    cv.destroyAllWindows()



    HSV 색공간에서 살색을 검출한 경우







    import cv2 as cv
    import numpy as np
    import os



    def detect(img, cascade):
        rects = cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30),
                                        flags=cv.CASCADE_SCALE_IMAGE)
        if len(rects) == 0:
            return []
        rects[:,2:] += rects[:,:2]
        return rects


    def removeFaceAra(img, cascade):
      gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
      gray = cv.equalizeHist(gray)
      rects = detect(gray, cascade)

      height,width = img.shape[:2]

      for x1, y1, x2, y2 in rects:
          cv.rectangle(img, (x1-10, 0), (x2+10, height), (0,0,0), -1)

      return img


    def make_mask_image(img_bgr):
       
      img_hsv = cv.cvtColor(img_bgr, cv.COLOR_BGR2HSV)

      #img_h,img_s,img_v = cv.split(img_hsv)

      low = (0, 30, 0)
      high = (15, 255, 255)

      img_mask = cv.inRange(img_hsv, low, high)
      return img_mask

     
    def distanceBetweenTwoPoints(start, end):

      x1,y1 = start
      x2,y2 = end

      return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))


    def calculateAngle(A, B):

      A_norm = np.linalg.norm(A)
      B_norm = np.linalg.norm(B)
      C = np.dot(A,B)

      angle = np.arccos(C/(A_norm*B_norm))*180/np.pi
      return angle


    def findMaxArea(contours):
     
      max_contour = None
      max_area = -1


      for contour in contours:
        area = cv.contourArea(contour)

        x,y,w,h = cv.boundingRect(contour)

        if (w*h)*0.4 > area:
            continue

        if w > h:
            continue

        if area > max_area:
          max_area = area
          max_contour = contour
     
      if max_area < 10000:
        max_area = -1

      return max_area, max_contour


    def getFingerPosition(max_contour, img_result, debug):
      points1 = []


      # STEP 6-1
      M = cv.moments(max_contour)

      cx = int(M['m10']/M['m00'])
      cy = int(M['m01']/M['m00'])


      max_contour = cv.approxPolyDP(max_contour,0.02*cv.arcLength(max_contour,True),True)
      hull = cv.convexHull(max_contour)

      for point in hull:
        if cy > point[0][1]:
          points1.append(tuple(point[0]))

      if debug:
        cv.drawContours(img_result, [hull], 0, (0,255,0), 2)
        for point in points1:
          cv.circle(img_result, tuple(point), 15, [ 0, 0, 0], -1)


      # STEP 6-2
      hull = cv.convexHull(max_contour, returnPoints=False)
      defects = cv.convexityDefects(max_contour, hull)

      if defects is None:
        return -1,None

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

        angle = calculateAngle( np.array(start) - np.array(far), np.array(end) - np.array(far))

        if angle < 90:
          if start[1] < cy:
            points2.append(start)
         
          if end[1] < cy:
            points2.append(end)

      if debug:
        cv.drawContours(img_result, [max_contour], 0, (255, 0, 255), 2)
        for point in points2:
          cv.circle(img_result, tuple(point), 20, [ 0, 255, 0], 5)


      # STEP 6-3
      points = points1 + points2
      points = list(set(points))


      # STEP 6-4
      new_points = []
      for p0 in points:
       
        i = -1
        for index,c0 in enumerate(max_contour):
          c0 = tuple(c0[0])

          if p0 == c0 or distanceBetweenTwoPoints(p0,c0)<20:
            i = index
            break

        if i >= 0:
          pre = i - 1
          if pre < 0:
            pre = max_contour[len(max_contour)-1][0]
          else:
            pre = max_contour[i-1][0]
         
          next = i + 1
          if next > len(max_contour)-1:
            next = max_contour[0][0]
          else:
            next = max_contour[i+1][0]


          if isinstance(pre, np.ndarray):
                pre = tuple(pre.tolist())
          if isinstance(next, np.ndarray):
            next = tuple(next.tolist())

           
          angle = calculateAngle( np.array(pre) - np.array(p0), np.array(next) - np.array(p0))    

          if angle < 90:
            new_points.append(p0)
     
      return 1,new_points


    def process(img_bgr, debug):

      img_result = img_bgr.copy()

      # STEP 1
      img_bgr = removeFaceAra(img_bgr, cascade)


      # STEP 2
      img_binary = make_mask_image(img_bgr)


      # STEP 3
      kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
      img_binary = cv.morphologyEx(img_binary, cv.MORPH_CLOSE, kernel, 1)
      cv.imshow("Binary", img_binary)


      # STEP 4
      contours, hierarchy = cv.findContours(img_binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

      if debug:
        for cnt in contours:
          cv.drawContours(img_result, [cnt], 0, (255, 0, 0), 3
       

      # STEP 5
      max_area, max_contour = findMaxArea(contours) 

      if max_area == -1:
        return img_result

      if debug:
        cv.drawContours(img_result, [max_contour], 0, (0, 0, 255), 3


      # STEP 6
      ret,points = getFingerPosition(max_contour, img_result, debug)
     

      # STEP 7
      if ret > 0 and len(points) > 0
        for point in points:
          cv.circle(img_result, point, 20, [ 255, 0, 255], 5)

      return img_result



    current_file_path = os.path.dirname(os.path.realpath(__file__))
    cascade = cv.CascadeClassifier(cv.samples.findFile(current_file_path + "\haarcascade_frontalface_alt.xml"))


    # cap = cv.VideoCapture('test.avi')

    cap = cv.VideoCapture(0)

    while True:

      ret,img_bgr = cap.read()
     
      if ret == False:
        break

      img_result = process(img_bgr, debug=False)
     
      key = cv.waitKey(1)
      if key== 27:
          break


      cv.imshow("Result", img_result)


    cap.release()
    cv.destroyAllWindows()




    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구독하기


    댓글 34

    • 2019.10.25 22:34


      비밀댓글입니다

    • 2019.11.03 17:36


      비밀댓글입니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.03 17:58 신고


        안드로이드에서 OpenCV 카메라 예제를 다룬 다음 포스트를 수정하여 진행하면 될듯합니다.

        자바는 결과를 보여주는데 사용하고
        실제 구현은 CPP 코드에서 하면 됩니다.

    • 꾸꾸루꾸 2019.11.13 15:57


      안녕하세요 opencv 사용하여 카메라 mjpg스트리밍으로 얼굴 검출 하고있습니다..ㅠ
      이게 제 소스인데
      #카메라 구동되도록 해주는 명령어
      os.system("sudo modprobe bcm2835-v4l2")

      # 얼굴특징이 담겨져있는 xml 파일을 불러옴
      faceCascade = cv2.CascadeClassifier("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml")

      #카메라를 가져옴
      video_capture = cv2.VideoCapture(-1)


      #카메라 설정
      video_capture.set(cv2.CAP_PROP_FPS,20)
      video_capture.set(cv2.CAP_PROP_FRAME_WIDTH ,320)
      video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT,240)


      while True: #무한반복


      #카메라의 한프레임을 읽어옴
      ret, frame = video_capture.read()

      rows,cols,_ = frame.shape#현재 프레임의 해상도를 가지고오고
      M = cv2.getRotationMatrix2D((cols/2,rows/2),180,1) #180 도 회전
      frame = cv2.warpAffine(frame,M,(cols,rows)) # 프레임에 저장


      gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #흑백으로 만들어줌

      faces = faceCascade.detectMultiScale(#얼굴검출
      gray,
      scaleFactor=1.1,
      minNeighbors=5,
      minSize=(20, 20),
      maxSize=(100, 100)
      )

      rows,cols,_ = frame.shape 부분에서
      AttributeError: 'NoneType' object has no attribute 'shape'
      이란 에러가 뜨네요.. 구글링 해서 몇페이지 다 번역해서 읽어봐도 다들 영상을 불러와서 쓰지 저처럼 스트리밍 해서
      하는 사례가 없더군요 ㅠ 혹시 도와주실수 있는지 해서 댓글 남겨봅니다!!
      비디오캡쳐는 0으로도 해보고 -1로도 해봤습니다!

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.13 21:26 신고


        스트리밍이면 주소로 해야 하지 않나요?

        아래 링크를 참고하세요

        mjpg-streamer를 사용한 웹 스트리밍을 OpenCV에서 가져오기
        https://webnautes.tistory.com/1262

      • 꾸꾸루꾸 2019.11.14 10:39


        안녕하세요! 댓글 답변 정말 감사합니다!! 하나만 더 여쭤보겠습니다 ㅠㅠ
        말씀하신대로 스트리밍 주소를 비디오 캡쳐에 넣어서 하니 에러없이 스트리밍이 되는데
        전엔 VideoCapture(0)으로도 소스가 잘 돌아갔었는데 한번 뻑난 이후로 설치환경을 다른버전들을 설치해서그런지 안돌아가기 시작했던거거든요..
        제가 하고있는것이 팬/틸트 키트(서보모터2개 x축,y축) 에 파이카메라를 부착하여 파이카메라가 사람 얼굴을 인식하면
        사각형을 그리며 프레임이 한쪽으로 치우치면 서보모터 작동하여 얼굴을 따라가게 되는데 우선적으로 얼굴인식을 하면 초록 사각형을 그리고 가장 큰 얼굴에 파란 사각형을 계속 화면에 띄워졌었는데
        VideoCapture(웹스트리밍주소)로 바꾸고선 cv2.rectangle 사용해도 사각형이 웹스트리밍 화면에 그려지질 않네요 ㅠㅠ 혹시 mjpg 웹스트리밍 화면에 사각형을 그릴 수 있는 방법 혹시 아시나요..?!

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.14 21:08 신고


        rectangle로 사각형을 그린 후에 imshow 함수를 호출해야 화면에 사각형이 보입니다.

      • 꾸꾸루꾸 2019.11.14 21:25


        imshow 함수를 호출하면 웹 스트리밍 창이 아닌 새로운 창이 뜨면서
        사각형이 그려지긴 하나 렉이 엄청 심합니다 ㅠ 그리고 뒤집혀서 나오기도하구요..
        아이피주소:8080/?action=stream.html
        mjpg 게시글 보며 스트리밍 옵션을 넣어주어 들어가서 보면 상하반전에 프레임도 괜찮게 나와서 딜레이도 없는것같은데...

        이런 매끄러운 화면에서 제가 원하는 화면을 띄우는건 욕심일까요..?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.14 22:12 신고


        웹스트리밍창도 OpenCV로 만든 창 아닌가요?

      • 꾸꾸루꾸 2019.11.15 12:37


        자꾸 귀찮게 해드려서 죄송합니다 ㅠ
        export STREAMER_PATH=$HOME/mjpg/mjpg-streamer/mjpg-streamer-experimental

        export LD_LIBRARY_PATH=$STREAMER_PATH

        $STREAMER_PATH/mjpg_streamer -i "input_raspicam.so -vf -d 200 -fps 20" -o "output-http.so -p 8080 -w $STREAMER_PATH/www"

        란 내용의 mjpg.sh 파일을 만들고
        sh mjpg.sh 를 한 콘솔창에 실행한 뒤

        또 다른 콘솔창에서 python face.py 를 실행하고있습니다.

        저도 여러곳에서 구글링해서 이것저것 추가해서 해봤던거라 라즈베리파이가 고장나기 전엔 videocapture(0)도 됐었고 이렇게 두개 창으로 했을 때 인터넷 열어서 주소창 들어갔을 때 스트리밍 화면에 사각형도 그려졌었거든요..ㅠㅠ

        하나하나 댓글 달아주심에 감사합니다..

      • 2019.11.15 15:54


        비밀댓글입니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.16 18:01 신고


        imshow 호출전에 이미지에 사각형을 그려주도록 하면됩니다.

      • 꾸꾸루꾸 2019.11.17 17:33


        몇일간 도움 감사했습니다!! 어느정도 여러가지 손보며 해결한듯 합니다 ㅎㅎ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.17 19:19 신고


        축하드려요..

    • 초보자 2019.12.30 12:32


      HSV 예제를 따라서 진행을 했는데

      cascade = cv.CascadeClassifier(cv.samples.findFile(current_file_path + "\haarcascade_frontalface_alt.xml"))

      이부분에서 다음과 같은 에러메시지가 출력되었는데요
      cascade = cv.CascadeClassifier(cv.samples.findFile(current_file_path + "\haarcascade_frontalface_alt.xml"))
      AttributeError: module 'cv2' has no attribute 'samples'
      이때에는 어떻게 해야되는지 검색을 해봐도 파일명을 바꾸면 된다고 만 나와서 이렇게 글을 남겨봅니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.30 13:36 신고


        cv.samples.findFile을 제거하고 해보세요

      • 초보자 2019.12.30 16:02


        cascade = cv.CascadeClassifier(current_file_path + "\haarcascade_frontalface_alt.xml")
        or
        cascade = cv.CascadeClassifier()
        이렇게 두가지 방식으로 했는데
        GStreamer-CRITICAL **: 15:52:02.185: gst_element_get_state: assertion 'GST_IS_ELEMENT (element)' failed

        VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV

        Unable to stop the stream: Device or resource busy

        VIDEOIO ERROR: V4L: can't open camera by index 0
        이러한 에러 문구가 출력되었습니다
        말씀하신 방법을 맞게 했는지 문의 드립니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.30 16:09 신고


        첫번째가 맞는 방법입니다. 에러는 카메라를 열수 없다는 에러입니다. 카메라를 확인해보세요

      • 초보자 2019.12.30 16:12


        pi카메라를 사용중인데 어떻게 확인하면 되나요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.30 16:17 신고


        다음.포스트를 참고하세요

        https://webnautes.tistory.com/1192

      • 초보자 2019.12.30 17:11


        포스트를 참고하여 raspistill -o image.jpg 까지 진행 하였고 이미지까지 확인하였습니다만 dmesg 에선
        brcmfmac : brcmf_fw_alloc_request: using brcm/brcmfmac43430-sdio for chip BCM43430/1
        brcmfmac : brcmf_link_down : WLC_DISASSOC failed(-52)
        이렇게 출력되었는데 연결 문제인가요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.30 18:38 신고


        포스트에서 확인하는 값이 둘다 1로 보이나요?

      • 초보자 2019.12.31 12:41


        네 둘다 1로 출력됩니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.31 20:10 신고


        0대신 -1을 사용해보셨나요?

      • 초보자 2020.01.02 10:31


        cap = cv.VideoCapture(0) 이부분을 -1로 변경하고 실행을 했더니
        Traceback (most recent call last):
        File "/home/pi/test.py", line 248, in <module>
        img_result = process(img_bgr, debug=False)
        File "/home/pi/test.py", line 190, in process
        img_bgr = removeFaceAra(img_bgr, cascade)
        File "/home/pi/test.py", line 19, in removeFaceAra
        rects = detect(gray, cascade)
        File "/home/pi/test.py", line 9, in detect
        flags=cv.CASCADE_SCALE_IMAGE)
        cv2.error: OpenCV(4.1.2) /home/pi/opencv/opencv-4.1.2/modules/objdetect/src/cascadedetect.cpp:1689: error: (-215:Assertion failed) !empty() in function 'detectMultiScale'
        에러 문구가 출력 되었습니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.01.03 09:41 신고


        XML 파일 위치를 못찾는 듯합니다. xml 파일을 파이썬 코드 있는 곳으로 복사해왔는지요?

        그리고 혹시 웹캠이 잘동작하는지 다음 코드에서 0 을 -1로 바꾸어서 테스트해보세요.
        https://webnautes.tistory.com/577

      • 초보자 2020.01.03 14:57


        xml 파일을 파이썬 코드 있는 곳으로 복사해서 실행을 해보았는데 동일한 에러가 발생했습니다
        그리고 알려주신 주소에 있는 예제로 테스트 진행을 했는데 pi카메라는 잘 동작하엿습니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.01.03 20:59 신고


        xml 파일을 못찾는 듯합니다..

        아래 링크의 예제로 테스트해보세요.
        https://webnautes.tistory.com/1352

    • 초보영상처리 2020.01.30 20:10


      안녕하세요 손가락 검출을 이용한 프로젝트를 진행중인 학생입니다.
      손끝을 검출하고 그 좌표를 이용하여 그림판에 그림을 그리는 것처럼 프로그램을 구현하고자 하는데
      가끔가다가 ret, points = getFingerPosition(findMaxArea(contours)[1],frame,True) 이 코드 부분에서 'NoneType' object is not iterable 이러한 오류가 발생합니다.
      아마 이미지 컨투어가 제대로 이루어지는 환경에 좌우되는 것 같기는 한데... 혹시 해결할수있는 방법을 여쭤보고 싶어서 댓글달았습니다.

      구글링해본 결과 반환되는 points가 None일 경우를 대비하여 예외문을 만들었는데도 같은 경우의 에러가 발생합니다.

    • 오픈씨비초보 2020.02.19 12:16


      저는 동영상 시작 전 드래그를 통해 드래그 한 물체만 트래킹 하는 프로그램을 만들고 있습니다.
      혹시 배경을 대부분 검은 색으로 바꾸고 바꾼 비디오를 가지고 트래킹을 할 수 있는 방법이 있을까요?

Designed by Tistory.