쫑쫑JJONG
끄적끄적 오후5시37분
쫑쫑JJONG
전체 방문자
오늘
어제
  • 분류 전체보기 (198)
    • Paper Reading (5)
    • Math (5)
    • Data Science (13)
      • SQL (12)
      • Data Analyst (1)
    • AI Track (32)
      • CV (21)
      • CV Remind (2)
      • NLP (1)
      • AI Basic (8)
    • Python (1)
      • Basic (8)
      • Application (5)
    • Robotics (31)
      • ROS (15)
      • Collabot_proj (16)
    • NaverBoost Camp 4기 (45)
      • 부스트일지 (13)
      • [P stage] Image Classificat.. (4)
      • [P stage] Object Detection (12)
      • [P stage] Semantic Segmenta.. (6)
      • [P stage] Final Project (5)
      • CV (1)
      • DL BASIC (4)
    • Excel (1)
    • Git (8)
      • Git (8)
    • Network (3)
      • 통신 (3)
    • 코테준비 (14)
      • Programmers (11)
      • 기타 (3)
    • 환경설정 (19)
    • etc (7)
      • 활동 (2)
      • TIP (3)
      • 잡동사니 (2)
    • 금융관련 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • 포트폴리오

인기 글

태그

  • N
  • CV
  • Confusion Matrix
  • collabot
  • error
  • Data Scraping
  • segmentation
  • python
  • GIT
  • robotics
  • diffusion
  • Monte Carlo Sampling
  • 논문분석
  • 이고잉
  • transformer
  • NLP
  • mmdetection
  • ros
  • SQL
  • 환경설정
  • Arduino

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
쫑쫑JJONG

끄적끄적 오후5시37분

[openCV] Trackbar HSV범위를 이용한 Contour
AI Track/CV

[openCV] Trackbar HSV범위를 이용한 Contour

2022. 11. 11. 21:42
728x90

 

라인트레이싱과 색상검출에 있어서

내가 원하는 색상의 hsv값의 범위를 구하는 것이 필수적이였다

이를 좀 간편하게 하기위해 트랙바를 이용하기로 결정

 

<코드 설명>

 

def callback(x):  => trackbar의 변화를 즉시 변수에 대입 시켜준다
    global H_low,H_high,S_low,S_high,V_low,V_high
    외부 코드에 영향을 줘야하기 때문에 global로 선언
    
    H_low = cv2.getTrackbarPos('low H','controls')
    H_high = cv2.getTrackbarPos('high H','controls')
    S_low = cv2.getTrackbarPos('low S','controls')
    S_high = cv2.getTrackbarPos('high S','controls')
    V_low = cv2.getTrackbarPos('low V','controls')
    V_high = cv2.getTrackbarPos('high V','controls')

   트랙바의 변화를 감지하여서 각각의 변수에 저장


cv2.namedWindow('controls',2)

창의 이름을 설정해주고
cv2.resizeWindow("controls", 550,10)

사이즈가 무지성으로 커지는 것을 방지해준다

 

H_low = 0
H_high = 179
S_low= 0
S_high = 255
V_low= 0
V_high = 255

전역변수를 초기화 시켜주고


cv2.createTrackbar('low H','controls',0,255,callback)
cv2.createTrackbar('high H','controls',225,225,callback)
cv2.createTrackbar('low S','controls',0,255,callback)
cv2.createTrackbar('high S','controls',255,255,callback)
cv2.createTrackbar('low V','controls',0,255,callback)
cv2.createTrackbar('high V','controls',255,255,callback)

트랙바를 생성 시켜 주는 데 createTrackbar("트랙바 이름, 윈도우 창 제목, 최솟값,최댓값,콜백함수")

※주의 : "트랙바 이름"과 "윈도우 창 제목"은 일종의 변수 역할이기 때문에 callback함수랑 이름을 일치시켜야 한다

 

*라즈베리파이랑 연동하기 위한 기본 세팅 (라즈베리파이에서는 cv2.VideoCapture(-1)로 바꿔야한다)

