"OpenCV"의 두 판 사이의 차이

Pywiki
둘러보기로 가기 검색하러 가기
태그: 모바일 웹 편집 모바일 편집
 
(다른 사용자 한 명의 중간 판 4개는 보이지 않습니다)
2번째 줄: 2번째 줄:
 
오픈소스 컴퓨터 비전 라이브러리. 실시간 이미지 프로세싱에 중점을 두었다.
 
오픈소스 컴퓨터 비전 라이브러리. 실시간 이미지 프로세싱에 중점을 두었다.
 
주로 이미지를 읽거나 영상을 읽고 연산을 적용한 후 표시, 다른 파일로 저장하는 용으로 쓰인다.
 
주로 이미지를 읽거나 영상을 읽고 연산을 적용한 후 표시, 다른 파일로 저장하는 용으로 쓰인다.
 +
 +
Numpy에 유일하다시피 의존한다. 기본적으로 이미지를 배열처리.
  
 
== 준비 ==
 
== 준비 ==
22번째 줄: 24번째 줄:
 
|}
 
|}
  
== 기초 사용 ==
+
= 기초 사용 =
 
{| class="wikitable"
 
{| class="wikitable"
 
!의도
 
!의도
31번째 줄: 33번째 줄:
 
|
 
|
 
|import cv2
 
|import cv2
 +
|-
 +
|
 +
|
 +
|
 +
|-
 +
|
 +
|
 +
|
 +
|}
 +
 +
== 이미지 관련 ==
 +
{| class="wikitable"
 +
!의도
 +
!설명
 +
!방법
 +
|-
 +
|이미지 읽기
 +
|이미지파일을 읽고 창에 띄운다.
 +
{| class="wikitable"
 +
!읽기모드
 +
!설명
 +
|-
 +
|cv2.IMREAD_COLOR
 +
|컬러(BGR) 스케일로 받는다.(디폴트)
 +
|-
 +
|cv2.IMREAD_UNCHANGED
 +
|파일 그대로
 +
|-
 +
|cv2.IMREAD_GRAYSCALE
 +
|흑백으로 읽기
 +
|}
 +
|<syntaxhighlight lang="python">
 +
img = cv2.imread('이미지 경로', 읽기모드)
 +
cv2.imshow('창이름', img)  # 창이름을 가진 창에 이미지를 띄운다.
 +
cv2.waitKey(0)  # 아무 키가 입력될 때까지 대기. 이미지를 띄울 때 이게 없으면 바로 끝난다. 눌린 키에 대응하여 값을 반환한다.
 +
cv2.destroyAllWindows()  # 모든 창 닫기.
 +
</syntaxhighlight>
 +
|-
 +
|이미지 저장
 +
|처리 후 다시 저장하기 위해.
 +
|<syntaxhighlight lang="python">
 +
cv2.imwrite('저장경로', img)  # 파일 포멧까지 지정해주어야 한다.
 +
</syntaxhighlight>
 +
|}
 +
 +
== 영상 관련 ==
 +
{| class="wikitable"
 +
!의도
 +
!설명
 +
!방법
 
|-
 
|-
 
|영상 불러오기
 
|영상 불러오기
36번째 줄: 88번째 줄:
 
인수로 영상파일 경로를 주면 파일을 열어 분석한다.
 
인수로 영상파일 경로를 주면 파일을 열어 분석한다.
 
|<syntaxhighlight lang="python">
 
|<syntaxhighlight lang="python">
cap = cv2.VideoCapture(0)
+
cap = cv2.VideoCapture(0) # 경로가 아닌 숫자라면, 카메라 번호를 의미한다.
  
 
while True:
 
while True:
     ret, img = cap.read()
+
     ret, img = cap.read() # read로 프레임을 하나씩 읽는다.
     if not ret:  # 해당 프레임이 있으면 ret에 True가 담긴다.
+
     if not ret:  # ret엔 cap.isOpened() 가 담겨 영상이 열려있는지 여부를 반환한다.
         breat
+
         break
 
     # 프레임 하나하나 이미지 처리되어 img 객체에 담기니, 이를 처리하면 된다.
 
     # 프레임 하나하나 이미지 처리되어 img 객체에 담기니, 이를 처리하면 된다.
 +
    cv2.imshow('창이름', img)  # 창을 열어 보여준다. 프레임마다 빠르게 불러 영상처럼.
 +
    if cv2.waitKey(1) != -1:  # 아무 키가 입력될 때까지 ms단위로 대기. 파일에 따라 다른 값을 준다. 너무 빠르게 넘어가면 볼 수가 없어.
 +
        break  # 아무 키가 입력되면 멈춘다. 아무 키가 없으면 -1 반환.
 +
cap.release()  # 객체에서 사용하던 자원을 반납한다.
 +
cv2.destroyAllWindows()
 
</syntaxhighlight>
 
</syntaxhighlight>
 
|-
 
|-
|영상 내보내기
+
|영상 보여주기
 
|처리한 영상을 img에 담으면 각 프레임마다
 
|처리한 영상을 img에 담으면 각 프레임마다
 
'창이름'이라는 창을 띄워 매끄러운 영상으로 보여준다.
 
'창이름'이라는 창을 띄워 매끄러운 영상으로 보여준다.
 +
 +
 +
print함수로 코드 중간을 점검하듯, imshow로 점검한다.
 
|<syntaxhighlight lang="python">
 
|<syntaxhighlight lang="python">
 
cv2.imshow('창이름', img)
 
cv2.imshow('창이름', img)
 
cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
 
cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
|-
 +
|영상 속성 보기
 +
|객체.get 함수를 이용하면 볼 수 있다.
 +
|cap.get(cv2.CAP_PROP_FPS)  # 해당 영상의 초당 프레임 수를 구한다.
 +
{| class="wikitable"
 +
!속성
 +
!설명
 +
|-
 +
|cv2.PROP_FRAME_WIDTH
 +
|프레임의 폭
 +
|-
 +
|cv2.PROP_FRAME_HEIGHT
 +
|프레임 높이
 +
|-
 +
|cv2.PROP_POS_AVI_RATIO
 +
|동영상 파일의 현재 위치(0~1 사이.)
 +
|}
 +
이외 수많은 속성들이 있다.
 +
|-
 +
|영상 속성 지정
 +
|객체.set 함수를 이용해 속성값을 지정할 수 있다.
 +
|cap.set(cv2.PROP_FRAME_WIDTH, 320)  # 영상의 폭을 320으로 지정.
 +
{| class="wikitable"
 +
!속성
 +
!설명
 +
|-
 +
|cv2.PROP_FRAME_WIDTH
 +
|프레임의 폭
 +
|}
 +
|-
 +
|영상 저장(특정프레임)
 +
|특정 프레임을 이미지로 저장.
 +
이미지의 저장과 동일하다.
 +
|다음 코드를 적절한 곳에 추가하면 된다.<syntaxhighlight lang="python">
 +
if cv2.waitKey(1) != -1:  # 아무 키가 입력될 때까지 ms단위로 대기.
 +
    cv2.imwrite('사진경로.jpg', img)  # 해당 이미지를 저장한다.
 +
</syntaxhighlight>
 +
|-
 +
|영상 저장(특정구간)
 +
|특정 구간을 영상으로 저장.
 +
적절한 fourcc값은 [https://www.fourcc.org/codecs.php 링크]에서 찾아보자.
 +
|<syntaxhighlight lang="python">
 +
# 사전 인수 설정.
 +
file_path = '주소.avi'
 +
fourcc = cv2.VideoWriter_fourcc(*'DIVX')  # 비디오인코딩 형식(4글자)
 +
 +
# 비디오 저장 클래스 객체를 생성한다.
 +
writer = cv2.VideoWriter(file_path, fourcc,
 +
                        fps,  # 초당 프레임
 +
                        (width, height)  # 크기
 +
)
 +
 +
while True:
 +
    ret, img = cap.read()
 +
    ...
 +
    writer.write(img)  # 해당 프레임을 쓴다.
 +
    if cv2.waitKey(1) != -1:  # 아무 키가 입력될 때까지 ms단위로 대기.
 +
        break  # 키를 누르면 녹화를 멈춘다.
 +
   
 +
writer.release()  # 파일을 닫는다.(자원 반환)
 +
   
 +
 +
</syntaxhighlight>
 +
|}
 +
 +
=== 팁 ===
 +
너무 고화질의 영상이라면 픽셀 수가 많아 연산하는 데 오래걸린다. 때문에 프레임 폭, 높이 조절로 픽셀 수를 줄이는 편이 이득.<syntaxhighlight lang="python">
 +
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
 +
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
 +
</syntaxhighlight>[카메라 외의 영상은 이렇게 안줄여진다고 하던데...]
 +
 +
=== 처리 효율 ===
 +
{| class="wikitable"
 +
!의도
 +
!설명
 +
!방법
 +
|-
 +
|이미지 형태 변환
 +
|원본 이미지를 사용하면 처리량이 많아져 계산이 오래걸린다.
 +
옵션은 굉장히 다양한데, 자주 쓰이는 것만 모아보았다.
 +
{| class="wikitable"
 +
!옵션
 +
!설명
 +
|-
 +
|cv2.COLOR_BGR2GRAY
 +
|BGR 컬러 이미지를 그레이스케일로
 +
|-
 +
|cv2.COLOR_BGR2RGB
 +
|BGR을 RGB로 변환
 +
|-
 +
|
 +
|
 +
|}
 +
|<syntaxhighlight lang="python">
 +
cov_img = cv2.cvtColor(img, cv2.COLOR_옵션)  # 원본 img와 옵션을 받아 형태를 변환한다.
 +
</syntaxhighlight>
 +
|-
 +
|바이너리
 +
|이미지를 검은색과 흰색만으로 표현한 것.
 +
그레이스케일보다 더 빠른 처리를 위해서 + 피사체의 모양을 더 명확하게 파악하기 위해.
 +
|<syntaxhighlight lang="python">
 +
ret, cov_img = cv2.threshold(img, 경계값, 255, cv2.THRESH_BINARY)
 +
# ret엔 트레시홀딩에 사용한 경계값이 나오니, 버리는 값이다.
 +
 +
ret, cov_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # 원본 img와 옵션을 받아 형태를 변환한다.
 +
# ret에 사용된 경계값이 담기니, 이 ret은 쓸만할지도..
 +
</syntaxhighlight>파이프 문자로 연결한 오츠 옵션은 오츠의 알고리즘을 통해 경계값을 자동으로 설정하게 하기 위한 것이다.
 +
 +
오츠의 알고리즘을 사용하면 모든 경우의 수에 대한 경계값을 조사하기 때문에 느리다.
 +
|-
 +
|적응형 트레숄드
 +
|그러나.. 조명이 일정하니 않은 경우엔 하나의 경계값을 전체에 적용하면 일부가 타버리는 경우가 있다.
 +
때문에 여러 영역에 따라 달리 적용해주어야 한다.
 +
|<syntaxhighlight lang="python">
 +
block_size = 9  # 블록사이즈
 +
c = 5  # 차감상수
 +
 +
cov_img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, block_size, c)
 +
</syntaxhighlight>적응형에서 가우시안 분포를 사용해 정리하는 편이 노이즈도 적고 깨끗한 이미지를 얻을 수 있다.
 
|}
 
|}
  
