[opencv-python] 이미지 연산 처리를 이용한 합성

2019. 7. 2. 14:30Python-이론/python-opencv

이미지 더하기

두개의 이미지를 합성 해보겠습니다. 

 

코드

import numpy as np
import cv2


def addImage(imgfile, imgfile2):
    img1 = cv2.imread(imgfile)
    img2 = cv2.imread(imgfile2)

    img1 = cv2.resize(img1, (479, 557))

    print(img1.shape)
    print(img2.shape)

    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", add_img2)

    cv2.waitKey(0)
    cv2.destroyAllWindows()


addImage("../resource/Images/ipad.jpeg", "../resource/Images/receipt.png")

 

코드 설명

img1 + img2 

각행렬의 요소를 더하는 방법이다. 만약 요소의 값이 255보다 더 크다면 256으로 나누어서 나머지를 값으로 지정한다.

 

cv2.add(img1, img2)

더한 결과가 255보다 크다면 255로 지정한다. 

결과 

원본 1

원본 2

 

cv2.add

 

img1 + img2 

이미지 블렌딩

이미지 블렌딩은 가중치를 두어 두 이미지를 합치는 방법이다. 

g(x) = (1-a)f(x)  + ag(x)

함수식을 위와 같이 표현할 수 있다. f(x)는 그림 1 g(x)는 그림 2이다. (1-a)가 그림 1이 이만큼 보였으면 좋겠다는 거고 g(x)는 a만큼 만 보였으면 좋겠다는 것이다. 따라서 가중치 만큼만 보이게 만드는 것이다. 

 

코드

import cv2
import numpy as np


def onMouse(x):
    pass


def imageBlending(imgfile1, imgfile2):
    img1 = cv2.imread(imgfile1)
    img2 = cv2.imread(imgfile2)

    cv2.namedWindow("blending", cv2.WINDOW_NORMAL)
    cv2.createTrackbar('weight', 'blending', 0, 100, onMouse) 
	#트랙바를 만들어서 가중치를 조절해줍니다. 
    mix = 0

    img1 = cv2.resize(img1, (1200, 600))
    img2 = cv2.resize(img2, (1200, 600))

    while True:
        weighted_img = cv2.addWeighted(img1, float(mix)/100, img2, float(100 - mix)/100, 0)
        # 두개의 이미지를 가중치에 따라서 다르게 보여줍니다. 
        cv2.imshow("blending", weighted_img)

        k = cv2.waitKey(1) & 0xFF
        if k == 27:
            break

        mix = cv2.getTrackbarPos("weight", "blending") # trackBar의 값을 가져옵니다. 

    cv2.destroyAllWindows()


imageBlending("../resource/Images/ipad.jpeg", "../resource/Images/desktop.png")

결과

bitOperation 하기

이미지에 다른 이미지를 roi영역에 추가하는 작업을 해보겠습니다. 

코드 

import numpy as np
import cv2


def bitOperation(hpos, vpos):
    img1 = cv2.imread("../resource/Images/desktop.png")
    img2 = cv2.imread("../resource/Images/ipad.jpeg")

    # 결과 값을 보여줄 namedWindow 지정
    cv2.namedWindow('result', cv2.WINDOW_NORMAL)
    cv2.namedWindow('mask', cv2.WINDOW_NORMAL)
    cv2.namedWindow('mask_inv', cv2.WINDOW_NORMAL)
    cv2.namedWindow('img_fg', cv2.WINDOW_NORMAL)
    cv2.namedWindow('img_bg', cv2.WINDOW_NORMAL)

    # img2 resize해준다.
    img2 = cv2.resize(img2, (800, 500))

    # 이미지의 가로길이 세로길이 가져온다.
    rows, cols, channel = img2.shape
    # 입력받은 roi지정
    roi = img1[vpos:vpos + rows, hpos: hpos + cols]

    # 마스크 만들기
    img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
    mask_inv = cv2.bitwise_not(mask)

    cv2.imshow("mask", mask)
    cv2.imshow("mask_inv", mask_inv)

    # 0이면 그대로 두고 아니면 그대로 mask를 씌웁니다.
    img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
    img2_fg = cv2.bitwise_and(img2, img2, mask=mask)

    cv2.imshow("img_fg", img2_fg)
    cv2.imshow("img_bg", img1_bg)

    # 두 이미지를 더해서 검은 부분과 색이 있는 부분이 더해져서 없어집니다. 
    dst = cv2.add(img1_bg, img2_fg)
    img1[vpos: vpos + rows, hpos: hpos + cols] = dst

    cv2.imshow('result', img1)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


bitOperation(10, 10)

코드 설명

 rows, cols, channel = img2.shape

집어 넣으려는 이미지의 속성을 가져온다. 


roi = img1[vpos:vpos + rows, hpos: hpos + cols]

지정된 크기만큼 영역을 가져옵니다. 


img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

마스크를 만들기 위해서 이미지의 색을 흑백으로 바꿔줍니다. 

 

ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)

threshold를 만들어서 mask를 만들어줍니다. threshold는 예전에 문턱 전압 뭐 이렇게 배운 기억이 나는데 여기서는 10 이상이면 하얀색 아니면 검은색으로 만들어줍니다. 

 

mask_inv = cv2.bitwise_not(mask)

마스크의 반대로 만들어줍니다.



img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)

and연산을 진행하는데 0이면 maks값을 씌워주고 roi와 roi and 연산을 진행합니다. 


img2_fg = cv2.bitwise_and(img2, img2, mask=mask)

img2, img2는 and연산을 진행합니다. 0이면 mask를 씌워줍니다. 

 

dst = cv2.add(img1_bg, img2_fg)

img1_bg와 img2_fg를 더해줍니다. 한부분은 완점 검은색 일꺼고 다른 한 이미지는 색을 갖고 있을 것입니다. 그래서 더해줄 때검은 부분은 이미지의 색으로 채워 질 것입니다. 

 

결과