Data Science/2) Open CV

[Python] 이미지 블렌딩, 이미지 비트 연산

은구잇 2021. 12. 5. 15:17
728x90

1. 이미지 블렌딩이란?

이미지 블렌딩은 이미지를 서로 합칠때 가중치를 두어 합치는 방법.

두 이미지가 있고 1번에서 2번 이미지로 전환하는 경우 서서히 변환하는 기능을 이용할때 좋은 기법

 

이미지 블랜딩 기법을 구현하기 위한 수식

g(x) = (1-a)f_0(x) + af_1(x)

a의 값이 0에서 1로 변해가면서 f_0(x)의 효과는 점점 작아지고, f_1(x)의 효과는 점점 커지게 됨.

이 수식은 addWeighted(이미지파일, 수식) 함수를 사용하면 된다.

 

아래의 예제에서는 위에 수식과 트랙바를 이용해서 구현해보았다.

 

<코드>

img1 = cv2.imread('./image/anemone-5281964_1280.jpg')
img2 = cv2.imread('./image/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(1) & 0xFF
        if k == 27:
            break
        

트랙바를 이용해서 블렌딩 강도를 조절할 수 있음.

 

 

 

2. 이미지 비트연산이란?

이미지는 AND, NOT, OR , XOR 비트연산이 가능핟.

이미지 비트 연산은 특정 영역을 추출하거나 직사각형 모양이 아닌 ROI를 정의할때,

이미지의 바탕을 제거하고 2개의 이미지를 합칠 때에 유용하게 사용 할  수 있음.
    cv2.destroyAllWindows()
    cv2.waitKey(1)

 

아래 이 두개의 파일을 합쳐볼건데 로고는 검정배경을 제거하고 자연스럽게 합칠거다.

2.1) ROI영역 추출 

로고를 넣을 이미지 영역을 추출한다.

<코드>

rows, cols, channels = img2.shape
roi = img1[ 10:10 + rows, 10:10 + cols ]

roi_bgr = bgr_to_rgb(roi)
plt.imshow(roi_bgr)
plt.title('ROI')
plt.xticks([])
plt.yticks([])
plt.show()

 

2.2) 로고 이미지를 흑백으로 전환하고 binary이미지로 전환한다.

threshold함수를 사용하는 이유는 픽셀값이 10 이상으로 넘어가면 255로 변경해서 

뒷배경을 제외하고 정확한 로고 부분을 추출하기 위함이다.

 

또한 비트 연산으로 이를 반전시켜 mask_inv에 저장한다. (흰->검, 검->흰)

<코드>

img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)  # 0->255 / 255-> 0 반대로 만드는 연산

images = [img2gray, mask, mask_inv]
titles = ["gray-scale", "mask", "mask_inv"]

plt.figure(figsize=(8, 8)) # 가로세로 8인치로 설정
for i in range(3):
    plt.subplot(1, 3, i+1)
    plt.imshow(images[i], cmap="gray")
    plt.title(titles[i])
    plt.axis('off')
    
plt.tight_layout()
plt.show()

 

 

 

2.3) mask, maks_inv로 추출한 이미지를 배경과 로고 이미지와 bitwise_and 연산

둘다 0이 아닌 값만 통과시키기 (검정 제외시키기)

 

img1_bg = cv2.bitwise_and(roi, roi, mask = mask_inv)
img2_fg = cv2.bitwise_and(img2, img2, mask = mask)
dst = cv2.add(img1_bg, img2_fg)

img1_bg_rgb = bgr_to_rgb(img1_bg)
img2_fg_rgb = bgr_to_rgb(img2_fg)
dst_rgb = bgr_to_rgb(dst)

 


images = [img1_bg_rgb, img2_fg_rgb, dst_rgb]
titles = ["img1_bg", "img2_fg", "dst"]

plt.figure(figsize=(8, 8))
for i in range(3):
    plt.subplot(1, 3, i+1)
    plt.imshow(images[i], cmap="gray")
    plt.title(titles[i])
    plt.axis('off')
    
plt.tight_layout()
plt.show()

2.4) 최종으로 합친 dst를  img1에 합쳐주면 끝

 

img1[ 10:10 + rows, 10:10 + cols ] = dst
cv2.imshow('result', img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.waitKey(1)