1. 程式人生 > >【cv筆記】卷積 + 數學形態學(膨脹腐蝕、開閉運算等)

【cv筆記】卷積 + 數學形態學(膨脹腐蝕、開閉運算等)

一 卷積

1 卷積定義

卷積是兩個變數在某範圍內相乘後求和的結果。如果卷積的變數是序列x(n)和h(n),則卷積的結果

y(n)=i=x(i)h(ni)=x(n)h(n)

一維卷積

【例】

X = [10, 1, 2, 3, 0, 3]
H= [0.4, 1, 0.5, 2] (卷積核Kernel
Y=X * H
這裡寫圖片描述
。。。。。。
這裡寫圖片描述 。。。。

import numpy as np
from scipy import signal

X = np.array([10, 1, 2, 3, 0
, 3]) H = np.array([2, 0.5, 1, 0.4]) S = signal.convolve(X, H) print(S)

output:

[ 20.    7.   14.5  12.    3.9   9.8   2.7   3.    1.2]

二維卷積

y[i,j]=u=kkv=kkx[u,v]h[iu,iv]
【例】
這裡寫圖片描述
import numpy as np
from scipy import signal

F = np.array([
    [1, 2, 0
, 7, 0, 3], [8, 7, 3, 4, 1, 0], [0, 3, 5, 3, 0, 1], [1, 2, 1, 7, 1, 0], [0, 0, 0, 0, 0, 1]]) H = np.array([ [-2, 1, 3], [-2, 0, 2], [1, 0, -1]]) S = signal.convolve2d(F, H, boundary='wrap',mode='valid') print(S)

output:

[[  2  19  22  11]
 [-12 -10  16  22]
 [  5 -10  -5  10]]

H、X的順序是不影響結果的,S = H * X = X * H

2 影象的卷積運算

可看做是加權求和的過程,使用到的影象區域中每個畫素分別與卷積核(權矩陣)的每個元素相乘,所有乘積只和作為區域中心畫素的新值

濾波器(卷積核)的一般要求
  • 2D卷積需要四個迴圈巢狀,比較耗時,所以我們一般採用較小的卷積核,如3*3、5*5
  • 濾波器的大小應該為奇數,如5*5 、7*7 ,這樣才會有中心,7*7的核半徑為3
  • 濾波器矩陣所有的元素之和等於1,濾波前後影象的亮度保持不變。大於1,影象變亮,小於1,影象變暗
  • 對於濾波後的結構,可能會出現0~255以外的數值。對這種情況,直接截斷到0和255之間即可
邊界處理

當處理影象邊界畫素時,卷積核與影象區域不能匹配,卷積核中心與邊界元素點對應,卷積運算出現問題,此時有以下幾種處理方式:
這裡寫圖片描述
1)想象I是無限長的影象的一部分,除了我們給定值的部分,其他部分的畫素值都是0。
這裡寫圖片描述
2)第二種方法也是想象I是無限影象的一部分。但沒有指定的部分是用影象邊界的值進行拓展。
這裡寫圖片描述
3)第三種情況就是認為影象是週期性的。也就是I不斷的重複。週期就是I的長度。在我們這裡,I(0)和I(8)的值就是一樣的,I(9)的值和I(1)的值也是一樣的。
這裡寫圖片描述
4)忽略邊界畫素(處理後的影象丟掉這些畫素)

3 卷積在影象處理中的應用

  • 均值模糊 高斯模糊
  • 高通濾波 低通濾波
  • 影象銳化 浮雕
  • 邊緣檢測
  • 。。。

例項0

下面這個濾波器,只有中心點的值是1,鄰域點的權值都是0。
相當於未對圖片進行變化

這裡寫圖片描述

例項1 均值模糊

這裡寫圖片描述

import cv2
import numpy as np

img =cv2.imread("pp1.jpg")

fil = np.array([[ 1/9,1/9, 1/9],
                [ 1/9, 1/9, 1/9],
                [ 1/9, 1/9, 1/9]])

res = cv2.filter2D(img,-1,fil)

cv2.imshow('win',res)
key_pressed=cv2.waitKey(0)

例項2 影象銳化

這裡寫圖片描述

import cv2
import numpy as np

img =cv2.imread("pp1.jpg")

fil = np.array([[ -1,-1, -1],
                [ -1, 9, -1],
                [  -1, 1, -1]])

res = cv2.filter2D(img,-1,fil)

