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 변수에 저장한다.

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기