본문 바로가기

머신러닝,딥러닝/opencv

opencv 입문하기 6편 트랙바, 산술 연산

 

1. 트랙바

 

cv2.createTrackbar(trackbarName, windowName, value, count, onChange)

 

   
trackbarName 트랙바 이름
windowName 트랙바를 포함하는 윈도우 이름
value 트랙바 초기값
count 트랙바 최댓값(defalut = 0)
onChange 트랙바 값이 변경될떄마다 호출할 콜백 함수 이름
콜백 함수는 아래처럼 사용됨
onChange(pose)

 

*  트랙바를 이용한 grayscale 조절 * 

 

import cv2
import numpy as np


def level_change(pos):

    value = pos * 8

    if value >= 255:
        value = 255

    img[:] = value
    cv2.imshow('img', img)


img = np.zeros((480, 640), dtype=np.uint8)


cv2.namedWindow('img')
cv2.createTrackbar('level', 'img', 0, 32, level_change)

cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()

 

 

* 트랙바를 이용히여 B,G,R 컬러를 각각 조절할 수 있는 프로그램  *

 

 

 

# trackbar_RGB_controller.py
# R,G,B 가 모두 있는 트랙바

import numpy as np
import cv2


def nothing(x):
    pass


frame = np.zeros((512, 512, 3), np.uint8)
cv2. namedWindow('frame')

cv2.createTrackbar('R', 'frame', 0, 255, nothing)
cv2.createTrackbar('G', 'frame', 0, 255, nothing)
cv2.createTrackbar('B', 'frame', 0, 255, nothing)

while True:
    cv2.imshow('frame', frame)

    key = cv2.waitKey(1)

    if key == 27:
        break

    r = cv2.getTrackbarPos('R', 'frame')
    g = cv2.getTrackbarPos('G', 'frame')
    b = cv2.getTrackbarPos('B', 'frame')

    frame[:] = [b, g, r]

cv2.destroyAllWindows()

 

2. 영상 산술연산 

 

grayscale 인 경우 특정값을 더하거나 빼서 밝기 조절이 가능합니다. 

영상의 밝기 조절은 모든 픽셀의 값을 더하거나 빼서 가능합니다. 

 

• 단, 최솟값 0, 최댓값 255로 제한되어 있음

 

cv2.add(src1, src2, dst=None, mask=None, dtype=None) 

 

• src1 : 첫 번째 입력 영상
• src2 : 두 번째 입력 영상
• dst : 출력 영상 결과
• mask : 마스크 영상
• dtype : 출력 영상(dst) 의 데이터 타입
예) cv2.CV_8U, cv2.CV_32F 등

 

import cv2
import numpy as np
x = np.uint8([250])  # 250 + 10 = 260 => 255
y = np.uint8([10])  # 250 + 10 = 260 => 260 % 256 = 4
print(cv2.add(x, y))
print(x+y)

위 코드의 실행결과는 255 와 4입니다. 

opencv 의 경우 데이터 타입의 범위를 벗어나면 데이터 타입이 갖을 수 있는 최대값이 됩니다. 

 

 

  위 메서드를 컬러 영상에 적용한 간단한 예제입니다. 

 

import os

import cv2

path = os.path.join('my_images', '고양이.jpg')
src = cv2.imread(path)

dst = cv2.add(src, 100)
dst2 = cv2.add(src, (100, 100, 100, 0))

src = cv2.resize(src, dsize=(480, 320), interpolation=cv2.INTER_AREA)
dst = cv2.resize(dst, dsize=(480, 320), interpolation=cv2.INTER_AREA)
dst2 = cv2.resize(dst2, dsize=(480, 320), interpolation=cv2.INTER_AREA)

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.imshow('dst2', dst2)

cv2.moveWindow('src', 200, 200)
cv2.moveWindow('dst', 650, 200)
cv2.moveWindow('dst2', 1150, 200)

cv2.waitKey()
cv2.destroyAllWindows()

2.1 임의의 영상과 (직접 만든) src2 영상 를 활용하여 두 영상의 add,substract, weighted sum, abs diff 결과를 하나의 창에 나타내는 프로그램 구현하기

 

* 결과 *

 

 

2-1) cv2.subtract(src1, src2, dst=None, mask=None, dtype=None)

 

2-2) cv2.addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None)