이미지 읽기
+
=== 이미지 준비 ===
img = cv2.imread(...., 읽기모드)
+
{| class="wikitable"
cv2.imshow(창이름, img)
+
!의도
cv2.waitKey() 특정 키가 입력될 때까지 대기. 이미지를 띄울 때 이게 없으면 바로 끝난다. 그럼.. 영상에선 필요 없는 거 아닌감.
+
!설명
cv2.destroyAllWindows()  모든 창 닫기.
+
!방법
 +
|-
 +
|노멀라이즈
 +
|정규화 하면 흐릿했던 이미지의 격차를 벌려 선명한 이미지를 얻을 수 있다.
 +
|<syntaxhighlight lang="python">
 +
norm = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)  # 구간 노멀라이즈를 실행한다.
 +
</syntaxhighlight>
 +
|-
 +
|이퀄라이즈
 +
|중심에서 멀리 떨어진 값은 노멀라이즈를 적용해도 여전히 흐리다.
 +
노멀라이즈 후 누적값을 전체 개수로 나누어 나온 값을 원래 값에 매핑.
 +
 
 +
각각의 값이 전체 분포에 차지하는 비중에 따라 재분배하여 명암대비에 효과적.
 +
 
 +
빛이 적어 윤곽선이 흐릿한 부분을 살려준다.
 +
