import matplotlib.pyplot as plt
import numpy as np
import cv2
def bgr_to_rgb(imgfile):
b, g, r = cv2.split(imgfile)
imgfile = cv2.merge([r, g, b])
return imgfile
이미지 더하기
두개의 이미지를 더하는 데는 2가지 방법이 있다. 하나는 + operator를 사용하여 연산하는 방법과 다른 하나는 opencv의 add함수를 사용하는 것이다. 두 방법 모두 서로 다른 이미지를 더하지만 더하는 방식에는 그 차이가 있다.
img1 + img2
우리가 opencv의 imread 함수로 이미지를 불러들였을 때, 그 이미지가 numpy array의 형식을 가지고 있으므로 img1과 img2를 더하는 것은 해당 이미지의 numpy array를 더하는 것과 같다. 따라서 img1과 img2를 + operator로 연산하기 위해서는 ★동일한 크기와 동일한 데이터 타입으로 이루어져 있어야 한다. + operator를 사용하였을 때 각 픽셀들을 더한 값이 255보다 크면 그 값을 256으로 나눈 나머지가 픽셀값이 된다. 예를들어 두 이미지 특정 픽셀의 Blue 채널의 합이 257인 경우 해당 픽셀의 Blue 채널은 1의 값을 가지게 된다.
cv2.add(img1, img2)
add()함수를 사용하는 경우 마찬가지로 numpy array를 그대로 덧셈으로 연산하지만 + operator를 사용하는 것과는 다르게 해당 픽셀값이 255를 넘어가면 그 픽셀값을 255로 고정하여 사용한다.
def addImage(imgfile1, imgfile2):
img1 = cv2.imread(imgfile1)
img2 = cv2.imread(imgfile2)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
add_img1 = img1 + img2
add_img2 = cv2.add(img1, img2)
cv2.imshow('img1+img2', add_img1)
cv2.imshow('cv2.add(img1, img2)', add_img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
addImage('anemone-5281964_1280.jpg', 'dove-2516641_1280.jpg')
img1 | img2 |
img1 + img2 | cv2.add(img1, img2) |
이미지 블렌딩 (Blending)
이미지 블렌딩은 이미지를 서로 합칠 때 가중치를 두어 합치는 방법이다. 두 이미지가 있고 1번 이미지에서 2번 이미지로 전환하려고 하는데, 서서히 변환하려고 할 때 이것이 좋은 기법이 될 수 있다. 다음은 이미지 블렌딩 기법을 구현하기 위한 수식 중 하나이다.
\[g(x) = (1-a) f_0(x) + a f_1(x)\]
여기서 a의 값이 0 에서 1로 변해감에 따라 f_0(x) (img1)의 효과는 점점 작아지고 f_1(x) (img2)의 효과는 점점 커지게 된다. 이미지 블렌딩을 사용하려고 할 때 opencv의 addWeighted() 함수를 사용할 수 있다.
img1 = cv2.imread('anemone-5281964_1280.jpg')
img2 = cv2.imread('dove-2516641_1280.jpg')
def onChange(x):
pass
def ImgBlending(imgfile1, imgfile2):
cv2.namedWindow('Img')
cv2.createTrackbar('Blending', 'Img', 0, 1000, onChange)
while True:
weight = cv2.getTrackbarPos('Blending', 'Img')
img = cv2.addWeighted(imgfile1, float(1000-weight) * 0.001, imgfile2, float(weight) * 0.001, 0)
cv2.imshow('Img', img)
k = cv2.waitKey(0) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
ImgBlending(img1, img2)
처음부터 코드를 차례대로 살펴보자. 우선 이미지를 열 윈도우 창의 이름을 Img라 정의하고 그 창에서 만들어낼 트랙바 이름을 'Blending'이라 정의한다. 지난번 트랙바를 정의할 때 TrackbarCallback 함수에서 아무 처리를 하지 않았던 것처럼 이번에도 onChange 함수에선 아무 동작을 하지 않도록 pass로 처리하였다. 시작값은 0, 마지막값은 1000으로 지정한다. weight = cv2.getTrackbarPos('Blending', 'Img') 이렇게 Img 윈도우 창 위에 Blending 트랙바를 만들었으면 Blending 위치 정보를 가중치라 정의하여 weight로 초기화한다. 그 다음 이 가중치를 사용하여 이미지 블렌딩 기법을 구현한다. addweighted 함수를 사용한다.
cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst
dst(I)=saturate(src1(I)∗alpha+src2(I)∗beta+gamma)
\[g(x) = (1-a) f_0(x) + a f_1(x)\]
위 수식에서 f_0(x)와 f_1(x)는 addWeighted 파라미터에서 각각 src1과 src2를 나타낸다. 해당 위치에는 각각 원본이미지 1과 원본이미지 2가 들어갈 수 있다. 또한 수식에서 f_0(x)에 효과를 주는 (1-a)와 f_1(x)에 효과를 주는 a는 파라미터에서 각각 alpha와 beta를 나타낸다. alpha는 src1 파라미터에 영향을 주며, beta는 src2 파라미터에 영향을 준다. (★이때 alpha, beta, gamma는 double 형이어야 한다.)
블렌딩한 결과 g(x)가 온전히 나타내어질 수 있으려면 우선 원본 이미지1, 2가 0~255의 픽셀 값으로 온전히 나타내어져야 한다. 예를들어 a가 0일 경우 f_0(x)의 원본이미지 1이 온전히 나타내어져야 하고, a가 1일 경우 f_1(x)의 원본이미지 2가 온전히 나타내어져야 한다. 그러기 위해선 alpha와 beta값의 크기가 0~1사이가 되어야 한다.
alpha : trackbarpos의 크기가 0~1000 사이이므로 우선 float(1000-weight)를 통해 f_0(x)의 픽셀값을 역전시켜준 후, 0.001을 곱해서 alpha 값을 0~1사이로 맞춰준다.
beta : alpha의 경우와 마찬가지지만 float(weight)만을 수행하여 f_1(x)의 픽셀값을 역전시키지 않은 상태에서 0.001을 곱해 beta 값을 0~1사이로 맞춰준다.
gamma : 따로 bias 값은 필요하지 않으므로 설정하지 않는다.
img = cv2.addWeighted(imgfile1, float(1000-weight) * 0.001, imgfile2, float(weight) * 0.001, 0) 이렇게 addWeighted로 수행된 numpy array 값을 img 변수에 저장한다.
'데이터 분석 & 시각화 > OpenCV' 카테고리의 다른 글
[OpenCV Practice 06 - 2] 이미지 비트연산 (0) | 2020.08.19 |
---|---|
[OpenCV Programming] 캐스케이드 분류기(Cascade Classifier) (0) | 2020.08.18 |
[OpenCV Practice 05] 이미지 속성과 관심 영역 지정(ROI) (0) | 2020.08.12 |
[OpenCV Practice 04] 트랙바 (Trackbar) (0) | 2020.08.11 |
[OpenCV Programming] 디스크립터(Descriptor) (0) | 2020.08.10 |
최근댓글