반응형

 

 

색깔있는 도형에  도형의 색 이름을 표시해주는 예제 코드입니다.

 

컨투어로 도형 내부 영역을 검출한 다음 평균으로 도형의 색을 계산합니다.

그리고 미리 지정해놓은 색들과 거리를 계산하여 가장 가까운 색으로 이름을 붙여줍니다.   

 



# 원본 코드 - https://www.pyimagesearch.com/2016/02/15/determining-object-color-with-opencv/
# 수정 - webnautes
import cv2
import numpy as np
from scipy.spatial import distance as dist



# Contour 영역 내에 텍스트 쓰기
# https://github.com/bsdnoobz/opencv-code/blob/master/shape-detect.cpp
def setLabel(image, str, contour):

   fontface = cv2.FONT_HERSHEY_SIMPLEX
   scale = 0.6
   thickness = 2

   size = cv2.getTextSize(str, fontface, scale, thickness)
   text_width = size[0][0]
   text_height = size[0][1]

   x, y, width, height = cv2.boundingRect(contour)

   pt = (x + int((width - text_width) / 2), y + int((height + text_height) / 2))
   cv2.putText(image, str, pt, fontface, scale, (255, 255, 255), thickness, 8)



# 컨투어 내부의 색을 평균내서 red, green, blue 중 어느 색인지 체크
def label(image, contour):


   mask = np.zeros(image.shape[:2], dtype="uint8")
   cv2.drawContours(mask, [contour], -1, 255, -1)

   mask = cv2.erode(mask, None, iterations=2)
   mean = cv2.mean(image, mask=mask)[:3]


   minDist = (np.inf, None)



   for (i, row) in enumerate(lab):

       d = dist.euclidean(row[0], mean)

       if d < minDist[0]:
           minDist = (d, i)

   return colorNames[minDist[1]]



# 인식할 색 입력
colors = [[0, 0, 255], [0, 255, 0], [255, 0, 0]]
colorNames = ["red", "green", "blue"]



lab = np.zeros((len(colors), 1, 3), dtype="uint8")
for i in range(len(colors)):
   lab[i] = colors[i]

lab = cv2.cvtColor(lab, cv2.COLOR_BGR2LAB)




# 원본 이미지 불러오기
image = cv2.imread("example_shapes.png", 1)


blurred = cv2.GaussianBlur(image, (5, 5), 0)

# 이진화
gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)

# 색검출할 색공간으로 LAB사용
img_lab = cv2.cvtColor(blurred, cv2.COLOR_BGR2LAB)

thresh = cv2.erode(thresh, None, iterations=2)
cv2.imshow("Thresh", thresh)


# 컨투어 검출
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)


# 컨투어 리스트가 OpenCV 버전에 따라 차이있기 때문에 추가
if len(contours) == 2:
   contours = contours[0]

elif len(contours) == 3:
   contours = contours[1]


# 컨투어 별로 체크
for contour in contours:

   cv2.imshow("Image", image)
   cv2.waitKey(0)

   # 컨투어를 그림
   cv2.drawContours(image, [contour], -1, (0, 255, 0), 2)


   # 컨투어 내부에 검출된 색을 표시
   color_text = label(img_lab, contour)
   setLabel(image, color_text, contour)


cv2.imshow("Image", image)
cv2.waitKey(0)





반응형

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

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

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

  1. Favicon of https://jjiangbbang.tistory.com BlogIcon 성구사마 2020.09.18 11:52 신고

    안녕하세요? 엄청 많이 배우고 있는 구독자입니다. 유투브도 잘보고 있습니다.
    질문이 하나 있는데 혹시
    저렇게 컨투어로 각종 모양의 외곽선을 찾았는데 컨투어한 물체 안에 음영이 좀 있어서 컨투어 안에 또 컨투어가 생기는 현상은 어떻게 처리해야할까요?

    pcb를 찾는 알고리즘을 만들고 있는 pcb를 찾고 그안에 작은 홈들을 또 찾아내 너무 지저분하게 많이 잡는데 ....
    크기로 조건을 주는것도 좋겠지만 케이스가 다양해 혹시 다른 방법이 있는 지 여쭙습니다.

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

      이진화를 하기 전에 컬러 혹은 흑백 이미지에서 잡음을 제거하는 방법을 찾아보면 어떨까 싶습니다.

  2. Siri 2020.10.19 16:34

    안녕하세요 많이 배우고 있는 구독자 입니다.
    c++환경에서 컨투어 내부가 비어있는지(색이 있는지 없는지) 판단하려고 합니다.
    적외선 카메라를 사용할 예정이라 그레이 스케일로 변환하여 각 2개의 도형의 색이 있는지 없는지 판단하려 합니다. (총 4가지 경우)

    c++로 색상 탐지 혹은 도형 내부 탐색(빈 도형 채워진 도형 구분)이 가능할까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.10.19 18:43 신고

      간단히 생각하면 내부에 채워진 픽셀의 값들의 평균값을 가지고 일정값을 넘으면 채워진것(흰색영역)이라 볼 수 있을듯합니다만.. 임계값을 정하기 어렵기때문에 고민이 필요할듯합니다. 특정 환경에만 잘 동작할수 있을듯합니다

+ Recent posts