|<syntaxhighlight lang="python">
 +
img = cv2.equalizeHist(img)
 +
</syntaxhighlight>
 +
|}
 +
 
 +
= 꾸미기 =
 +
 
 +
=== 글씨 쓰기 ===
 +
{| class="wikitable"
 +
!의도
 +
!설명
 +
!방법
 +
|-
 +
|글씨쓰기
 +
|영상이나 이미지에 글씨를 쓴다.
 +
|<syntaxhighlight lang="python">
 +
cv2.putText(img,        # 글씨를 표시할 이미지나 프레임.
 +
            text,      # 표시할 텍스트.
 +
            point,      # 표시할 좌표. 문자열의 좌측 하단이 기준이 된다.
 +
            fontFace,   # 글씨체
 +
            fontSize,  # 1이 평범한 크기.
 +
            color,      # (255,255,255) 형태.
 +
            )
 +
</syntaxhighlight>
 +
|}
 +
 
 +
= 외부입력 =
 +
{| class="wikitable"
 +
!의도
 +
!설명
 +
!방법
 +
|-
 +
|키 입력 받기
 +
|cv2.waitKey(ms) 함수는 특정 시간동안 키입력이 없으면 -1을 반환한다.
 +
인수로 0을 주면 무한정 기다린다.
 +
 
 +
반환하는 키 코드는 아스키코드와 같아 ord 함수를 이용하여 매칭할 수 있다.
 +
 
 +
 
 +
주의 : 64비트 환경에선 cv2.waitKey() 함수가 아스키코드보다 큰 32비트 정수를 반환하기도 한다. 이를 처리하려면 하위 8비트만 남기고 지운다.
 +
|<syntaxhighlight lang="python">
 +
key = cv2.waitKey(10000) & 0xFF # &연산으로 하위 8비트만 남기고 높은 비트는 0 처리.
 +
if key == ord('a'):  # a키를 받으면...
 +
</syntaxhighlight>
 +
|}
 
