1, 2일차는 openCV에 대해 공부 및 따로 게시글을 작성하지 않았습니다.
import cv2
import numpy as np
def cont():
try:
cap=cv2.VideoCapture(0)
except:
print('camera_errro')
return
while True:
ret, frame = cap.read()
if not ret:
print('camera2_error')
break
dst = frame.copy()
test = cv2.cvtColor(frame, cv2.COLOR_BGR2YCrCb)
mask_hand = cv2.inRange(test, np.array([0,133,77]),np.array([255,173,127]))
#test = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret, thr = cv2.threshold(mask_hand, 127, 255, cv2.THRESH_BINARY_INV)
_, contours, hierachy=cv2.findContours(thr, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
for i in contours:
hull = cv2.convexHull(i,clockwise=True)
cv2.drawContours(dst, [hull], 0, (0,0,255),2)
cv2.imshow('dst', dst)
cv2.imshow('mask_hand', mask_hand)
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
cont()
try ~ break 까지 비디오를 통해서 영상 가져오고 오류 검사
test = cv2.cvtColor(frame, cv2.COLOR_BGR2YCrCb) 에서는 해당 비디오를 BGR색상을 YCrCb 변환
mask_hand = cv2.inRange(test, np.array([0,133,77]),np.array([255,173,127])) 에서는 inRange로 ycrcb의 이미지를 해당 범위에 속하는 픽셀들만 masking한다. 즉 살색만 흰색을 만들고 그 나머지는 검은색으로 변환
ret, thr = cv2.threshold(mask_hand, 127, 255, cv2.THRESH_BINARY_INV) 관련 설명은 밑 사이트 참고
https://opencv-python.readthedocs.io/en/latest/doc/09.imageThresholding/imageThresholding.html
thr에 사진에 대한 정보가 들어가 있다. cv2.imshow('thr', thr)를 하면 확인 가능하다.
하지만 ret, thr = cv2.threshold(mask_hand, 127, 255, cv2.THRESH_BINARY_INV) 를 빼고 적용시켜 본 결과 딱히 큰 차이 없는 듯 이 부분은 없어도 되는 거 같다.
_, contours, hierachy=cv2.findContours(mask_hand, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) 에서 원래는
images, contours, hierachy = cv2.findContours(image, mode, method)
-
image: 흑백이미지 또는 이진화된 이미지
-
mode : 컨투어를 찾는 방법
-
cv2.RETR_EXTERNAL: 컨투어 라인 중 가장 바깥쪽의 라인만 찾음
-
cv2.RETR_LIST: 모든 컨투어 라인을 찾지만, 상하구조(hierachy)관계를 구성하지 않음
-
cv2.RETR_CCOMP: 모든 컨투어 라인을 찾고, 상하구조는 2 단계로 구성함
-
cv2.RETR_TREE: 모든 컨투어 라인을 찾고, 모든 상하구조를 구성함
-
-
method : 컨투어를 찾을 때 사용하는 근사화 방법
-
cv2.CHAIN_APPROX_NONE: 모든 컨투어 포인트를 반환
-
cv2.CHAIN_APPROX_SIMPLE: 컨투어 라인을 그릴 수 있는 포인트만 반환
-
cv2.CHAIN_APPROX_TC89_L1: Teh_Chin 연결 근사 알고리즘 L1 버전을 적용하여 컨투어 포인트를 줄임
-
cv2.CHAIN_APPROX_TC89_KCOS: Teh_Chin 연결 근사 알고리즘 KCOS 버전을 적용하여 컨투어 포인트를 줄임
-
컨투어 정보는 컨투어를 구성하는 점들로 이루어진 배열의 리스트다.
출처 : https://datascienceschool.net/view-notebook/f9f8983941254a34bf0fee42c66c5539/
hull = cv2.convexHull(i,clockwise=True) 는 cv2.convexHull()를 활용해 윤곽선에서 블록 껍질을 검출합니다.
cv2.convexHull(윤곽선, 방향)을 의미합니다.
윤곽선은 윤곽선 검출 함수에서 반환되는 구조를 사용합니다.
방향은 검출된 볼록 껍질의 볼록점들의 인덱스 순서를 의미합니다.
블록 껍질 함수는 단일 형태에서만 검출이 가능합니다.
그러므로, 반복문을 활용해 단일 형태의 윤곽선 구조에서 블록 껍질을 검출합니다.
-
Tip : 윤곽선 구조는 윤곽선 검출 함수의 반환값과 형태가 동일하다면, 임의의 배열에서도 검출이 가능합니다.
-
Tip : 방향이 True라면 시계 방향, False라면 반시계 방향으로 정렬됩니다.
convexHull에 대한 알고리즘 참고 사이트 : https://hns17.tistory.com/entry/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-ConvexHull-Grahams-Scan
만약 convexHull을 안 썼을 때 위 코드에서 일부를 밑처럼 수정
_, contours, hierachy=cv2.findContours(mask_hand, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
for i in contours:
#hull = cv2.convexHull(i,clockwise=True)
cv2.drawContours(dst, [i], 0, (0,0,255),2)
cv2.imshow('dst', dst)
cv2.imshow('mask_hand', mask_hand)
해당 결과 : 라인이 다 그려짐
외곽선과 convexhull의 선이 겹치는 지점이 손가락 끝점이라 보고 찾을 수 있는데 아래 시도해본 코드
points1 = []
for i in contours:
M = cv2.moments(i, False)
try:
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
except ZeroDivisionError:
print("ZeroDivision")
contours = cv2.approxPolyDP(contours,0.02*cv2.arcLength(contours,True),True)
hull = cv2.convexHull(contours[0])
for point in hull:
if cy > point[0][1]:
points1.append(tuple(point[0]))
cv2.drawContours(mask_hand, [hull], 0, (0,255,0), 2)
for point in points1:
cv.circle(mask_hand, tuple(point), 15, [ 0, 0, 0], -1)
손가락 끝 점 출력 코드라고 하는데 오류가 ZeroDivisionError 가 계속 난다. 실시간 동영상인 것이 아마 원인이지 않을까 싶다.
_, contours, hierachy=cv2.findContours(mask_hand, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
points1 = []
result_cx = []
result_cy = []
for i in contours:
M = cv2.moments(i)
if M["m00"] != 0:
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
else:
# set values as what you need in the situation
cX, cY = 0, 0
for cnt in contours:
approx = cv2.approxPolyDP(cnt,0.02*cv2.arcLength(cnt,True),True)
#cv2.drawContours(dst, [approx], 0, (0,255,0), 3)
hull = cv2.convexHull(approx)
for point in hull:
if cy > point[0][1]:
points1.append(tuple(point[0]))
cv2.drawContours(dst, [hull], 0, (0,0,255),2)
for point in points1:
cv2.circle(dst, tuple(point), 15, [255, 0, 0], -1)
cv2.imshow('dst', dst)
코드 오류 안 나게 수정한 부분...
그럼에도 원이 표시되지만 이상하게 뜨네요. 아마 원인은 손만 나와야하는데 주변에 잡인식이 많아서 그런 것 같네요. 다음에는 일단 배경 정리부터 다시 해야할 듯 하네요.
밑에는 풀코드.. 주석처리도 많고 더럽네요 나중에 오류 해결하면 코드 정리해야겠어요ㅠ
import cv2
import numpy as np
def cont():
try:
cap=cv2.VideoCapture(0)
except:
print('camera_errro')
return
while True:
ret, frame = cap.read()
if not ret:
print('camera2_error')
break
dst = frame.copy()
#cv2.imshow('frame', frame)
#gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#gray = cv2.equalizeHist(gray)
#rects = detect(gray, debug=False)
#height,width = frame.shape[:2]
#for x1, y1, x2, y2 in rects:
# cv.rectangle(frame, (x1-10, 0), (x2+10, height), (0,0,0), -1)
#cv2.imshow('frame1', frame1)
test = cv2.cvtColor(frame, cv2.COLOR_BGR2YCrCb)
mask_hand = cv2.inRange(test, np.array([0,133,77]),np.array([255,173,127]))
#cv2.imshow('mask_hand', mask_hand)
#test = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#ret, thr = cv2.threshold(mask_hand, 127, 255, cv2.THRESH_BINARY_INV)
#cv2.imshow('thr', thr)
_, contours, hierachy=cv2.findContours(mask_hand, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
points1 = []
result_cx = []
result_cy = []
for i in contours:
M = cv2.moments(i)
if M["m00"] != 0:
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
else:
# set values as what you need in the situation
cX, cY = 0, 0
for cnt in contours:
approx = cv2.approxPolyDP(cnt,0.02*cv2.arcLength(cnt,True),True)
#cv2.drawContours(dst, [approx], 0, (0,255,0), 3)
hull = cv2.convexHull(approx)
for point in hull:
if cy > point[0][1]:
points1.append(tuple(point[0]))
cv2.drawContours(dst, [hull], 0, (0,0,255),2)
for point in points1:
cv2.circle(dst, tuple(point), 15, [255, 0, 0], -1)
cv2.imshow('dst', dst)
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
cont()
그 밖에 참고 사이트 : https://webnautes.tistory.com/1378
https://076923.github.io/posts/Python-opencv-25/
https://m.blog.naver.com/pckbj123/100203325426
나중에 참고할 사이트 : https://dbpia.co.kr/journal/articleDetail?nodeId=NODE02367971#none
'Project' 카테고리의 다른 글
GameProgramming Project - 유니티 Shader를 이용한 비와 물결 구현 (1) | 2020.02.20 |
---|---|
파이썬으로 영화 예매 오픈 알리미 만들기-2 [완료] (3) | 2020.02.11 |
파이썬으로 내가 원하는 공지 알림 받기 [응용편] (0) | 2020.02.10 |
파이썬으로 영화 예매 오픈 알리미 만들기-1 (0) | 2020.02.10 |
수화 인식 프로젝트 - [4일차] 배경 지우기(openCV) (0) | 2020.02.08 |
댓글