[ openCV ] Image Operation ( Blending, Operate Image Bit, ROI )
openCV

[ openCV ] Image Operation ( Blending, Operate Image Bit, ROI )

 

오늘은 이미지 연산에 대해서 정리를 해볼까 한다.

 

바로 알아보자

 

 

1. Blending

 

첫번째 개념은 블렌딩이다.

 

블렌딩은 2개의 이미지의 투명도를 조정하여 2개의 이미지가 겹쳐보이도록 만드는 기술이다.

 

openCV는 블렌딩을 위해 addWeighted() 함수를 이용한다.

 

addWeighted() 함수는 밑과 같은 수식으로 동작한다

 

Blending a numerical expression

상수 alpha, beta가 Threshold로 이용되며, 입력 이미지 img1, img2의 투명도를 조절한다.

 

다만 Threshold인 alpha, beta가 가질 수 있는 범위는 0.0 ~ 1.0 사이며

0.0에 가까울 수록 투명한 상태가 되며 1.0에 가까워진다면 불투명해진다.

 

gamma는 가중치 합에 추가로 더하는 상수이다.

 

이렇게 이론으로 주저리주저리 쓰는 것보다 직접 해보는게 훨씬 낫다.

바로 코드를 살펴보자.

 

import cv2
import imutils
import numpy as np 
import time

# Select The Threshold
alpha = 0.0
beta = 1.0

while alpha <= 1.0:

    img1 = cv2.imread('./cat.jpg', cv2.IMREAD_COLOR)
    img2 = cv2.imread('./beach.jpg', cv2.IMREAD_COLOR)

    #If You want use cv2.addWeighted(), You should read the same size picture
    img2_resized = cv2.resize(img2, (img1.shape[1], img1.shape[0]))

    dst = cv2.addWeighted(img1, alpha, img2_resized, beta, 0)

    #print Threshold
    print(alpha, " ", beta)

    dst = imutils.resize(dst, width=500, height=500)
    cv2.imshow("dst", dst)
    
    key = cv2.waitKey(1)

    if key == 27:
        break
    
    # Up & Down Threshold
    alpha = round(alpha + 0.1, 1)
    beta = round(beta - 0.1, 1)
    
    time.sleep(0.2)

cv2.destroyAllWindows()

 하나하나 살펴보자

 

# Select The Threshold
alpha = 0.0
beta = 1.0

위에서 말했듯 cv2.addWeighted()를 사용하기 위해서는 Threshold 값이 필요하다.

 

#If You want use cv2.addWeighted(), You should read the same size picture
img2_resized = cv2.resize(img2, (img1.shape[1], img1.shape[0]))

조금 생뚱맞은 코드 같아 보일 수도 있는데 상당히 중요하다.

 

위 코드를 통해서 두 이미지의 width, height 값을 맞춰주지 않는다면

 

Traceback (most recent call last): dst= cv2.addWeighted(img1,0.5,img2,0.5,0) cv2.error: C:\projects\opencv-python\opencv\modules\core\src\arithm.cpp:659: error: (-209) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function cv::arithm_op

 

위와 같이 흉측한 오류가 뜬다

 

구글링 결과 cv2.addWeighted() 함수를 쓰기 위해서는 두 이미지의 해상도가

항상 같아야만 된다고 한다.

 

stackoverflow.com/questions/47884187/why-does-cv2-addweighted-give-an-error-that-the-operation-is-neither-array-op

 

Why does cv2.addweighted() give an error that the operation is neither 'array op array', nor 'array op scalar', nor ' scalar op

This is my code for image blending but there is something wrong with the cv2.addweighted() function: import cv2 import numpy as np img1 = cv2.imread('1.png') img2 = cv2.imread('messi.jpg') dst= cv2.

stackoverflow.com

 

# Up & Down Threshold
    alpha = round(alpha + 0.1, 1)
    beta = round(beta - 0.1, 1)

아 코드는 Threshold 값을 조정하는 코드이다.

그리 어려운 코드가 아니니 넘기겠다.

 

[ Result ]

 

img1
img2

 

 

Blending Result

 

콘솔창에 Threshold 값이 alpha, beta 값이 출력되면서