W_View_size = 640
H_View_size = int(W_View_size / 1.777)
FPS = 90  # PI CAMERA: 320 x 240 = MAX 90
try:
    cap = cv2.VideoCapture(0)  # 카메라 켜기  # 카메라 캡쳐 (사진만 가져옴)
    cap.set(3, W_View_size)
    cap.set(4, H_View_size)
    cap.set(5, FPS)
except:
    print('cannot load camera!')

 

while (True): 

   계속 갱신 받는 느낌이여서 while 문에 밑에 두줄 넣음 
    lower =  np.array([H_low, S_low, V_low])
    higher = np.array([H_high, S_high, V_high])


    ret, frame = cap.read()  # 영상파일 읽어드리기

    일종의 cao는 연결이라 생각하고 cap.read()는 영상을 이미지로 capture하는 느낌이라 이해하면 된다

    그렇기에 무조건 while문 속에 들어가야한다

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    RGB를 HSV로 바꿔주고  

    mask_color = cv2.inRange(hsv, lower, higher) 

    밑에 사용할 색상 범위 변수를 지정 (색상의 최댓값 최솟값이용)
    res_color = cv2.bitwise_and(frame, frame, mask=mask_color) 

    이진화를 이용해 범위안에 있으면 1 없으면 0 => 범위내 색상만 뽑아준다 

   

 

 # 모폴로지

모폴로지 변환(Perspective Transformation)은 영상이나 이미지를 형태학적 관점에서 접근하는 기법을 의미합니다.

모폴로지 변환은 주로 영상 내 픽셀값 대체에 사용됩니다. 이를 응용해서 노이즈 제거, 요소 결합 및 분리, 강도 피크 검출 등에 이용할 수 있습니다.

(출처 : https://076923.github.io/posts/Python-opencv-26/)


    k = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

 

   cv2.getStructuringElement(커널의 형태, 커널의 크기, 중심점)로 구조 요소을 생성.

   커널의 형태는 직사각형(Rect), 십자가(Cross), 타원(Ellipse).

   커널의 크기는 구조 요소의 크기를 의미 (커널의 크기가 너무 작다면 커널의 형태는 영향을 받지 않음)

   고정점은 커널의 중심 위치를 나타냄 (필수는 x )


    dst = cv2.dilate(res_color, k) 

 

<dilate> -> 팽창

커널 영역 안에 존재하는 모든 픽셀의 값을 커널 내부의 극댓값(local maximum)으로 대체

즉, element(구조 요소)를 이용하여서 픽셀들을 통일 시킴

어두운 부분이 줄어들고 밝은 영역이 늘어난다시행하면 할 수록 객체 내부의 구멍이 사라진다노이즈 제거 후 줄어든 크기를 복구하고자 할 때 사용

 

<erode> -> 침식

커널 영역 안에 존재하는 모든 픽셀의 값을 커널 내부의 극댓값(local minimum)으로 대체

즉, element(구조 요소)를 이용하여서 픽셀들을 통일 시킴

밝은 영역이 줄어들고 어두운 영역이 늘어남

객체내부의 구멍이 커진다

노이즈 제거에 주로 사용 

 

    imgray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)

   가우시안 블러를 사용하기 위해 RGB를 GRAY scale로 변환

    cam = cv2.GaussianBlur(imgray, (3, 3), 0)  # 가우시안 블러

 

<가우시안 블러>

중심에 있는 픽셀에 높은 가중치를 부여해준다

canny edge등등 사용하기 전에 노이즈를 제거하기 위해 사용

(이 경우 Contour를 하기위한 전처리 과정)