[[분류:머신러닝 라이브러리]]
 
[[분류:머신러닝 라이브러리]]

2021년 10월 7일 (목) 17:15 기준 최신판

1 개요[편집 | 원본 편집]

오픈소스 컴퓨터 비전 라이브러리. 실시간 이미지 프로세싱에 중점을 두었다. 주로 이미지를 읽거나 영상을 읽고 연산을 적용한 후 표시, 다른 파일로 저장하는 용으로 쓰인다.

Numpy에 유일하다시피 의존한다. 기본적으로 이미지를 배열처리.

2 준비[편집 | 원본 편집]

의도 설명 방법
설치 pip install opencv-python

3 기초 사용[편집 | 원본 편집]

의도 설명 방법
임포트 import cv2

3.1 이미지 관련[편집 | 원본 편집]

의도 설명 방법
이미지 읽기 이미지파일을 읽고 창에 띄운다.
읽기모드 설명
cv2.IMREAD_COLOR 컬러(BGR) 스케일로 받는다.(디폴트)
cv2.IMREAD_UNCHANGED 파일 그대로
cv2.IMREAD_GRAYSCALE 흑백으로 읽기
img = cv2.imread('이미지 경로', 읽기모드)
cv2.imshow('창이름', img)  # 창이름을 가진 창에 이미지를 띄운다.
cv2.waitKey(0)  # 아무 키가 입력될 때까지 대기. 이미지를 띄울 때 이게 없으면 바로 끝난다. 눌린 키에 대응하여 값을 반환한다.
cv2.destroyAllWindows()  # 모든 창 닫기.
이미지 저장 처리 후 다시 저장하기 위해.
cv2.imwrite('저장경로', img)  # 파일 포멧까지 지정해주어야 한다.