alpha: src1 에 부여되는 가중치

beta: src2 에 부여되는 가중치

gamma: 영상에 공통적으로 더하는 값 

dst: 출력 영상 결과

dtype: 출력 영상 타입

 

addWeighted 메서드는 알파 블렌딩이라 하며 메서드의 구현 수식은

 

dst(x,y) = t x src1(x,y) + (1-t) x src2(x,y)   (x 는 곱하기를 의미) 

 

입니다. 

 

 

2-3) cv2.absdiff(src1, src2, dst=None)

 

- 두 영상의 같은 위치에 있는 픽셀값의 차이를 출력

- 연속된 영상의 경우 변화가 있는 물체의 결과만 출력

 

위의 3가지 메서드와 앞에서 배운 add 메서드 4가지를 이용하여 src1, src2 이미지들로 산술 연산을 진행한 결과입니다.

 

 

2.1 코드

 

# opencv_Arithmetic.py

import os

import cv2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec

path = os.path.join('my_images', '고양이.jpg')
src1 = cv2.imread(path, cv2.IMREAD_GRAYSCALE)

h, w = src1.shape
print(h, w)

src2 = np.ones((h, w), dtype=np.uint8)
cv2.rectangle(src2, (50, 50), (200, 200), 255, -1)

dst1 = cv2.add(src1, src2, dtype=cv2.CV_8U)
dst2 = cv2.subtract(src1, src2, dtype=cv2.CV_8U)
dst3 = cv2.addWeighted(src1, 0.5, src2, 0.5, 0)
dst4 = cv2.absdiff(src1, src2)

fig = plt.figure(figsize=(15, 6))
gs = gridspec.GridSpec(nrows=3,  # row 몇 개
                       ncols=2,  # col 몇 개
                       height_ratios=[2, 2, 2],
                       width_ratios=[3, 3]
                       )

plt.subplot(231), plt.axis('off'), plt.imshow(
    src1, cmap='gray'), plt.title('src1')
plt.subplot(232), plt.axis('off'), plt.imshow(
    src2, cmap='gray'), plt.title('src2')
plt.subplot(233), plt.axis('off'), plt.imshow(
    dst1, cmap='gray'), plt.title('dst1')
plt.subplot(234), plt.axis('off'), plt.imshow(
    dst2, cmap='gray'), plt.title('dst2')
plt.subplot(235), plt.axis('off'), plt.imshow(
    dst3, cmap='gray'), plt.title('dst3')
plt.subplot(236), plt.axis('off'), plt.imshow(
    dst4, cmap='gray'), plt.title('dst4')

plt.show()

 

+) bit 연산 - 픽셀별로 논리연산 후 이진수로 표현 

 

비트연산 예제1

 

 

코드

 

# bitwise_example_1.py

import os

import cv2
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec

path = os.path.join('my_images', '고양이.jpg')
src = cv2.imread(path)
gray = cv2.imread(path, cv2.COLOR_BGR2GRAY)

_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

_and = cv2.bitwise_and(gray, binary)
_or = cv2.bitwise_or(gray, binary)
_xor = cv2.bitwise_xor(gray, binary)
_not = cv2.bitwise_not(gray)

src = np.concatenate((np.zeros_like(gray), gray, binary,
                      np.zeros_like(gray)), axis=1)
dst = np.concatenate((_and, _or, _xor, _not), axis=1)
dst = np.concatenate((src, dst), axis=0)

dst = cv2.resize(dst, dsize=(1120, 640), interpolation=cv2.INTER_AREA)
cv2.imshow("dst", dst)


cv2.waitKey(0)
cv2.destroyAllWindows()

 

원본 이미지(src)와 그레이스케일(gray), 이진화(binary)을 선언합니다.

연산 이미지는 그레이스케일 이미지와 127 임곗값을 갖는 이진화 이미지를 사용합니다.

 

 

cv2.bitwise(연산 이미지1, 연산 이미지2)를 이용하여 비트 연산을 진행합니다.

논리곱값(bitwise_and), 논리합(bitwise_or), 배타적 논리합(bitwise_xor), 부정(bitwise_not) 등으로 연산이 가능합니다.

논리곱 함수는 두 이미지의 요소별 논리곱을 계산합니다.

연산 이미지1 연산 이미지2의 값을 비트 단위로 파악하며, 해당 비트에 대해 AND 연산을 진행합니다.