Blending이 되는 것을 볼 수 있다.

 

 

2. Operate Image Bit

 

이미지 비트를 연산한다는 것이 조금 낯설게 느껴질 수 있는데

쉽게 말하면 이미지를 대상으로 비트 연산을 행하는 것을 의미한다.

 

이 개념에서는 사진 합성을 실습해볼것인데 생소한 함수들이 있어서

먼저 비트연산을 하는데 이용되는 함수들을 간단히 정리해보자

 

cv2.bitwise_and, cv2.bitwise_or, cv2.bitwise_not, cv2.bitwise_xor 이라는 함수들이 존재한다.

 

함수 이름에서도 알 수 있듯이 and, or, not, xor와 같은 연산을 해준다.

 

비트 연산을 모른다면 밑의 사이트를 참고하자.

ko.wikipedia.org/wiki/%EB%B9%84%ED%8A%B8_%EC%97%B0%EC%82%B0

 

비트 연산 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 둘러보기로 가기 검색하러 가기

ko.wikipedia.org

 

그렇다면 함수에 들어가는 parameter에 대해서 알아보자

 

cv2.bitwise_[bit연산자](InputArray src1, InputArray src2, InputArray mask = @)

 

조금 난해하긴 한데 대충 설명을 덧붙여보자면

mask는 범위를 뜻하며 mask 범위안에서 src1, src2의 이미지를 bit 연산해주는것이다

 

 

잘 이해가 가지 않으니 바로 코드를 살펴보자

 

import cv2
import numpy as np
import imutils

img_logo = cv2.imread('./logo.png', cv2.IMREAD_COLOR)
img_background = cv2.imread('./background.png', cv2.IMREAD_COLOR)

# LogoImage = GrayScale -> Binarization
img_gray = cv2.cvtColor(img_logo, cv2.COLOR_BGR2GRAY)
ret, img_mask = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY)

# Flip the img_mask
img_mask_inv = cv2.bitwise_not(img_mask)

# Cut the size of logo image in img_background
# The position of insert the logo image
height, width = img_logo.shape[:2]
img_roi = img_background[0:height, 0:width]

# Delect the background img in logo img Using Binarization
img1 = cv2.bitwise_and(img_logo, img_logo, mask=img_mask_inv)
# Delect the position of logo image in background
img2 = cv2.bitwise_and(img_roi, img_roi,mask=img_mask)

# add image
dst = cv2.add(img1, img2)

# copy the img to background img
img_background[0:height, 0:width] = dst

while True:
    cv2.imshow("Hello", img_background)

    key = cv2.waitKey(1)

    if key == 27:
        break

cv2.destroyAllWindows()

 

하나하나 살펴보자

 

# LogoImage = GrayScale -> Binarization
img_gray = cv2.cvtColor(img_logo, cv2.COLOR_BGR2GRAY)
ret, img_mask = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY)

우선 합성할 이미지를 GrayScale로 변환 후 Binarization을 시켜준다.

 

# Flip the img_mask
img_mask_inv = cv2.bitwise_not(img_mask)

img_mask_inv는 Binarization한 로고 이미지를 not 연산해주어서

img_mask와는 반전된 결과를 보여준다.

 

# Cut the size of logo image in img_background
# The position of insert the logo image
height, width = img_logo.shape[:2]
img_roi = img_background[0:height, 0:width]

로고의 이미지를 height, width로 지정하여

background image의 ROI를 추출한다.

 

바로 이 부분이 로고 이미지가 들어갈 부분이다.

 

# Delect the background img in logo img Using Binarization
img1 = cv2.bitwise_and(img_logo, img_logo, mask=img_mask_inv)

img_mask와 반전된 img_mask_inv라는 범위 안에서

img_logo를 and 연산해주어서 img_logo의 배경화면을 제거해준다.

 

# Delect the position of logo image in background
img2 = cv2.bitwise_and(img_roi, img_roi,mask=img_mask)

img_mask라는 범위안에서 img_background의 ROI에 img_logo가 들어갈 수 있도록

and 연산을 통해서 위치를 제거합니다.

 

# add image
dst = cv2.add(img1, img2)

