• Home
  • About
    • Yerim Oh photo

      Yerim Oh

      Happy and worthwhile day by day :)

    • Learn More
    • Email
    • LinkedIn
    • Instagram
    • Github
    • Youtube
  • Posts
    • All Posts
    • All Tags
  • Projects

[010] OpenCV 영상처리 이미지 비트연산

20 Jan 2020

Reading time ~3 minutes

Table of Contents
  • 이미지
  • 이미지 비트 연산
    • 비트연산 종류
    • 예제
      • C++
        • 최종코드
      • PYTHON
    • 최종코드

이미지

  • 이미지 비트 연산
    • 비트연산 종류
    • 예제
      • C++
      • PYTHON

이미지 비트 연산

OpenCV에서는 이미지를 대상으로 비트 연산을 수행하는 함수를 제공

비트연산 종류

cv2.bitwise(연산 이미지1, 연산 이미지2, 경과파일, 용영역) 연산 이미지1과 연산 이미지2의 값을 비트 단위로 파악하며, 두 이미지의 요소별 논리연산

  • 논리곱(bitwise_and) 두 이미지의 요소별 논리곱을 계산
  • 논리합(bitwise_or) 논리합 함수는 두 이미지의 요소별 논리합을 계산
  • 배타적 논리합(bitwise_xor) 두 이미지의 요소별 배타적 논리합을 계산
  • 부정(bitwise_not) 연산 이미지1의 값을 비트 단위로 파악하며, 해당 비트에 대해 NOT 연산을 진행

예제

and 연산을 사용하여 penCV 로고를 오른쪽에 있는 배경사진에 합성
(로고 이미지) image

(배경 이미지)
image

C++

[step1]
우선 로고에 대한 이진화 이미지를 만듦

[step2]
로고 이미지에서 배경을 지우고 배경 이미지에 합성하려면 2개의 이진화 이미지가 필요.
(그냥 이진화)
로고만 남기고 배경을 지우기 위해 사용하고,

Mat img_gray;
cvtColor(img_logo, img_gray, COLOR_BGR2GRAY);
Mat img_mask;
threshold(img_gray, img_mask, 200, 255, THRESH_BINARY);

(이진화 반전)
논리 부정 이용하여 반전시킴
배경에서 로고가 들어갈 부분만 배경을 지우기 위해 사용

Mat img_mask_inv;
bitwise_not(img_mask, img_mask_inv);

image

[step3]
로고 이미지 크기만큼 배경 이미지를 잘라내서 이미지 삽입

int height = img_logo.rows;
int width = img_logo.cols;
Mat img_roi(img_background, Rect(0, 0, width, height));

[step4]
왼쪽 이미지는 로고 이미지에서 로고만 빼고 나머지 배경을 지운 결과
오른쪽 이미지는 로고 이미지와 같은 크기를 배경 이미지 에서 가져와서 로고가 들어갈 부분만 배경을 지운 결과입니다.

Mat img1, img2;
bitwise_and(img_logo, img_logo, img1, img_mask_inv);
bitwise_and(img_roi, img_roi, img2, img_mask);

image

[step5]
bitwise and 연산 결과 bitwise and 연산 결과를 하나로 합치면 배경 이미지에 자연스럽게 로고가 합성됨

 Mat dst;
 add(img1, img2, dst);

[step6]
이제 원본 배경 이미지로 다시 복사해주면 됨

dst.copyTo(img_background(Rect(0, 0, width, height)));

image

최종코드

# include < opencv2/opencv.hpp>
using namespace cv;
int main()
{ // 사용할 이미지를 불러옵니다.
  Mat img_logo, img_background;
  img_logo = imread("logo.png", IMREAD_COLOR);
  img_background = imread("background.png", IMREAD_COLOR);

  // 로고를 이진화합니다.
  Mat img_gray;
  cvtColor(img_logo, img_gray, COLOR_BGR2GRAY);
  Mat img_mask;
  threshold(img_gray, img_mask, 200, 255, THRESH_BINARY);

  // 배경을 지우고 로고만 배경 이미지에 보여주려면 // 반전된 이진화 이미지도 필요합니다.
  Mat img_mask_inv;
  bitwise_not(img_mask, img_mask_inv);

  // 로고 이미지 크기만큼 배경 이미지를 잘라냅니다.
  // 로고가 삽입될 위치가 됩니다.
  int height = img_logo.rows;
  int width = img_logo.cols;
  Mat img_roi(img_background, Rect(0, 0, width, height));

  // 이진화 이미지를 사용하여 로고 이미지에서는 배경을 지우고 // 배경 이미지에서는 로고가 들어갈 위치를 제거합니다.
  Mat img1, img2;
  bitwise_and(img_logo, img_logo, img1, img_mask_inv);
  bitwise_and(img_roi, img_roi, img2, img_mask);

  // bitwise_and함수를 사용한 결과를 더하면 // 배경 이미지에 로고가 합성된 결과를 얻을 수 있습니다.
  Mat dst;
  add(img1, img2, dst);
  // 합성 결과를 배경 이미지에 복사해줍니다
  dst.copyTo(img_background(Rect(0, 0, width, height)));

  // 결과를 보여줍니다.
  imshow("background", img_background);
  // imshow("logo", img_logo);
  // imshow("img_mask_inv", img_mask_inv);
  // imshow("img_mask", img_mask);
  // imshow("img1", img1);
  // imshow("img2", img2);
  // imshow("dst", dst);
  waitKey(0);
}