논리합 함수는 두 이미지의 요소별 논리합을 계산합니다.

연산 이미지1 연산 이미지2의 값을 비트 단위로 파악하며, 해당 비트에 대해 OR 연산을 진행합니다.

배타적 논리합 함수는 두 이미지의 요소별 배타적 논리합을 계산합니다.

연산 이미지1 연산 이미지2의 값을 비트 단위로 파악하며, 해당 비트에 대해 XOR 연산을 진행합니다.

논리합 함수는 두 이미지의 요소별 논리합을 계산합니다.

연산 이미지1의 값을 비트 단위로 파악하며, 해당 비트에 대해 NOT 연산을 진행합니다.

 

요소의 값이 각각 198, 255인 이미지를 배타적 논리합 비트 연산을 진행한다면 다음과 같습니다.

198은 1100 0110이 되며, 255는 1111 1111이 됩니다.

XOR 연산은 비트 값이 같으면 0, 다르다면 1이 됩니다.

각 자리수 마다 값을 비교한다면 0011 1001이 됩니다.

이 값을 10진수로 변경한다면, 57이 됩니다.

그러므로, 이미지 요소 값은 57의 값으로 할당됩니다.

 

연결 함수(np.concatenate)로 이미지들을 연결합니다.

 

비트연산 예제2

좀 더 비교를 위해 아래 2가지 이미지로 비트 연산을 진행 해보겠습니다. 

 

 

 

결과 

 

 

 

import cv2
import numpy as np
import matplotlib.pyplot as plt

src1 = cv2.imread('lenna.jpg', cv2.IMREAD_GRAYSCALE)
h, w = src1.shape
src2 = np.ones((h, w), dtype=np.uint8)

# src2 를 흑백 절반으로 바꾸기 
for x in range(int(w/2)):
    for y in range(h):
        src2[y, x] = 255  

cv2.imshow('src1', src1)
cv2.imshow('src2', src2)

bit_and = cv2.bitwise_and(src1, src2)
bit_or = cv2.bitwise_or(src1, src2)
bit_not = cv2.bitwise_not(src1, src2)
bit_xor = cv2.bitwise_xor(src1, src2)

plt.subplot(221), plt.axis('off'), plt.imshow(
    bit_and, cmap='gray'), plt.title('blt_and')
plt.subplot(222), plt.axis('off'), plt.imshow(
    bit_or, cmap='gray'), plt.title('bit_or')
plt.subplot(223), plt.axis('off'), plt.imshow(
    bit_not, cmap='gray'), plt.title('bit_not')
plt.subplot(224), plt.axis('off'), plt.imshow(
    bit_xor, cmap='gray'), plt.title('bit_xor')

plt.show()

cv2.waitKey()
cv2.destroyAllWindows()

 

이것으로 이번 포스팅은 마치겠습니다 :) 

 

https://github.com/JangDaehyuk/opencv_self_study/

 

JangDaehyuk/opencv_self_study

this repository for my study about opencv. Contribute to JangDaehyuk/opencv_self_study development by creating an account on GitHub.

github.com

 

 

 

* 참고 * 

 

http://www.gisdeveloper.co.kr/?p=6407

 

Python과 OpenCV – 7 : 이미지에 대한 산술 연산 – GIS Developer

이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_core/py_image_arithmetics/py_image_arithmetics.html 입니다. 이 글에서는 이미지에 대한 더하기 연산, 빼기 연산, Bitwise 연산 등에 대한 �

www.gisdeveloper.co.kr

https://jacegem.github.io/blog/2018/OpenCV-Python-Tutorials-08-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%9D%98-%EC%82%B0%EC%88%A0-%EC%97%B0%EC%82%B0/

 

[OpenCV-Python Tutorials] 08 이미지의 산술 연산

[OpenCV-Python Tutorials] 08 이미지의 산술 연산 목표 더하기, 빼기, 비트 연산 등과 같은 이미지에 대한 여러 가지 산술 연산에 대해 배웁니다. cv2.add(), cv2.addWeighted() 등의 함수를 배우게 됩니다. 이미�

jacegem.github.io

https://076923.github.io/posts/Python-opencv-32/

 

Python OpenCV 강좌 : 제 32강 - 비트 연산 | 076923

비트 연산(Bitwise)

076923.github.io