0. 이미지란
OpenCV로 읽어 들인 이미지는 Numpy 배열로 보존된다. 아래에서도 나오겠지만 세로 N, 가로 M 픽셀의 이미지는 흑백 이미지인 경우 N x M의 행렬로 보존되고, 컬러 이미지는 채널 수(색상 수) N x M x 3의 행렬로 보존된다. 이미지를 취급하는 데 있어 가장 중요한 것은 왼쪽 최상단의 좌표가 (0, 0)이 되는 것이다. 오른쪽으로 가면 갈 수록 x좌표가 점점 증가하는 것은 당연하지만, 아래로 갈 수록 y좌표가 증가하는 것에 대해 위화감을 느낄 수 있다. 그러나 이것은 이미지 처리 라이브러리 전반에 적용되는 공통 규칙이다.
1. 화소값의 접근 또는 변경방법
처음으로는 컬러 이미지를 읽어 들여 보자.
import cv2
import numpy as np
img = cv2.imread('messi5.jpg')
어떤 화소의 행또는 열의 좌표를 지정하는 것으로 화소치에 접근할 수 있다.
BGR이미지의 화소값은 파랑, 녹색, 빨강색의 값 배열로 구성되어 있으며,
그레이스케일화된 이미지의 화소값을 명도를 리턴한다.
px = img[100,100]
print px
>>> [157 166 200]
# accessing only blue pixel
blue = img[100,100,0]
print blue
>>> 157
아래와 같은 접근 방법을 사용하면, 화소치의 변경이 가능하다.
img[100,100] = [255,255,255]
print img[100,100]
>>> [255 255 255]
<주의 사항> numpy는 배열을 고속으로 계산하는 것에 최적화된 라이브러리이다. 그러므로 화소값의 취득이나 변경은 각 화소에 대한 처리는 처리 시간이 꽤 걸려버리기 때문에 권장하지 않는다. |
<노트> 위의 방법은 배열의 영역(예를 들면, 처음의 5열과 마지막 3행)을 선택할 때에 잘 사용된다. 각 화소에 접근에 관해서는 numpy의 배열을 다루는 array.item()이나 array.itemset()을 사용하면 될 것 처럼 느껴질 수 있지만, 위의 함수들은 스칼라값을 리턴하기 때문에 청색, 녹색, 빨강색의 모든 화소값에 접근하기 위해서는 array.item()를 모든 색 성분에 대해 적용할 필요가 있다. |
화소에의 접근 방법과 변경 방법:
# accessing RED value
img.item(10,10,2)
>>> 59
# modifying RED value
img.itemset((10,10,2),100)
img.item(10,10,2)
>>> 100
2. 이미지의 속성 정보의 취득
배열의 속성 정보로는 열의 수, 행의 수, 채널 수(색상 수), 이미지 데이터의 형, 화소 수 등이 있다.
이미지의 형상은 img.shape로 취득 가능하다.
리턴값은 행수, 열수, (컬러 이미지 라면)채널 수의 튜플이다.
print img.shape
>>> (342, 548, 3)
<노트> 흑백 이미지의 리턴값의 튜플은 행의 수와 열의 수만 존재한다. 그러므로 위의 방법을 통해 이미지가 컬러인지 흑백인지 알아보는 데에 잘 사용된다. |
총 화소의 수는 img.size로 알 수 있다.
print img.size
>>> 562248
이미지 데이터의 데이터형은 img.dtype을 사용하면 알 수 있다.
print img.dtype
>>> uint8
<노트> img.dtype은 디버깅할 때 매우 중요하다. 그 이유는 OpenCV-Python을 사용할 때 자주 발새아는 에러는 맞지 않은 데이터형에 이해 발생하기 때문이다. |
3. 이미지 중 주목 영역(ROI)의 설정
이미지의 특정 영역에 대해 무엇인가를 처리할 때가 반드시 생긴다. 예를 들어 이미지에서 눈을 검출할 때, 먼저 이미지의 전체에서 사람의 얼굴을 검출하고 그 다음 얼굴 안에서 눈을 검출한다. 위와 같이 영역을 좁혀가며 검출하는 이유는 효율성이 높기 때문이다. 주목 영역(ROI)의 지정은 numpy의 인덱스를 사용한다. 여기서는 이미지 중에서 공의 위치를 선별해 다른 장소에 복사한다.
ball = img[280:340, 330:390]
img[273:333, 100:160] = ball
결과는 아래와 같다.
4. 이미지의 분할 또는 통합
이미지의 청색, 녹색, 빨강색 성분은 필요하다면 독립적으로 각각의 성분을 분리할 수 있다.
분리시킨 색 성분을 다시 통합하여 BGR이미지를 한번 더 만드는 것도 가능하다:
b,g,r = cv2.split(img)
img = cv2.merge((b,g,r))
아래의 코드로, 어떤 색 성분만을 추출하는 것도 가능하다.
b = img[:,:,0]
이미지 중에 다른 색 성분과 분할하지 않고 빨강색 성분만을 0으로 설정하고 싶다고 가정하자.
numpy의 인덱스를 사용하면 아래와 같이 표현 가능하다.
img[:,:,2] = 0
<주의 사항> cv2.split()은 (처리속도의 관점에서) 계산 비용이 큰 처리이므로, 필요할 때만 사용하는 것이 좋다. numpy의 인덱스는 효율적이기 때문에 가능하다면 인덱스를 사용하자. |
5. 이미지의 경계 만들기 (패딩)
이미지에 포토 프레임같은 경계선을 만들 때는 cv2.copyMakeBorder()함수를 사용한다.
cv2.copyMakeBorder()함수의 인자는 다음과 같다.
- src ; 입력 이미지
- top, bottom, left, right ; 경계의 각 방향에 대한 선의 폭
- borderType ; 추가하는 경계의 종류를 지정하기 위한 플래그, 아래와 같은 타입이 존재
1) cv2.BORDER_CONSTANT ; 단색의 경계를 추가하는 것, value에서 색의 지정을 한다.
2) cv2.BORDER_REFLECT ; 거울에 비춘 것 처럼 경계를 지정한다. 예를 들면, 아래와 같은 경계를 만들 수 있다.
; fedcba|abcdefgh|hgfedcb
3) cv2.BORDER_REFLECT_101 / cv2.BORDER_DEFAULT ; cv2.BORDER_REFLECT와 같지만 미세한 차이가 있다
; gfedcb|abcdefgh|gfedcba
4) cv2.BORDER_REPLICATE ; 마지막 요소를 반복해서 표시한다.
; aaaaaa|abcdefgh|hhhhhhh
5) cv2.BORDER_WRAP ; 잘 설명할 수 없지만, 아래와 같이 표시된다.
; cdefgh|abcdefgh|abcdefg
- value ; 플래그가 cv2.BORDER_CONSTANT일 경우 경계 색을 지정할 때 사용한다.
참고로, 이미지의 convolution이나 제로 패딩과 같은 처리도 있다.
아래의 코드는 위에서 설명한 전 패턴을 표시하는 코드이다.
import cv2
import numpy as np
from matplotlib import pyplot as plt
BLUE = [255,0,0]
img1 = cv2.imread('opencv_logo.png')
replicate = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_WRAP)
constant= cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)
plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()
결과는 아래의 이미지와 같다.
이미지를 matplotlib를 이용해 표시하기 이해 파랑과 빨강색 성분의 위치를 바꿨다.
참고자료
'IT > AI\ML' 카테고리의 다른 글
[python/OpenCV] 이미지 처리 예제 Q06~Q10 (0) | 2020.04.20 |
---|---|
[python/OpenCV] 이미지 처리 예제 Q01~Q05 (0) | 2020.04.20 |
[python] miniconda 설치, 환경 설정 및 패키지 설치(Windows) (0) | 2020.04.19 |
[AI/ML] 딥러닝, 머신러닝 입문자를 위한 커리큘럼, 강좌 정리 (0) | 2020.04.19 |
[AI/ML] 2020년 실무 현장에서 요구되는 데이터 사이언티스트·머신러닝 엔지니어 기술 요건 (0) | 2020.04.19 |