PYTHON

[step1]
우선 로고에 대한 이진화 이미지를 만듦

[step2]
로고 이미지에서 배경을 지우고 배경 이미지에 합성하려면 2개의 이진화 이미지가 필요.
(그냥 이진화)
로고만 남기고 배경을 지우기 위해 사용하고,

img_gray = cv.cvtColor(img_logo, cv.COLOR_BGR2GRAY) 
ret,img_mask = cv.threshold(img_gray, 200, 255, cv.THRESH_BINARY)

(이진화 반전)
논리 부정 이용하여 반전시킴
배경에서 로고가 들어갈 부분만 배경을 지우기 위해 사용

img_mask_inv = cv.bitwise_not(img_mask)

image

[step3]
로고 이미지 크기만큼 배경 이미지를 잘라

height, width = img_logo.shape[:2]
img_roi = img_background[0:height, 0:width]

[step4]
왼쪽 이미지는 로고 이미지에서 로고만 빼고 나머지 배경을 지운 결과
오른쪽 이미지는 로고 이미지와 같은 크기를 배경 이미지 에서 가져와서 로고가 들어갈 부분만 배경을 지운 결과입니다.

img1 = cv.bitwise_and(img_logo, img_logo, mask = img_mask_inv) 
img2 = cv.bitwise_and(img_roi, img_roi, mask=img_mask)

image

[step5]
bitwise and 연산 결과 bitwise and 연산 결과를 하나로 합치면 배경 이미지에 자연스럽게 로고가 합성됨

dst = cv.add(img1, img2)

[step6]
이제 원본 배경 이미지로 다시 복사해주면 됨

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

image

최종코드

import cv2 as cv 
import numpy as np

# 사용할 이미지를 불러옵니다.
img_logo = cv.imread('logo.png', cv.IMREAD_COLOR) 
img_background = cv.imread('background.png', cv.IMREAD_COLOR)

# 로고를 이진화합니다.
img_gray = cv.cvtColor(img_logo, cv.COLOR_BGR2GRAY) 
ret,img_mask = cv.threshold(img_gray, 200, 255, cv.THRESH_BINARY)


# 배경 지우고 로고만 배경 이미지에 보여주려면 반전된 # 이진화 이미지도 필요합니다.
img_mask_inv = cv.bitwise_not(img_mask)

# 로고 이미지 크기만큼 배경 이미지를 잘라냅니다.
# 로고가 삽입될 위치가 됩니다.
height, width = img_logo.shape[:2]
img_roi = img_background[0:height, 0:width]

# 이진화 이미지를 사용하여 로고 이미지에서는 배경을 지우고 # 배경 이미지에서는 로고가 들어갈 위치를 제거합니다.
img1 = cv.bitwise_and(img_logo, img_logo, mask = img_mask_inv) 
img2 = cv.bitwise_and(img_roi, img_roi, mask=img_mask)

# bitwise_and함수를 사용한 결과를 더하면 # 배경 이미지에 로고가 합성된 결과를 얻을 수 있습니다.
dst = cv.add(img1, img2)

# 합성 결과를 배경 이미지에 복사해줍니다.
img_background[0:height, 0:width] = dst

# 결과를 보여줍니다.
cv.imshow('background', img_background) 
# cv.imshow('logo', img_logo) 
# cv.imshow('img_mask_inv', img_mask_inv) 
# cv.imshow('img_mask', img_mask) 
# cv.imshow('img1', img1) 
# cv.imshow('img2', img2) 
# cv.imshow('dst', dst) cv.waitKey(0)


OpenCV Share Tweet +1