[v0.19]μμμ²λ¦¬_ νν°μ 컨볼루μ μ°μ°, λΈλ¬λ§
220108 μμ±
<λ³Έ λΈλ‘κ·Έλ κ·νμ΄ μμ¬λμ λΈλ‘κ·Έλ₯Ό μ°Έκ³ ν΄μ 곡λΆνλ©° μμ±νμμ΅λλ€>
OpenCV - 17. νν°(Filter)μ 컨볼루μ (Convolution) μ°μ°, νκ· λΈλ¬λ§, κ°μ°μμ λΈλ¬λ§, λ―ΈλμΈ λΈλ¬λ§,
μ΄λ² ν¬μ€ν λΆν°λ μμ νν°μ λν΄ μμλ³΄κ² μ΅λλ€. μ΄λ² ν¬μ€ν μμ 'νμ΄μ¬μΌλ‘ λ§λλ OpenCV νλ‘μ νΈ(μ΄μΈμ° μ )'λ₯Ό μ 리ν κ²μμ λ°νλλ€. μ½λ: github.com/BaekKyunShin/OpenCV_Project_Python/tree
bkshin.tistory.com
1. νν° (Filter)μ 컨볼루μ (Convolution)
κ³΅κ° μμ νν°λ§(spacial domain filtering)
: μλ‘μ΄ ν½μ κ°μ μ»μ λ νλμ ν½μ κ°μ΄ μλ κ·Έ μ£Όλ³ ν½μ λ€μ κ°μ νμ©
: μ°μ° λμ ν½μ κ³Ό κ·Έ μ£Όλ³ ν½μ λ€μ νμ©νμ¬ μλ‘μ΄ ν½μ κ°μ μ»λ λ°©λ²
λΈλ¬λ§(Blurring)
: κΈ°μ‘΄μ μμμ νλ¦Ώνκ² λ§λλ μμ
컀λ(kernel)
: μ£Όλ³ ν½μ μ μ΄λ λ²μκΉμ§ νμ©ν μ§ κ·Έλ¦¬κ³ μ°μ°μ μ΄λ»κ² ν μ§λ₯Ό κ²°μ
: μλ(window), νν°(filter), λ§μ€ν¬(mask)λΌκ³ λ λΆλ₯Έλ€
컨볼루μ μ°μ°
: μΌλμΌλ‘ λμνλ μμΉμ μλ 컀λμ μμμ λμνλ μ λ ₯ ν½μ κ°μ κ³±ν΄μ λͺ¨λ ν©ν κ²μ
κ²°κ³Ό ν½μ κ°μΌλ‘ κ²°μ
: μ°μ°μ λ§μ§λ§ ν½μ κΉμ§ λ°λ³΅
dst = cv2.filter2D(src, ddepth, kernel, dst, anchor, delta, borderType)
: 컨볼루μ
μ°μ°νκΈ°
- src : μ
λ ₯ μμ, Numpy λ°°μ΄
- ddepth: μΆλ ₯ μμμ dtype (-1: μ
λ ₯ μμκ³Ό λμΌ)
- kernel: 컨볼루μ
컀λ, float32μ n x n ν¬κΈ° λ°°μ΄
- dst(optional): κ²°κ³Ό μμ
- anchor(optional): 컀λμ κΈ°μ€μ , default: μ€μ¬μ (-1, -1)
- delta(optional): νν°κ° μ μ©λ κ²°κ³Όμ μΆκ°ν κ°borderType(optional): μΈκ³½ ν½μ
보μ λ°©λ² μ§μ
2. νκ· λΈλ¬λ§ (Average Blurring)
: λΈλ¬λ§μ μ΄μ μ΄ λ§μ§ μλ―μ΄ μμμ νλ¦Ώνκ² νλ μμ
: νκ· λΈλ¬λ§μ μ£Όλ³ ν½μ κ°λ€μ νκ· μ μ μ©
: μ£Όλ³ ν½μ λ€μ νκ· κ°μ μ μ©νλ©΄ ν½μ κ° μ°¨μ΄κ° μ μ΄μ Έ μ λͺ λκ° λ¨μ΄μ Έ μ 체μ μΌλ‘ νλ¦Ώνλ€
# νκ· νν°λ₯Ό μμνμ¬ λΈλ¬ μ μ©
import cv2
import numpy as np
img = cv2.imread('img/night.jpg')
'''
#5x5 νκ· νν° μ»€λ μμ± ---β
kernel = np.array([[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04]])
'''
# 5x5 νκ· νν° μ»€λ μμ± ---β‘
kernel = np.ones((5,5))/5**2
# νν° μ μ© ---β’
blured = cv2.filter2D(img, -1, kernel)
# κ²°κ³Ό μΆλ ₯
cv2.imshow('origin', img)
cv2.imshow('avrg blur', blured)
cv2.waitKey()
cv2.destroyAllWindows()
# 5x5 νκ· λΈλ¬λ§ νν° μ»€λ μμ±
kernel = np.ones((5,5))/5**2
- 5 x 5 νν°μ μμ κ°μμΈ 5**2(=25)λ‘ λλκΈ°
- νν°μ ν¬κΈ°κ° ν΄μλ‘ νκ· λΈλ¬λ§μ μ μ©νμ λ μ λͺ λκ° λ λ¨μ΄μ§λ€
+) opencv μ νκ· λΈλ¬λ§ ν¨μ
dst = cv2.blur(src, ksize, dst, anchor, borderType)
: 컀λμ ν¬κΈ°λ§ μ ν΄μ£Όλ©΄ μμμ νκ· μ»€λμ μμ±ν΄μ νκ· λΈλ¬λ§μ μ μ©ν μμμ μΆλ ₯
: 컀λ ν¬κΈ°λ μΌλ°μ μΌλ‘ νμ
- src : μ
λ ₯ μμ, numpy λ°°μ΄
- ksize : 컀λμ ν¬κΈ°
- λλ¨Έμ§ νλΌλ―Έν°λ cv2.filter2D()μ λμΌ
dst = cv2.boxFilter(src, ddepth, ksize, dst, anchor, normalize, borderType)
: normalizeμ Trueλ₯Ό μ λ¬νλ©΄ cv2.blur() ν¨μμ λμΌν κΈ°λ₯
- ddepth : μΆλ ₯ μμμ dtype (-1: μ λ ₯ μμκ³Ό λμΌ)
- normalize(optional) : 컀λ ν¬κΈ°λ‘ μ κ·ν(1/ksize²) μ§μ μ¬λΆ (Boolean), default=True
- λλ¨Έμ§ νλΌλ―Έν°λ cv2.filter2D()μ λμΌ
# λΈλ¬ μ μ© ν¨μλ‘ λΈλ¬λ§ μ μ©
import cv2
import numpy as np
file_name = 'img/taekwonv1.jpg'
img = cv2.imread(file_name)
# blur() ν¨μλ‘ λΈλ¬λ§ ---β
blur1 = cv2.blur(img, (10,10))
# boxFilter() ν¨μλ‘ λΈλ¬λ§ μ μ© ---β‘
blur2 = cv2.boxFilter(img, -1, (10,10))
# κ²°κ³Ό μΆλ ₯
merged = np.hstack( (img, blur1, blur2))
cv2.imshow('blur', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
- λ ν¨μ λμΌν μ΄λ―Έμ§ μΆλ ₯ !
3. κ°μ°μμ λΈλ¬λ§(Gaussian Blurring)
: κ°μ°μμ λΆν¬λ₯Ό κ°λ 컀λλ‘ λΈλ¬λ§ νλ κ²
: κ°μ°μμ λΆν¬(gaussian distribution)λ μ κ· λΆν¬(normal distribution)μ΄λΌκ³ λ ν¨
: νκ· κ·Όμ²μ λͺ°λ € μλ κ°λ€μ κ°μκ° λ§κ³ νκ· μμ λ©μ΄μ§μλ‘ κ·Έ κ°μκ° μ μ΄μ§λ λΆν¬
: κ°μ°μμ λΈλ¬λ§ 컀λμ μ€μκ°μ΄ κ°μ₯ ν¬κ³ μ€μμμ λ©μ΄μ§μλ‘ κ·Έ κ°μ΄ μμμ§λ€
- κ°μ°μμ λΈλ¬λ§ 컀λμ μ μ©νλ©΄ λμ ν½μ μ κ°κΉμΈμλ‘ λ§μ μν₯μ μ£Όκ³ ,
λ©μ΄μ§μλ‘ μ μ μν₯μ μ£ΌκΈ° λλ¬Έμ
μλμ μμκ³Ό λΉμ·νλ©΄μλ λ Έμ΄μ¦λ₯Ό μ κ±°νλ ν¨κ³Ό
cv2.GaussianBlur(src, ksize, sigmaX, sigmaY, borderType)
: 컀λ ν¬κΈ°μ νμ€ νΈμ°¨λ₯Ό μ λ¬νλ©΄ κ°μ°μμ λΈλ¬λ§μ μ μ©
- src : μ
λ ₯ μμ
- ksize : 컀λ ν¬κΈ° (μ£Όλ‘ νμ)
- sigmaX : X λ°©ν₯ νμ€νΈμ°¨ (0: auto) -> μλμΌλ‘ νμ€νΈμ°¨λ₯Ό μ νν΄μ μ¬μ©
- sigmaY(optional) : Y λ°©ν₯ νμ€νΈμ°¨ (default: sigmaX) -> μλ΅νλ©΄ sigmaX κ°κ³Ό λμΌ
- borderType(optional) : μΈκ³½ ν
λ리 보μ λ°©μ
ret = cv2.getGaussianKernel(ksize, sigma, ktype)
: 컀λ ν¬κΈ°μ νμ€ νΈμ°¨λ₯Ό μ λ¬νλ©΄ κ°μ°μμ νν°λ₯Ό λ°ν
: λ°νλ νν°λ 1μ°¨μμ΄λ―λ‘ cv2.filter2D() ν¨μμ μ¬μ©νλ €λ©΄ ret * ret.Tμ κ°μ νμμΌλ‘ μ λ¬
- ret : κ°μ°μμ 컀λ (1μ°¨μμ΄λ―λ‘ ret * ret.T ννλ‘ μ¬μ©ν΄μΌ ν¨)
# κ°μ°μμ λΈλ¬λ§
import cv2
import numpy as np
img = cv2.imread('img/gaussian_noise.jpg')
# κ°μ°μμ 컀λμ μ§μ μμ±ν΄μ λΈλ¬λ§ ---β
k1 = np.array([[1, 2, 1],
[2, 4, 2],
[1, 2, 1]]) *(1/16)
blur1 = cv2.filter2D(img, -1, k1)
# κ°μ°μμ 컀λμ APIλ‘ μ»μ΄μ λΈλ¬λ§ ---β‘
k2 = cv2.getGaussianKernel(3, 0)
blur2 = cv2.filter2D(img, -1, k2*k2.T)
# κ°μ°μμ λΈλ¬ APIλ‘ λΈλ¬λ§ ---β’
blur3 = cv2.GaussianBlur(img, (3, 3), 0)
# κ²°κ³Ό μΆλ ₯
print('k1:', k1)
print('k2:', k2*k2.T)
merged = np.hstack((img, blur1, blur2, blur3))
cv2.imshow('gaussian blur', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 첫 λ²μ§Έλ κ°μ°μμ νν°λ₯Ό μ§μ μμ±ν΄μ cv2.filter2D() ν¨μμ μ λ¬νμ¬ λΈλ¬λ§
- λ λ²μ§Έλ cv2.getGaussianKernel() ν¨μλ₯Ό μ΄μ©ν΄ κ°μ°μμ 컀λ μ»κ³ cv2.filter2D() ν¨μμ μ λ¬νμ¬ λΈλ¬λ§
- μΈ λ²μ§Έλ cv2.GaussianBlur() ν¨μλ₯Ό νμ©νμ¬ νν°λ₯Ό λ³λλ‘ κ΅¬νμ§ μκ³ μ§μ κ°μ°μμ λΈλ¬λ§μ μ μ©
- κ°μ°μμ λΈλ¬λ§μ λ Έμ΄μ¦λ₯Ό μ κ±°νλ ν¨κ³Ό
4. λ―ΈλμΈ λΈλ¬λ§(Median Blurring)
: 컀λμ ν½μ κ° μ€ μ€μκ°μ μ ννλ κ²
: λ―ΈλμΈ λΈλ¬λ§μ μκΈ-νμΆ μ‘μμ μ κ±°νλ ν¨κ³Ό
: μκΈ-νμΆ μ‘μμ΄λ μ΄λ―Έμ§μ μκΈκ³Ό νμΆλ₯Ό λΏλ¦° κ²κ³Ό κ°μ΄ μκΈ΄ μ‘μ
dst = cv2.medianBlur(src, ksize)
src: μ
λ ₯ μμ
ksize: 컀λ ν¬κΈ°
# λ―ΈλμΈ λΈλ¬λ§
import cv2
import numpy as np
img = cv2.imread("img/salt_pepper_noise.jpg")
# λ―ΈλμΈ λΈλ¬ μ μ© --- β
blur = cv2.medianBlur(img, 5)
# κ²°κ³Ό μΆλ ₯
merged = np.hstack((img,blur))
cv2.imshow('media', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
5. λ°μ΄λ ν°λ΄ νν°(Bilateral Filter)
: κ²½κ³λ₯Ό νλ¦Ώνκ² νλ λ¬Έμ λ₯Ό 보μ
: κ°μ°μμ νν°μ κ²½κ³ νν°λ₯Ό κ²°ν©
: κ²½κ³λ λλ ·νκ³ λ Έμ΄μ¦λ μ κ±°λλ ν¨κ³Όκ° μμ§λ§ μλκ° λ리λ€
dst = cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, dst, borderType)
- src : μ
λ ₯ μμ
- d : νν°μ μ§κ²½(diameter), 5λ³΄λ€ ν¬λ©΄ λ§€μ° λλ¦Ό
- sigmaColor : μ곡κ°μ μκ·Έλ§ κ°
- sigmaSpace : μ’ν 곡κ°μ μκ·Έλ§ κ°
# λ°μ΄λ ν°λ΄ νν°μ κ°μ°μμ νν° λΉκ΅
import cv2
import numpy as np
img = cv2.imread("img/gaussian_noise.jpg")
# κ°μ°μμ νν° μ μ© ---β
blur1 = cv2.GaussianBlur(img, (5,5), 0)
# λ°μ΄λ ν°λ΄ νν° μ μ© ---β‘
blur2 = cv2.bilateralFilter(img, 5, 75, 75)
# κ²°κ³Ό μΆλ ₯
merged = np.hstack((img, blur1, blur2))
cv2.imshow('bilateral', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
- κ°μ°μμμ κ²½κ³κ° νλ¦Ώ, λ ν리λ©ν ..
- λ°μ΄λ ν°λ΄μ λ Έμ΄μ¦ μ€λ©΄μ κ²½κ³κ° μ μ§, κ°μ°μμλ³΄λ¨ μ λͺ λλ ·