파이썬 OpenCV 설치 및 예제로 알아보는 이미지 처리 방법
OpenCV 넌 뭐하는 놈이냐?
OpenCV는 Open Source Computer Vision Library의 약어로 실시간 컴퓨터 비전을 목적으로 한 프로그래밍 라이브러리이다. 원래는 인텔이 개발하였다. 실시간 이미지 프로세싱에 중점을 둔 라이브러리이다. 인텔 CPU에서 사용되는 경우 속도의 향상을 볼 수 있는 IPP(Intel Performance Primitives)를 지원한다. 이 라이브러리는 윈도, 리눅스 등에서 사용 가능한 크로스 플랫폼이며 오픈소스 BSD 허가서 하에서 무료로 사용할 수 있다. OpenCV TensorFlow , Torch / PyTorch 및 Caffe의 딥러닝 프레임워크를 지원한다.
OpenCV는 컴퓨터 비전 관련 프로그래밍을 쉽게 할 수 있도록 도와주는 라이브러리로 이미지 딥러닝(알파고 기술)에도 많이 활용된다.
컴퓨터 비전(Computer Vision)은 카메라, 에지 기반 또는 클라우드 기반 컴퓨팅, 소프트웨어 및 인공 지능(AI)을 결합하여 시스템이 사물을 “확인”하고 식별할 수 있게 합니다. 인텔은 범용 프로세싱을 위한 CPU, 컴퓨터 비전, 비전 처리 장치(VPU)를 비롯한 AI 가속화를 지원하는 다양한 기술 포트폴리오를 보유하고 있습니다. 다양한 환경에서 가치를 발휘하는 컴퓨터 비전 시스템은 사물과 사람을 빠르게 인식하고, 고객 통계 자료를 분석하고, 공산품을 검사하는 등의 작업을 수행할 수 있습니다.
컴퓨터 비전은 딥 러닝을 사용하여 이미지 처리 및 분석 시스템을 안내하는 신경망을 형성합니다. 충분히 훈련된 컴퓨터 비전 모델은 사물을 인식하고 사람을 감지하거나 인식하며 움직임도 추적할 수 있습니다.
OpenCV 응용분야
인간과 컴퓨터의 상호 작용(HCI), 물체 인식, 안면 인식, 모바일 로보틱스, 제스쳐인식, 자율주행 등 다양함.
파이썬용 OpenCV 설치
opencv라이브러리 사용을 위해서 명령프롬프트 창을 열고 pip명령어를 사용하여 설치합니다.
pip install opencv-python
설치된 버전 : opencv-python-4.5.2.54
C:>pip install opencv-python
Collecting opencv-python
Downloading opencv_python-4.5.2.54-cp39-cp39-win_amd64.whl (34.7 MB)
|████████████████████████████████| 34.7 MB 6.4 MB/s
Requirement already satisfied: numpy>=1.19.3 in c:usersilikeappdatalocalprogramspythonpython39libsite-packages (from opencv-python) (1.19.3)
Installing collected packages: opencv-python
Successfully installed opencv-python-4.5.2.54
opencv 설치된 버전 확인 스크립트
import cv2
print(cv2.__version__)
#실행결과
4.5.2
OpenCV 이미지 처리
1. 이미지를 불러오기
imread(filename, flags)함수를 사용하여 이미지를 불러옵니다.
2번째 인자(파라미터) 플래그 타입을 설정하지 않은 경우, 1로 한 경우, cv2.IMREAD_COLOR 한 경우 코드 상 표기만 다를뿐 모두 동일하니, 편한 방법으로 사용하면 된다. 반환된 이미지의 값을 받은 img1 변수의 타입을 print()문으로 출력해보면 넘파이(numpy) 배열(numpy.ndarray)임을 알 수 있어요.
imshow()함수는 이미지를 출력하기위한 윈도우 창을 호출하기위해 사용됩니다. 윈도우 창이름을 같은 값으로 지정하면 동일한 윈도우로 간주되어 하나의 윈도우창만 열리게 되니, 여러개의 이미지 창을 실행할 때는 라벨명을 다르게 해야 합니다.
destoryAllWindows()함수는 실행중인 프로그램 종료시 모든 창을 닫을 때 사용합니다.
waitKey()함수는 사용자의 입력을 기다려주는 함수이다. 인자값이 없거나 0일 경우 시간 제한 없이 기다려 줍니다. 키를 입력받아 분기할 작업이 있을때 활용하면 됩니다. 아래 샘플 코드에서는 cv2.destoryAllWindows()함수를 실행하기 위해 기다린다고 생각하면 되요.
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg', 1)
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg', cv2.IMREAD_COLOR)
print(type(img1))
cv2.imshow('image1', img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
[코드 실행결과]
<class ‘numpy.ndarray’>
imread()함수의 2번째 인자 값 플래그 타입(enum)
flags 타입 | 내용 |
IMREAD_COLOR | 별도로 지정하지 않은 경우 기본값, 3채널 BGR 컬러 이미지로 반환 |
IMREAD_GRAYSCALE | 단일 채널 회색조 이미지로 반환(내부 코덱 변환) |
IMREAD_UNCHANGED | 이미지 원본 그대로 반환한다. 투명도(Alpha 채널)을 포함, EXIF값은 무시됨 |
IMREAD_ANYDEPTH | 설정된 경우 입력에 해당 깊이가있을 때 16 비트 / 32 비트 이미지를 반환하고 그렇지 않으면 8 비트로 변환합니다. |
IMREAD_ANYCOLOR | 설정된 경우 가능한 모든 색상 형식으로 이미지를 읽습니다. |
IMREAD_LOAD_GDAL | 설정된 경우 이미지로드에 gdal 드라이버를 사용합니다. |
IMREAD_REDUCED_GRAYSCALE_2 | 설정된 경우 항상 이미지를 단일 채널 회색조 이미지로 변환하고 이미지 크기를 1/2로 줄입니다. |
IMREAD_REDUCED_COLOR_2 | 설정된 경우 항상 이미지를 3 채널 BGR 컬러 이미지로 변환하고 이미지 크기를 1/2로 줄입니다. |
IMREAD_REDUCED_GRAYSCALE_4 | 설정된 경우 항상 이미지를 단일 채널 회색조 이미지로 변환하고 이미지 크기를 1/4로 줄입니다. |
IMREAD_REDUCED_COLOR_4 | 설정된 경우 항상 이미지를 3 채널 BGR 컬러 이미지로 변환하고 이미지 크기를 1/4로 줄입니다. |
IMREAD_REDUCED_GRAYSCALE_8 | 설정된 경우 항상 이미지를 단일 채널 회색조 이미지로 변환하고 이미지 크기를 1/8로 줄입니다. |
IMREAD_REDUCED_COLOR_8 | 설정된 경우 항상 이미지를 3 채널 BGR 컬러 이미지로 변환하고 이미지 크기를 1/8로 줄입니다. |
IMREAD_IGNORE_ORIENTATION | 설정된 경우 EXIF의 방향 플래그에 따라 이미지를 회전하지 마십시오. |
5개의 플래그 값에 대한 이미지 반환을 확인해봅니다.
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img2 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg', cv2.IMREAD_GRAYSCALE)
img3 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg', cv2.IMREAD_ANYCOLOR)
img4 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg', cv2.IMREAD_ANYDEPTH)
img5 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg', cv2.IMREAD_LOAD_GDAL)
cv2.imshow('image1', img1)
cv2.imshow('image2', img2)
cv2.imshow('image3', img3)
cv2.imshow('image4', img4)
cv2.imshow('image5', img5)
cv2.waitKey(0)
cv2.destroyAllWindows()
[코드실행결과]
육안으로 식별이 가능한가?
2. 이미지 다른이름으로 저장
원본이미지를 그레이스케일 처리 후 다른 이름으로 저장하기위해 cv2.imwrite()함수를 사용 합니다.
import cv2)
img2 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imwrite('C:pythonopencvsample_imagesampe_save.jpg', img2)
[실행결과]
지정한 파일이름으로 지정 폴더에 저장 되었습니다.
이미지를 저장할 때, 3번째 인자값에 다음과 같은 저장 관련 옵션을 적용할 수 있습니다.
flags 타입 | 내용 |
IMWRITE_JPEG_QUALITY | JPEG의 경우 0에서 100까지의 품질이 될 수 있습니다 (높을수록 좋습니다). 기본값은 95입니다. |
IMWRITE_JPEG_PROGRESSIVE | JPEG 기능 활성화 (0 또는 1), 기본값은 False입니다. |
IMWRITE_JPEG_OPTIMIZE | JPEG 기능 활성화 (0 또는 1), 기본값은 False입니다. |
IMWRITE_JPEG_RST_INTERVAL | JPEG 재시작 간격, 0-65535, 기본값은 0-재시작 안 함. |
IMWRITE_JPEG_LUMA_QUALITY | 별도의 채도 품질 수준, 0-100, 기본값은 0-사용하지 않습니다. |
IMWRITE_PNG_COMPRESSION | PNG의 경우 0에서 9까지의 압축 수준이 될 수 있습니다. 값이 높을수록 크기가 작고 압축 시간이 길어집니다. 지정된 경우 전략은 IMWRITE_PNG_STRATEGY_DEFAULT (Z_DEFAULT_STRATEGY)로 변경됩니다. 기본값은 1 (최고 속도 설정)입니다. |
IMWRITE_PNG_STRATEGY | 기본값 |
IMWRITE_PNG_BILEVEL | 바이너리 레벨 PNG, 0 또는 1, 기본값은 0입니다. |
IMWRITE_PXM_BINARY | PPM, PGM 또는 PBM의 경우 이진 형식 플래그 0 또는 1 일 수 있습니다. 기본값은 1입니다. |
IMWRITE_EXR_TYPE | |
IMWRITE_WEBP_QUALITY | EXR 스토리지 유형 재정의 (FLOAT (FP32)가 기본값 임)
WEBP의 경우 1에서 100까지의 품질이 될 수 있습니다 (높을수록 좋습니다). 기본적으로 (매개 변수 없음) 품질이 100 이상인 경우 무손실 압축이 사용됩니다. |
IMWRITE_PAM_TUPLETYPE | PAM의 경우 TUPLETYPE 필드를 형식에 대해 정의 된 해당 문자열 값으로 설정합니다. |
IMWRITE_TIFF_RESUNIT | TIFF의 경우 설정할 DPI 해상도 단위를 지정하는 데 사용합니다. 유효한 값은 libtiff 문서를 참조하십시오. |
IMWRITE_TIFF_XDPI | TIFF의 경우를 사용하여 X 방향 DPI를 지정합니다. |
IMWRITE_TIFF_YDPI | TIFF의 경우를 사용하여 Y 방향 DPI를 지정합니 |
IMWRITE_TIFF_COMPRESSION | TIFF의 경우를 사용하여 이미지 압축 체계를 지정합니다. 압축 형식에 해당하는 정수 상수는 libtiff를 참조하십시오. 깊이가 CV_32F 인 이미지의 경우 libtiff의 SGILOG 압축 체계 만 사용됩니다. 지원되는 다른 깊이의 경우이 플래그로 압축 체계를 지정할 수 있습니다. LZW 압축이 기본값입니다. |
이미지 저장시, 이미지 품질을 낮게 처리 한다면 아래와 같은 방법으로 처리해줍니다.
cv2.imwrite('C:pythonopencvsample_imagesampe_save2.jpg', img2, [cv2.IMWRITE_JPEG_QUALITY, 10])
3. OpenCV 이미지 붙이기
여러개의 이미지를 붙이기 위해 cv2.vconcat()함수와 cv2.hconcat()함수를 사용한다. 인자값은 n차원 배열 타입입니다.
함수명 | 설명 |
vconcat([img1,img2]) | 이미지를 수직 방향으로 붙여 리턴 |
hconcat([img1,img2]) | 이미지를 수평 방향으로 붙여 리턴 |
이미지 2개를 수평방향으로 붙여주는 샘플 코드
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img2 = cv2.imread('C:pythonopencvsample_imagegray_image.jpg')
img3 = cv2.hconcat([img1, img2])
cv2.imshow('image3', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
[실행결과]
cv2.resize() 함수를 사용하여 이미지 사이즈 변경이 가능하며, 튜플 자료형으로 가로와 세로의 사이즈 값을 할당합니다.
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img1 = cv2.resize(img1, (320, 300))
resize()함수는 정수값만 적용할 수 있음으로 아래의 코드 스니펫처럼 나눗셈을 한경우 리턴값 타입이 float 타입임으로 round()함수를 이용하여 소숫점을 제거해야 합니다.
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
w = img1.shape[1] #이미지 가로 사이즈
h = img1.shape[0] #세로 사이즈
print(w)
print(h)
width = round(w/2)
height = round(h/2)
img = cv2.resize(img1, (width, height))
#esized = cv2.resize(img1, (width, height), interpolation=cv2.INTER_AREA)
#print('이미지 사이즈 변경 : ',resized.shape)
cv2.imwrite('C:pythonopencvsample_imagessssss.jpg', img)
이미지 확대 축소시 사용되는 interpolation 속성
속성 | 의미 |
cv2.INTER_LANCZOS4 | Lanczos 보간법 |
cv2.INTER_NEAREST | 이웃 보간법 |
cv2.INTER_AREA | 영역 보간법 (이미지 축소시 사용), 이미지를 확대시 사용하는 경우, 이웃보간법과 비슷한 결과를 반환한다. |
cv2.INTER_LINEAR_EXACT | 비트 쌍 선형 보간법 |
cv2.INTER_CUBIC | 바이큐빅 보간법 (이미지 확대시 많이 사용) |
cv2.INTER_LINEAR | 쌍 선형 보간법(이미지 확대시 많이 사용) |
5. OpenCV 이미지 밝기 조절
이미지의 밝기 값을 덧셈 뺄셈을 이용하여 해당 수치만큼 처리하면 이미지의 밝기를 조절할 수 있습니다. 아래 샘플 코드는 원본이미지의 밝기를 조절한 후 3개의 이미지를 수평방향으로 붙여서 보여줍니다.
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img2 = img1 + 50 #이미지 밝게
img3 = img1 - 50 #어둡게
img4 = cv2.hconcat([img1, img2, img3])
cv2.imshow('image3', img4)
cv2.waitKey(0)
cv2.destroyAllWindows()
[실행결과]
이미지 처리 결과 어디서 많이 보던 이미지가 아닌가? 포토샵에서 히스토그램에서 이미지 밝기 조절할 때 흔히 볼 수 있는 결과 입니다. 이미지 픽셀값의 최대값인 255를 넘기거나 최소값인 0이하로 값이 변경될 경우 나타나는 현상입니다.
처음에 openCV를 사용하여 이미지를 읽어 올때 이미지의 반환 값이 넘파이 배열임을 알고 있죠. 이런 현상을 처리하기 위해 numpy모듈(라이브러리) 사용하여 numpy.clip()함수를 이용하면 해결하여 조건을 추가할 수 있습니다.
numpy.clip(src, min, max)함수는 src 값에 적용할 최소값과 최대값을 사전이 대입하여, 최소값 보다 작은 경우, 최소값으로 치환하고, 최대값 보다 큰 경우 최대값으로 치환해주는 함수 입니다.
다음 샘플코드를 실행하면 정상적으로 밝은 이미지와 어두운 이미지로 변환 되었음을 확인할 수 있어요.
이미지의 타입값을 int 타입으로 먼저 변경 후에 밝기 값을 계산 해준 뒤, uint8타입으로 변경해 줘야 오류가 발생하지 않습니다.
import cv2
import numpy as np
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img2 = np.clip(img1.astype('int32') + 50, 0, 255).astype('uint8')
img3 = np.clip(img1.astype('int32') - 50, 0, 255).astype('uint8')
img4 = cv2.hconcat([img1, img2, img3])
cv2.imshow('image3', img4)
cv2.waitKey(0)
cv2.destroyAllWindows()
6. OpenCV 이미지 회전
이미지 회전을 위해 2×3 회전 행렬 생성 함수인 cv2.getRotationMatrix2D(center, angle, scale)를 이용하여 회전 변환 행렬을 계산합니다. 아핀 변환 함수(cv2.warpAffine)로 회전 변환을 계산합니다. 아래 코드는 이미지의 중심점을 기준으로 45도 회전하면서 0.5배로 확대하는 이미지를 반환합니다. 앵글(angle) 회전각도값이 양수값인 경우 시계반대방향으로 회전합니다. cv2.getRotationMatrix2D() 결과에서 나온 변환행렬을 cv2.warpAffine()함수에 적용합니다.
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
height, width, channel = img1.shape
matrix = cv2.getRotationMatrix2D((width / 2, height / 2), 45, 0.5)
dst = cv2.warpAffine(img1, matrix, (width, height))
cv2.imshow("1. 이미지 회전", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
[실행결과]
7. OpenCV 이미지 대칭(Flip)
이미지의 대칭 처리를 위해서 cv2.flip(src, flipCode)함수를 사용합니다.
img1 = cv2.flip(img1, 0) #상하반전
flipCode | 설명 |
flipCode = 0 | X축 대칭( 상하 대칭 )( 상하 반전) |
flipCode > 0 | Y축 대칭( 좌우 대칭) |
flipCode < 0 | XY축 대칭( 상하좌우 대칭) |
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
cv2.imshow("1. 이미지 뒤집기", cv2.flip(img1, 0))
cv2.imshow("2. 이미지 상하좌우대칭", cv2.flip(img1, -1))
cv2.imshow("3. 이미지 좌우대칭", cv2.flip(img1, 1))
cv2.waitKey(0)
cv2.destroyAllWindows()
[실행결과] 윈도창 이름을 한글로 했을 경우 깨집니다. 영어로 하세요.
8. OpenCV 이미지 자르기(Slice)
영상이나 이미지의 특정 영역을 잘라내는 것은 관심 영역(Region Of Interest, ROI)이라고 합니다. 이미지를 처리할 때 이미지에서 특정 사물을 탐지하거나 검출하는 영역을 잘라낼때 활용합니다.
img1[이미지에 높이(행), 너비(열)]로 관심 영역을 설정합니다.
img1[50:200, 100:250]
리스트 혹은 배열의 특정 영역을 자르는 방식과 동일합니다.
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img2 = img1[50:200, 100:250].copy()
cv2.imshow("TEST", img1)
cv2.imshow("TEST2", img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
[실행결과]
9. OpenCV 이미지 색상 공간 변환
색상 공간 변환 함수인 cv2.cvtcolor()를 이용하여 이미지의 색상 공간을 변경할 수 있습니다.
import cv2
img1 = cv2.imread('C:pythonopencvsample_imageleopard-518210_640.jpg')
img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
height, width, channel = img1.shape
height2, width2 = img2.shape
print(channel)
속성 | 설명 | 비고 |
BGR | Blue, Green, Red 채널 | |
BGRA | Blue, Green, Red, Alpha 채널 | |
RGB | Red, Green, Blue 채널 | |
RGBA | Red, Green, Blue, Alpha 채널 | |
GRAY | 단일 채널 | 그레이스케일 |
BGR565 | Blue, Green, Red 채널 | 16 비트 이미지 |
XYZ | X, Y, Z 채널 | CIE 1931 색 공간 |
YCrCb | Y, Cr, Cb 채널 | YCC (크로마) |
HSV | Hue, Saturation, Value 채널 | 색상, 채도, 명도 |
Lab | L, a, b 채널 | 반사율, 색도1, 색도2 |
Luv | L, u, v 채널 | CIE Luv |
HLS | Hue, Lightness, Saturation 채널 | 색상, 밝기, 채도 |
YUV | Y, U, V 채널 | 밝기, 색상1, 색상2 |
BG, GB, RG | 디모자이킹 | 단일 색상 공간으로 변경 |
_EA | 디모자이킹 | 가장자리 인식 |
_VNG | 디모자이킹 | 그라데이션 사용 |
이미지를 처리하는 또 다른 라이브러리가 있다. pillow(PIL)과 Matplotlib 등이 있다. 관심있다면 아래 글을 참고!
[REFERENCE]
- https://ko.wikipedia.org/wiki/OpenCV
- https://pypi.org/project/opencv-python/
- https://docs.opencv.org/master/d9/df8/tutorial_root.html
- https://www.intel.co.kr/content/www/kr/ko/internet-of-things/computer-vision/overview.html
- https://docs.opencv.org/3.4/d8/d6a/group__imgcodecs__flags.html
- https://076923.github.io/
- https://opencv-python.readthedocs.io/
#python opencv,#numpy.clip(),#파이썬 OpenCV,#OpenCV 사용법,#Python OpenCV,#OpenCV-python 예제,#OpenCV 예제,#OpenCV 사용법,#opencv란,#컴퓨터 비전,#Open CV 활용