3.2 영상 관련[편집 | 원본 편집]

의도 설명 방법
영상 불러오기 VideoCapture의 인수로 0을 주면 웹캠을 열고,

인수로 영상파일 경로를 주면 파일을 열어 분석한다.

cap = cv2.VideoCapture(0)  # 경로가 아닌 숫자라면, 카메라 번호를 의미한다.

while True:
    ret, img = cap.read()  # read로 프레임을 하나씩 읽는다.
    if not ret:  # ret엔 cap.isOpened() 가 담겨 영상이 열려있는지 여부를 반환한다.
        break
    # 프레임 하나하나 이미지 처리되어 img 객체에 담기니, 이를 처리하면 된다.
    cv2.imshow('창이름', img)  # 창을 열어 보여준다. 프레임마다 빠르게 불러 영상처럼.
    if cv2.waitKey(1) != -1:  # 아무 키가 입력될 때까지 ms단위로 대기. 파일에 따라 다른 값을 준다. 너무 빠르게 넘어가면 볼 수가 없어.
        break  # 아무 키가 입력되면 멈춘다. 아무 키가 없으면 -1 반환.
cap.release()  # 객체에서 사용하던 자원을 반납한다.
cv2.destroyAllWindows()
영상 보여주기 처리한 영상을 img에 담으면 각 프레임마다

'창이름'이라는 창을 띄워 매끄러운 영상으로 보여준다.


print함수로 코드 중간을 점검하듯, imshow로 점검한다.

cv2.imshow('창이름', img)
cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
영상 속성 보기 객체.get 함수를 이용하면 볼 수 있다. cap.get(cv2.CAP_PROP_FPS) # 해당 영상의 초당 프레임 수를 구한다.
속성 설명
cv2.PROP_FRAME_WIDTH 프레임의 폭
cv2.PROP_FRAME_HEIGHT 프레임 높이
cv2.PROP_POS_AVI_RATIO 동영상 파일의 현재 위치(0~1 사이.)

이외 수많은 속성들이 있다.

영상 속성 지정 객체.set 함수를 이용해 속성값을 지정할 수 있다. cap.set(cv2.PROP_FRAME_WIDTH, 320) # 영상의 폭을 320으로 지정.
속성 설명
cv2.PROP_FRAME_WIDTH 프레임의 폭
영상 저장(특정프레임) 특정 프레임을 이미지로 저장.

이미지의 저장과 동일하다.

다음 코드를 적절한 곳에 추가하면 된다.
if cv2.waitKey(1) != -1:  # 아무 키가 입력될 때까지 ms단위로 대기.
    cv2.imwrite('사진경로.jpg', img)  # 해당 이미지를 저장한다.
영상 저장(특정구간) 특정 구간을 영상으로 저장.

적절한 fourcc값은 링크에서 찾아보자.

# 사전 인수 설정.
file_path = '주소.avi'
fourcc = cv2.VideoWriter_fourcc(*'DIVX')  # 비디오인코딩 형식(4글자)

# 비디오 저장 클래스 객체를 생성한다.
writer = cv2.VideoWriter(file_path, fourcc,
                        fps,  # 초당 프레임
                        (width, height)  # 크기
)

while True:
    ret, img = cap.read()
    ...
    writer.write(img)  # 해당 프레임을 쓴다.
    if cv2.waitKey(1) != -1:  # 아무 키가 입력될 때까지 ms단위로 대기.
        break  # 키를 누르면 녹화를 멈춘다.
    
writer.release()  # 파일을 닫는다.(자원 반환)

3.2.1[편집 | 원본 편집]

너무 고화질의 영상이라면 픽셀 수가 많아 연산하는 데 오래걸린다. 때문에 프레임 폭, 높이 조절로 픽셀 수를 줄이는 편이 이득.

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)

