OpenCV/OpenCV 강좌
주사위 눈 개수 세는 OpenCV Python 예제
webnautes
2023. 10. 20. 07:13
반응형
주사위 눈 개수를 세는 OpenCV Pytrhon 예제 코드입니다.
깃허브에서 오래전에 발견했던 코드를 수정했습니다. 주사위 눈을 세는 부분을 공유안해주셨지만 힌트가 포함되어 있어서 다행히 동작하도록 수정했네요.
https://github.com/arnavdutta/OpenCV-Contours-Hierarchy/blob/master/OpenCV_Contours.ipynb
2023. 5. 28 최초작성
이진화 실행 결과입니다.
주사위 눈 검출 결과입니다. 주사위마다 표시된 빨간색 숫자는 눈의 개수이며 보라색 작은 숫자들은 검출된 컨투어의 인덱스 입니다. 왼쪽위에 표시된 28은 주사위 전체 눈 개수입니다.
전체 소스 코드입니다.
import cv2 import numpy as np image = cv2.imread('dice.png') image_copy = image.copy() # 컨투어 검출하기 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5, 5), 0) t, binary = cv2.threshold(blur, -1, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) dict_i = {} # 주사위를 검출한 컨투어를 찾습니다. for i, (c,h) in enumerate(zip(contours,hierarchy[0])): rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.intp(box) p1 = box[0] p2 = box[1] p3 = box[2] dist1 = np.linalg.norm(p1-p2) dist2 = np.linalg.norm(p2-p3) if dist2 == 0: dist2 = 0.000001 if dist1/dist2 > 0.8 and dist1/dist2 < 1.5: if h[3] == -1: dict_i[i] = [] # 주사위 눈을 검출한 컨투어를 찾습니다. total_pips = [] for i, (c,h) in enumerate(zip(contours,hierarchy[0])): if h[3] in dict_i.keys(): rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.intp(box) p1 = box[0] p2 = box[1] p3 = box[2] dist1 = np.linalg.norm(p1-p2) dist2 = np.linalg.norm(p2-p3) if dist2 == 0: dist2 = 0.000001 if dist1/dist2 > 0.8 and dist1/dist2 < 1.5: dict_i[h[3]].append(i) total_pips.append(i) list_del = [] for key in dict_i.keys(): if len(dict_i[key]) == 0: list_del.append(key) for del_item in list_del: del dict_i[del_item] print('주사위 목록') print(dict_i) for index, (c,h) in enumerate(zip(contours,hierarchy[0])): rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.intp(box) x, y, _, _ = cv2.boundingRect(c) # 주사위 눈 리스트 생성 list_item = [] for i in dict_i.values(): list_item = list_item + i if index in dict_i.keys() or index in list_item: # 주사위와 주사위 눈을 그려줌 cv2.drawContours(image_copy, [box], 0, (255, 0, 150), 3) # 주사위 눈 개수 출력 if index in dict_i and len(dict_i[index]) > 0: cv2.putText(image_copy, str(len(dict_i[index])), (x+100, y-5), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 2, cv2.LINE_AA) # 컨투어 인덱스 출력 cv2.putText(image_copy, str(index), (x+20, y-5), cv2.FONT_HERSHEY_SIMPLEX, 1, (200, 140, 140), 1, cv2.LINE_AA) # 전체 주사위 눈 개수 출력 cv2.putText(image_copy, f'total = {len(total_pips)}', (100,200), cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 0, 255), 2, cv2.LINE_AA) binary = cv2.resize(binary, None, fx=0.5, fy=0.5) image_copy = cv2.resize(image_copy, None, fx=0.5, fy=0.5) cv2.imshow('result', binary) cv2.waitKey(0) cv2.imshow('result', image_copy) cv2.waitKey(0) |
테스트에 사용한 이미지입니다.
반응형