세번째 argument에 0을 지정하면 커널에 크기에 맞춰 시그마를 계산해서 사용



    _, cam_binary = cv2.threshold(cam, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # 이진화

cv2.threshold -> 이미지 임계처리 (영상을 흑백으로 만들어 준다 (진짜 255 or 0 ))

픽셀 값을 127을 기준으로 작으면 0 크면 255 처리를 해준다

cv2.THRESH_BINARY: 픽셀 값이 임계값을 넘으면 value로 지정하고, 넘지 못하면 0으로 지정
cv2.THRESH_BINARY_INV: cv.THRESH_BINARY의 반대
cv2.THRESH_TRUNC: 픽셀 값이 임계값을 넘으면 value로 지정하고, 넘지 못하면 원래 값 유지
cv2.THRESH_TOZERO: 픽셀 값이 임계값을 넘으면 원래 값 유지, 넘지 못하면 0으로 지정
cv2.THRESH_TOZERO_INV: cv2.THRESH_TOZERO의 반대

 

cv2.THRESJ_OTSU는 뭘까? -> 오츠의 이진화 알고리즘 (임계값에 영향 x 즉 위의 127,255에 영향 x)

임계값을 임의로 정해 픽셀을 두 분류로 나누고 두 부류의 명암 분포를 구하는 작업을 반복

명암 분포가 가장 균일 할 때를 임계값으로 선택

이 경우 t는 120 ~ 140 으로 결정된다

이 두개를 "or" 연산으로 때려서 좀더 다양한 표현을 생성

 


    contours, hierarchy = cv2.findContours(cam_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  # 컨투어
위에 이진화된 이미지를 사용하여서 contour를 찾는 코드

 

 

<cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None) -> contours, hierarchy>

1. image -> 무조건 binary (이진) image

2. mode : 외각선 검출 방법 -> 4가지가 존재

- RETR_EXTERNAL : 계층 정보 x , 바깥 외각선만 검출 (단순히 리스트로 묶어준다)

- RETR_LIST : 계층 정보 x, 모든 외각선을 검출한다, (바깥, 안쪽 순서는 랜덤)

- RETR_CCOMP : 계층 구조를 2층까지만 만듬, 2층이 넘어가면 1층 취급

- RETR_TREE : 계층구조를 만듬

 

3. method : 외각선 근사화 방법

- NONE : 주로 사용(기본값)

- SIMPLE : 수직선,수평선,대각선에 대해 끝점을 저장 

 

4. contours(선택) : 검출한 컨투어 좌표 (numpy.ndarray로 구성된 리스트)

 

5. hierarchy(선택) : 컨투어계층 정보 (numpy.ndarray.shape(1,N,4).dtype=numpy.int32)

hierarchy[0,i,0] -> hierarchy[0,i,3] 순서대로 next, prev,child,parent 외각선

 

6. offset(선택) : ROI 등으로 인해 이동한 좌표의 오프셋

 

 

<hierarchy >

print(hierarchy)

-1 : 아무것 도 없음

0번 : 첫 번째 도형 컨투어 (삼각형 외각)

다음 도형은 2 이고(동그라미 외각)

Child는 1 이다 (삼각형 내각)

 

그러므로 최외각을 뽑고 싶으면 부모항목이 -1인 애들만 뽑으면 된다

 

import cv2
import numpy as np
img = cv2.imread('./test.jpg')
img = cv2.resize(img,(700,350))
img2,img3,img4  = img.copy(),img.copy(),img.copy()

imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, imthres = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY_INV)
contour, hierarchy = cv2.findContours(imthres, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
contour2, hierarchy = cv2.findContours(imthres, cv2.RETR_LIST ,cv2.CHAIN_APPROX_SIMPLE)
contour3, hierarchy = cv2.findContours(imthres, cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
contour4, hierarchy = cv2.findContours(imthres, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)


for idx, cont in enumerate(contour): 
    color = [int(i) for i in np.random.randint(0,255, 3)]
    cv2.drawContours(img, contour, idx, color, 3)
    cv2.putText(img, str(idx), tuple(cont[0][0]), cv2.FONT_HERSHEY_PLAIN,1, (0,0,255))

for idx, cont in enumerate(contour2): 
    color = [int(i) for i in np.random.randint(0,255, 3)]
    cv2.drawContours(img2, contour2, idx, color, 3)
    cv2.putText(img2, str(idx), tuple(cont[0][0]), cv2.FONT_HERSHEY_PLAIN,1, (0,0,255))

for idx, cont in enumerate(contour3): 
    color = [int(i) for i in np.random.randint(0,255, 3)]
    cv2.drawContours(img3, contour3, idx, color, 3)
    cv2.putText(img3, str(idx), tuple(cont[0][0]), cv2.FONT_HERSHEY_PLAIN,1, (0,0,255))

for idx, cont in enumerate(contour4):
    color = [int(i) for i in np.random.randint(0,255, 3)]
    cv2.drawContours(img4, contour4, idx, color, 3)
    cv2.putText(img4, str(idx), tuple(cont[0][0]), cv2.FONT_HERSHEY_PLAIN,1, (0,0,255))

# 화면 출력
cv2.imshow('RETR_EXTERNAL', img)
cv2.imshow('RETR_LIST', img2)
cv2.imshow('RETR_CCOMP', img3)
cv2.imshow('RETR_TREE', img4)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

 

    if len(contours) == 0:
        print("색상 인식 x")

       이 부분없으면 에러나서...

    else:
        contr = contours[0] .#첫번째 컨투어를 가져옴
        x, y, w, h = cv2.boundingRect(contr)  

       cv2.boundingRect(contr) 최소한의 사각형을 뽑아주는 함수
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)

       #사각형을 그려줌 

        print("지정색깔 감지"," 좌표 : (", x+0.5*w, " , ",y+0.5*h ,")")

       #중앙의 좌표를 뽑아줌
    cv.imshow("Original", frame)  # 원본파일
    cv.imshow("detection range", res_color)  # 노랑감지

 

<완성 코드>

import cv2
import cv2 as cv
import numpy as np
from time import sleep


#trackbar callback fucntion to update HSV value
def callback(x):
	global H_low,H_high,S_low,S_high,V_low,V_high
	#assign trackbar position value to H,S,V High and low variable
	H_low = cv2.getTrackbarPos('low H','controls')
	H_high = cv2.getTrackbarPos('high H','controls')
	S_low = cv2.getTrackbarPos('low S','controls')
	S_high = cv2.getTrackbarPos('high S','controls')
	V_low = cv2.getTrackbarPos('low V','controls')
	V_high = cv2.getTrackbarPos('high V','controls')


#create a seperate window named 'controls' for trackbar
cv2.namedWindow('controls',2)
cv2.resizeWindow("controls", 550,10);


#global variable
H_low = 0
H_high = 179
S_low= 0
S_high = 255
V_low= 0
V_high = 255

#create trackbars for high,low H,S,V 
#create trackbars for high,low H,S,V 
cv2.createTrackbar('low H','controls',0,255,callback)
cv2.createTrackbar('high H','controls',225,225,callback)

cv2.createTrackbar('low S','controls',0,255,callback)
cv2.createTrackbar('high S','controls',255,255,callback)

cv2.createTrackbar('low V','controls',0,255,callback)
cv2.createTrackbar('high V','controls',255,255,callback)


W_View_size = 640
H_View_size = int(W_View_size / 1.777)
FPS = 90  # PI CAMERA: 320 x 240 = MAX 90

try:
    cap = cv2.VideoCapture(0)  # 카메라 켜기  # 카메라 캡쳐 (사진만 가져옴)

    cap.set(3, W_View_size)
    cap.set(4, H_View_size)
    cap.set(5, FPS)

except:
    print('cannot load camera!')
while (True):
    lower =  np.array([H_low, S_low, V_low])
    higher = np.array([H_high, S_high, V_high])
    ret, frame = cap.read()  # 영상파일 읽어드리기
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    mask_color = cv2.inRange(hsv, lower, higher)  # 노랑최소최대값을 이용해서 maskyellow값지정
    res_color = cv2.bitwise_and(frame, frame, mask=mask_color)  # 노랑색만 추출하기

    # 모폴로지
    k = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    dst = cv2.dilate(res_color, k)

    imgray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)

    cam = cv2.GaussianBlur(imgray, (3, 3), 0)  # 가우시안 블러

    ret, cam_binary = cv2.threshold(cam, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # 이진화
    contours, hierarchy = cv2.findContours(cam_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  # 컨투어

    if len(contours) == 0:
        print("정상 상태")

    else:
        contr = contours[0]
        #rect = cv2.minAreaRect(contr)
        x, y, w, h = cv2.boundingRect(contr)  # 최소한의 사각형 그려주는 함수
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
        #box = cv2.boxPoints(rect)   # 중심점과 각도를 4개의 꼭지점 좌표로 변환
        #box = np.int0(box)          # 정수로 변환
        #cv2.drawContours(frame, [box], -1, (0,255,0), 3)
        print("지정색깔 감지"," 좌표 : (", x+0.5*w, " , ",y+0.5*h ,")")


    cv.imshow("Original", frame)  # 원본파일
    cv.imshow("detection range", res_color)  # 노랑감지

    if cv2.waitKey(1) == 27:
        break

cap.release()
cv2.destroyAllWindows()


#cv2.drawContours(이미지, [윤곽선], 윤곽선 인덱스, (B, G, R), 두께, 선형 타입)

 

ㅋㅋㅋㅋㅋㅋㅋ지금 내 상황

참고

https://bkshin.tistory.com/entry/OpenCV-8-%EC%8A%A4%EB%A0%88%EC%8B%9C%ED%99%80%EB%94%A9Thresholding

 

OpenCV - 8. 스레시홀딩(Thresholding), 오츠의 알고리즘(Otsu's Method)

이번 포스팅에서는 바이너리 이미지를 만드는 대표적인 방법인 스레시홀딩에 대해 알아보겠습니다. 이번 포스팅 역시 '파이썬으로 만드는 OpenCV 프로젝트(이세우 저)'를 정리한 것임을 밝힙니다

bkshin.tistory.com

https://076923.github.io/posts/Python-opencv-35/

 

Python OpenCV 강좌 : 제 35강 - 트랙 바

트랙 바(Track Bar)

076923.github.io

https://bkshin.tistory.com/entry/OpenCV-22-%EC%BB%A8%ED%88%AC%EC%96%B4Contour

 

OpenCV - 22. 컨투어(Contour)

이번 포스팅에서는 영상 분할 방법 중 하나인 컨투어에 대해 알아보겠습니다. 이번 포스팅 역시 '파이썬으로 만드는 OpenCV 프로젝트(이세우 저)'를 정리한 것임을 밝힙니다. 코드: github.com/BaekKyunS

bkshin.tistory.com

 

728x90
저작자표시 비영리 변경금지

'AI Track > CV' 카테고리의 다른 글

[Obj Det] Fast, Faster R-CNN, SPPNet (2 Stage Detectors)  (0) 2022.11.21
[Obj Det] Basic of Object Detection(정의, mAP 등등)  (0) 2022.11.17
[openCV] Houghline(허프변환)을 이용한 중앙선 및 각도 검출  (2) 2022.11.12
[openCV] linetracer 중앙정렬  (1) 2022.11.09
[openCV] cv2.imshow 창이 안뜨는 문제 해결  (0) 2022.11.09
    'AI Track/CV' 카테고리의 다른 글
    • [Obj Det] Basic of Object Detection(정의, mAP 등등)
    • [openCV] Houghline(허프변환)을 이용한 중앙선 및 각도 검출
    • [openCV] linetracer 중앙정렬
    • [openCV] cv2.imshow 창이 안뜨는 문제 해결
    쫑쫑JJONG
    쫑쫑JJONG
    connect : tmdwhd619@naver.com

    티스토리툴바