cv2.imshow('win',res)
key_pressed=cv2.waitKey(0)

例項3 邊緣檢測

這裡寫圖片描述

其他效果

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

二 數學形態學(Mathematical morphology)

是一門建立在格論和拓撲學基礎之上的影象分析學科,是數學形態學影象處理的基本理論。其基本的運算包括:二值腐蝕和膨脹、二值開閉運算、骨架抽取、極限腐蝕、擊中擊不中變換、形態學梯度、Top-hat變換、顆粒分析、流域變換、灰值腐蝕和膨脹、灰值開閉運算、灰值形態學梯度等。

1 腐蝕 (erode)

先確定一個kernel
例如確定好核的尺寸為3*3 .
在opencv中核又被稱之為結構元素。
用結構元素與其覆蓋的二值影象做 (and)操作 ,如果都為1,結果影象的該畫素為1。否則為0。
也就是說, 如果一個點周邊所有點與其本身, 只要這裡面有一個0, 它就會被視作為0.
這裡寫圖片描述
核取的越大, 腐蝕效果越強.

kernel = np.ones((5,5), np.uint8) #新建一個核
erorsion_img = cv2.erode(img, kernel, iterations=1) #將核傳入erode函式

iterations為迭代次數
下圖分別為 原圖 、 1次迭代 、 2次迭代
這裡寫圖片描述

import cv2
import numpy as np
img = cv2.imread("d1.png", flags=cv2.IMREAD_GRAYSCALE)# 讀入灰度圖
#print(img)
kernel = np.ones((5,5), np.uint8)
erorsion_img = cv2.erode(img, kernel, iterations=1)
cv2.imshow('win',erorsion_img )
key_pressed=cv2.waitKey(0)

2 膨脹 (dilate)

假如使用的是3*3 的核(結構元素).
用核與其覆蓋的二值影象做or操作
如果周邊與其自身任意一個點為1,結果影象的該畫素為1, 否則為0
這裡寫圖片描述

kernel = np.ones((5,5), np.uint8) #新建一個核
dilation_img = cv2.dilate(img, kernel, iterations=1) #將核傳入dilate函式

下圖分別為 原圖 、 1次迭代 、 2次迭代
這裡寫圖片描述

3 開運算 (opening )

開運算(opening) 等於對影象先進行腐蝕(erode) 然後進行膨脹(dilate).
通常用於去除小粒噪聲

opening_img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

這裡寫圖片描述

import cv2
import numpy as np
img = cv2.imread("dd.png", flags=cv2.IMREAD_GRAYSCALE)# 讀入灰度圖
kernel = np.ones((5,5), np.uint8)
opening_img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=1)
cv2.imshow('win',opening_img )
key_pressed=cv2.waitKey(0)

4 閉運算 (closing )

閉運算(opening) 等於對影象先進行膨脹(dilate)然後進行腐蝕(erode) .
通常用於消除內部細小空洞的部分

closing_img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel,iterations=1)

這裡寫圖片描述

import cv2
import numpy as np
img = cv2.imread("p.png", flags=cv2.IMREAD_GRAYSCALE)# 讀入灰度圖
kernel = np.ones((5,5), np.uint8)
closing_img = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel,iterations=1)
cv2.imshow('win',closing_img)
key_pressed=cv2.waitKey(0)

5 數學形態學梯度 (gradient)

數學形態學梯度 = 影象膨脹 - 影象腐蝕
獲取到影象的邊緣.

 gradient_img = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

這裡寫圖片描述
用二進位制邏輯運算也可以得到 gradient :

erode = cv2.erode(img, kernel)
dilate = cv2.dilate(img,kernel)
gradient = cv2.bitwise_xor(dilate, erode)

6 頂帽運算(Top Hat)

頂帽運算為原影象與它的開運算值之差,
因為開運算帶來的結果是放大了裂縫或者區域性低亮度的區域,因此得到的圖突出了比原圖輪廓周圍的區域更明亮的區域,且這一操作和選擇的核的大小相關。
頂帽運算往往用來分離比鄰近點亮一些的斑塊。

7 黑帽運算(black-tophat)

黑帽運算為原影象與它的閉運算值之差,
黑帽運算後的效果圖突出了比原圖輪廓周圍的區域更暗的區域,且這一操作和選擇的核的大小相關。
黑帽運算用來分離比鄰近點暗一些的斑塊。