[카메라 외의 영상은 이렇게 안줄여진다고 하던데...]

3.2.2 처리 효율[편집 | 원본 편집]

의도 설명 방법
이미지 형태 변환 원본 이미지를 사용하면 처리량이 많아져 계산이 오래걸린다.

옵션은 굉장히 다양한데, 자주 쓰이는 것만 모아보았다.

옵션 설명
cv2.COLOR_BGR2GRAY BGR 컬러 이미지를 그레이스케일로
cv2.COLOR_BGR2RGB BGR을 RGB로 변환
cov_img = cv2.cvtColor(img, cv2.COLOR_옵션)  # 원본 img와 옵션을 받아 형태를 변환한다.
바이너리 이미지를 검은색과 흰색만으로 표현한 것.

그레이스케일보다 더 빠른 처리를 위해서 + 피사체의 모양을 더 명확하게 파악하기 위해.

ret, cov_img = cv2.threshold(img, 경계값, 255, cv2.THRESH_BINARY)
# ret엔 트레시홀딩에 사용한 경계값이 나오니, 버리는 값이다.

ret, cov_img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)  # 원본 img와 옵션을 받아 형태를 변환한다.
# ret에 사용된 경계값이 담기니, 이 ret은 쓸만할지도..
파이프 문자로 연결한 오츠 옵션은 오츠의 알고리즘을 통해 경계값을 자동으로 설정하게 하기 위한 것이다.

오츠의 알고리즘을 사용하면 모든 경우의 수에 대한 경계값을 조사하기 때문에 느리다.

적응형 트레숄드 그러나.. 조명이 일정하니 않은 경우엔 하나의 경계값을 전체에 적용하면 일부가 타버리는 경우가 있다.

때문에 여러 영역에 따라 달리 적용해주어야 한다.

block_size = 9  # 블록사이즈
c = 5  # 차감상수

cov_img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, block_size, c)
적응형에서 가우시안 분포를 사용해 정리하는 편이 노이즈도 적고 깨끗한 이미지를 얻을 수 있다.

3.2.3 이미지 준비[편집 | 원본 편집]

의도 설명 방법
노멀라이즈 정규화 하면 흐릿했던 이미지의 격차를 벌려 선명한 이미지를 얻을 수 있다.
norm = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)  # 구간 노멀라이즈를 실행한다.
이퀄라이즈 중심에서 멀리 떨어진 값은 노멀라이즈를 적용해도 여전히 흐리다.

노멀라이즈 후 누적값을 전체 개수로 나누어 나온 값을 원래 값에 매핑.

각각의 값이 전체 분포에 차지하는 비중에 따라 재분배하여 명암대비에 효과적.

빛이 적어 윤곽선이 흐릿한 부분을 살려준다.

img = cv2.equalizeHist(img)

4 꾸미기[편집 | 원본 편집]

4.1 글씨 쓰기[편집 | 원본 편집]

의도 설명 방법
글씨쓰기 영상이나 이미지에 글씨를 쓴다.
cv2.putText(img,        # 글씨를 표시할 이미지나 프레임.
            text,       # 표시할 텍스트.
            point,      # 표시할 좌표. 문자열의 좌측 하단이 기준이 된다.
            fontFace,   # 글씨체
            fontSize,   # 1이 평범한 크기.
            color,      # (255,255,255) 형태.
            )

5 외부입력[편집 | 원본 편집]

의도 설명 방법
키 입력 받기 cv2.waitKey(ms) 함수는 특정 시간동안 키입력이 없으면 -1을 반환한다.

인수로 0을 주면 무한정 기다린다.

반환하는 키 코드는 아스키코드와 같아 ord 함수를 이용하여 매칭할 수 있다.


주의 : 64비트 환경에선 cv2.waitKey() 함수가 아스키코드보다 큰 32비트 정수를 반환하기도 한다. 이를 처리하려면 하위 8비트만 남기고 지운다.

key = cv2.waitKey(10000) & 0xFF  # &연산으로 하위 8비트만 남기고 높은 비트는 0 처리.
if key == ord('a'):  # a키를 받으면...