img_background의 ROI 영역에 뒷배경이 제거된 img_logo를 추가해준다.

(사진 합성)

 

img_background[0:height, 0:width] = dst

최종적으로 원본 img_background에 합성된 이미지를 복사해준다.

 

[ Result ]

 

img_logo
img_background
img_logo_binarization
img_logo_binarization_flip

 

img1
img2
dst
FInal

 

개인적으로는 조금 난이도가 있는 문법이라고 생각해서

다시 한번 복습하는 것이 좋을 거 같다.

 

 

3. ROI

 

사실상  ROI는 전 게시물에서도 몇 번 언급한적이 있어서

이번에는 그냥 ROI 영역에서 canny edge를 적용해보는 실습을 하고 넘어가도록 하겠습니다.

 

import cv2

img_color = cv2.imread('./Image_Sample.jpg' , cv2.IMREAD_COLOR )

height, width = img_color.shape[:2]

center_x, center_y = int(width * 0.5), int(height * 0.5)

# Set the ROI with center Position
# If you use copy method, You will not edit original image
img_roi = img_color[center_y - 100 : center_y + 100, center_x - 100 : center_x + 100].copy()

img_gray = cv2.cvtColor(img_roi, cv2.COLOR_BGR2GRAY)
img_edge = cv2.Canny(img_gray, 100, 300)

# Translate Color image To Copy original imge
img_edge1 = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2BGR)

#Copy To Original Image
img_color[center_y- 100 : center_y + 100, center_x - 100 : center_x + 100]= img_edge1

while True:
    cv2.imshow("COLOR", img_color)
    cv2.imshow("ROI", img_roi)
    key = cv2.waitKey(1)

    if key == 27:
        break

cv2.destroyAllWindows()

 

앞에서 공부했던 openCV의 함수들이기 때문에 간략하게 설명하겠습니다.

 

height, width = img_color.shape[:2]

center_x, center_y = int(width * 0.5), int(height * 0.5)

Image의 width, height 계산 후, center position 구하기

 

# Set the ROI with center Position
# If you use copy method, You will not edit original image
img_roi = img_color[center_y - 100 : center_y + 100, center_x - 100 : center_x + 100].copy()

original image의 ROI를 center position으로 구한다.

copy method를 활용한다면 원본 이미지 수정없이 사용 가능.

 

2021/01/09 - [openCV] - [openCV] Numpy Array

 

[openCV] Numpy Array

저번주에 작성했던 2021/01/02 - [Nefus] - openCV - 기초부터 다지기에 이어서 오늘은 Numy Array가 openCV에서 어떻게 활용되는지에 대해서 정리를 해볼려고 한다. 우선 어떻게 활용되는지 알아보기 전에 Nu

confidence-10211.tistory.com

위 글에서 numpy 배열에 대해서 설명이 되어 있으니

만약 copy method의 역할이 헷갈린다면 읽어보면 좋을거 같다.

 

img_gray = cv2.cvtColor(img_roi, cv2.COLOR_BGR2GRAY)
img_edge = cv2.Canny(img_gray, 100, 300)

canny edge 검출

2021/01/16 - [openCV] - [openCV] Graphic User Interface

 

[openCV] Graphic User Interface

제목에 쫄지 말자 그저 GUI의 Full Name일뿐😬 우선 오늘은 제목에 나와 있듯이 openCV에서 지원하는 GUI를 다뤄보면서 공부해보자 0. What Is Canny Edge? 코드를 보기 전에 Canny Edge가 뭔지 알아보자🤔 Cann

confidence-10211.tistory.com

canny edge를 모른다면 위에 블로그를 참조하자

 

# Translate Color image To Copy original imge
img_edge1 = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2BGR)

원본 이미지에 합성하기 위해서 컬러 이미지로 변환

 

[ Result ]

 

 

 

오늘도 끄-읕😉

'openCV' 카테고리의 다른 글

[openCV] ROI  (0) 2021.02.17
[openCV] Draw Function  (0) 2021.02.06
[openCV] Binarization  (0) 2021.01.23
[openCV] Graphic User Interface  (0) 2021.01.16
[openCV] Numpy Array  (1) 2021.01.09