圖像處理學習筆記(二)
- 4 OpenCV圖像處理:
-
- 4.2 形态學操作:
-
- 4.2.1 連通性:
- 4.2.1 腐蝕和膨脹:
- 4.2.2 開閉運算:
- 4.2.3 禮帽和黑帽:
- 4.2.4 形态學操作總結:
- 4.3 圖像平滑:
-
- 4.3.1 圖像噪聲:
- 4.3.2 均值濾波:
- 4.3.3 高斯濾波:
- 4.3.4 中值濾波:
- 4.3.5 圖像平滑總結:
- 4.4 直方圖:
-
- 4.4.1 灰階直方圖:
- 4.4.2 直方圖的計算和繪制:
- 4.4.3 掩膜的應用:
- 4.4.4 直方圖均衡化:
- 4.4.5 自适應直方圖均衡化:
- 4.4.6 直方圖總結:
- 4.5 邊緣檢測:
-
- 4.5.1 sobel和Scharr算子:
- 4.5.2 Laplacian算子:
- 4.5.3 Canny邊緣檢測:
- 4.5.4 邊緣檢測總結:
- 4.6 模闆比對和霍夫變換:
-
- 4.6.1 模闆比對:
- 4.6.2 霍夫變換原理:
- 4.6.3 霍夫線檢測:
- 4.6.4 霍夫圓檢測(了解):
- 4.6.5 總結:
- 4.7 圖像特征提取與描述:
-
- 4.7.1 角點特征:
- 4.7.2 Harris和Shi-Tomas算法:
-
- 4.7.2.1 Harris角點檢測
- 4.7.2.2 Shi-Tomasi角點檢測
- 4.7.3 總結
- 4.8 SIFT/SURF算法:
-
- 4.8.1 SIFT:
-
- 4.8.1.1 SIFT基本流程:
哔哩哔哩:《黑馬程式員人工智能教程_10小時學會圖像處理OpenCV入門教程》
4 OpenCV圖像處理:
4.2 形态學操作:
形态學轉換是基于圖像形狀的一些簡單操作,通常在二進制圖像上進行,腐蝕和膨脹是兩個基本的形态學運算符,它的變體形式如開運算、閉運算、禮帽黑帽等。
4.2.1 連通性:
圖像中,最小的機關是像素,每個像素周圍有8個鄰接像素,常見的鄰接關系有3種:4鄰接、8鄰接和D鄰接。
4.2.1 腐蝕和膨脹:
- 腐蝕和膨脹是針對白色部分(高亮部分)而言的
- 膨脹是使得圖中高亮部分擴張,效果圖擁有比原圖更大的高亮區域;腐蝕是原圖中的高亮區域被蠶食,效果圖擁有比原圖更小的高亮區域。
- 膨脹是求局部最大值的操作,腐蝕是求局部最小值的操作。
1. 腐蝕
腐蝕的作用是消除物體邊界點,使得目标縮小,可以消除小于結構元素的噪聲點。
2. 膨脹
膨脹的作用是将與物體接觸的所有背景點合并到物體中,使得目标增大可填目标中的孔洞。
# 使用一個5*5的卷積核實作腐蝕和膨脹的運算
# 1、讀取圖像
img = cv.imread('1.jpg')
# 2、建立卷積核
kernel = np.ones((5,5),np.uint8)
# 3、圖像腐蝕和膨脹
erosion = cv.erode(img,kernel)
dilate = cv.dilate(img,kernel)
# 3、圖像顯示
fig,axes = plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title('Start')
axes[1].imshow(erosion[:,:,::-1])
axes[1].set_title('erosion')
axes[2].imshow(dilate[:,:,::-1])
axes[2].set_title('dilate')
plt.show()
效果圖:
4.2.2 開閉運算:
- 開運算是先腐蝕後膨脹
- 作用:分離物體,消除小區域。
- 特點:消除噪點,去除小的幹擾塊,而不影響原來的圖像。
- 閉運算是先膨脹後腐蝕
- 作用:消除“閉合”物體裡面的孔洞。
- 特點:可以填充閉合區域。
# 使用一個10*10的卷積核實作開閉運算實作
# 1、讀取圖像
img = cv.imread('1.jpg')
# 2、建立卷積核
kernel = np.ones((10,10),np.uint8)
# 3、圖像的開閉運算
cvOpen = cv.morphologyEx(img,cv.MORPH_OPEN,kernel)
cvColse = cv.morphologyEx(img,cv.MORPH_CLOSE,kernel)
# 4、圖像顯示
fig,axes = plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title('Start')
axes[1].imshow(cvOpen[:,:,::-1])
axes[1].set_title('cvOpen')
axes[2].imshow(cvColse[:,:,::-1])
axes[2].set_title('cvColse')
plt.show()
效果圖:
4.2.3 禮帽和黑帽:
# 使用一個10*10的卷積核實作禮帽黑帽
# 1、讀取圖像
img = cv.imread('1.jpg')
# 2、建立卷積核
kernel = np.ones((10,10),np.uint8)
# 3、圖像的禮帽黑帽
topHat = cv.morphologyEx(img,cv.MORPH_TOPHAT,kernel)
blackHat = cv.morphologyEx(img,cv.MORPH_BLACKHAT,kernel)
# 4、圖像顯示
fig,axes = plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title('Start')
axes[1].imshow(topHat[:,:,::-1])
axes[1].set_title('topHat')
axes[2].imshow(blackHat[:,:,::-1])
axes[2].set_title('blackHat')
plt.show()
效果圖如下:
4.2.4 形态學操作總結:
1、連通性:
鄰接關系:4鄰接、8鄰接和D鄰接
4連通、8連通和m連通
2、形态學操作
- 腐蝕和膨脹
膨脹是求局部最大值的操作
腐蝕是求局部最小值的操作
- 開閉運算
開:先腐蝕後膨脹
閉:先膨脹後腐蝕
- 禮帽和黑帽
禮帽:原圖像-開運算
黑帽:閉運算-原圖像
4.3 圖像平滑:
4.3.1 圖像噪聲:
- 椒鹽噪聲(脈沖噪聲):
- 高斯噪聲(正态噪聲):
4.3.2 均值濾波:
- 圖像平滑從信号處理的角度就是去除其中的高頻資訊,保留低頻資訊,是以可以對圖像進行低通濾波。
- 根據濾波器的不同,可分為均值濾波、高斯濾波、中值濾波和雙邊濾波
優點:算法簡單,計算速度快;
缺點:去噪的同時去除了很多細節部分,将圖像變得模糊。
下圖引自:圖像處理:中值濾波&均值濾波
均值濾波原理:就是将上圖中每個n×n的子方格的中心換為這n×n個格像素的平均值。
例如:n=3,左上角的3*3的子方格其中心現在為2,變為(1+2+1+1+2+2+5+7+6)/9 = 3
import cv2 as cv
import matplotlib.pyplot as plt
# 1、讀取圖檔
img = cv.imread('1.jpg')
# 2、均值濾波
blur = cv.blur(img,(5,5))
# 3、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1])
plt.subplot(122),plt.imshow(blur[:,:,::-1])
plt.show()
4.3.3 高斯濾波:
均值濾波是預設鄰接矩陣的權重全部為1,而高斯濾波是按照權重來計算的。
高斯濾波流程:
- 确定權重矩陣
- 計算高斯模糊
import cv2 as cv
import matplotlib.pyplot as plt
# 1、讀取圖檔
img = cv.imread('1.jpg')
# 2、高斯濾波
blur = cv.GaussianBlur(img,(3,3),1)
# 3、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1])
plt.subplot(122),plt.imshow(blur[:,:,::-1])
plt.show()
4.3.4 中值濾波:
- 中值濾波是一種典型的非線性濾波技術,基本思想是用像素點鄰域灰階值的中值來替代該像素點的灰階值。
- 中值濾波對椒鹽噪聲來說尤其有用,因為它不依賴于鄰域内那些與典型值差别很大的值。
# 1、讀取圖檔
img = cv.imread('1.jpg')
# 2、高斯濾波
blur = cv.medianBlur(img,5)
# 3、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1])
plt.subplot(122),plt.imshow(blur[:,:,::-1])
plt.show()
4.3.5 圖像平滑總結:
- 圖像噪聲:
椒鹽噪聲:圖像中随機出現的白點或者黑點
高斯噪聲:噪聲點機率密度分布是正态分布
- 圖像平滑
均值濾波:算法簡單,計算速度快,在去噪的同時去掉了很多細節部分,将圖像變得模糊
API:cv.blur()
高斯濾波:去除高斯噪聲
API:cv.GaussianBlur()
中值濾波:去除椒鹽噪聲
cv.medianBlur()
4.4 直方圖:
4.4.1 灰階直方圖:
- 原理
直方圖的術語和細節:
- dims:需要統計的特征數目。上例中,僅統計灰階值,則dims=1
- bins:每個特征空間子區段的數目。上例中,bins=16
- range:要統計特征的取值範圍。上例中,range=[0,255]
直方圖的意義
- 直方圖是圖像中像素強度分布的圖形表達式
- 統計每一個強度所具有的像素個數
- 不同圖像的直方圖可能是相同的
4.4.2 直方圖的計算和繪制:
import cv2 as cv
import matplotlib.pyplot as plt
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
# 2、統計灰階圖
histr = cv.calcHist([img],[0],None,[256],[0,256])
# 3、繪制灰階圖
plt.figure(figsize=(10,6),dpi=100)
plt.plot(histr)
plt.show()
4.4.3 掩膜的應用:
在數字圖像進行中,常用二維矩陣數組進行掩膜。掩膜是由0和1組成一個二進制圖像,利用該掩膜圖像對要處理的圖像進行掩膜,其中1值的區域被處理,0值區域被屏蔽,不會處理。
掩膜的主要用途
- 提取感興趣的區域:用預先制作的感興趣區掩膜與待處理圖像進行“與”操作,得到感興趣區圖像,感興趣區内圖像保持不變,而區外圖像值都為0
- 屏蔽作用:用掩膜對圖像上某些區域做屏蔽,使其不參加處理或不參加處理參數的運算,或者僅對屏蔽區域作處理或統計
- 結構特征提取:用相似性變量或圖像比對方法檢測和提取圖像中與掩膜相似的結構特征
- 特殊形狀圖像制作
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
# 2、建立蒙版
mask = np.zeros(img.shape[:2],np.uint8)
mask[0:600,0:600] = 255
# 3、掩膜
masked_img = cv.bitwise_and(img,img,mask=mask)
# 4、統計掩膜後圖像的灰階圖
mask_histr = cv.calcHist([img],[0],mask,[256],[1,256])
# 3、圖像展示
fig,axes = plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img,cmap=plt.cm.gray)
axes[0,1].imshow(mask,cmap=plt.cm.gray)
axes[1,0].imshow(masked_img,cmap=plt.cm.gray)
axes[1,1].plot(mask_histr)
plt.show()
4.4.4 直方圖均衡化:
原理與應用
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
dst = cv.equalizeHist(img)
fig,axes = plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[1].imshow(dst,cmap=plt.cm.gray)
plt.show()
感覺是增加了對比度
4.4.5 自适應直方圖均衡化:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
# 2、建立一個自适應均衡化的對象,并應用于圖像
clahe = cv.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
cl1 = clahe.apply(img)
# 3、圖像展示
fig,axes = plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[1].imshow(cl1,cmap=plt.cm.gray)
plt.show()
4.4.6 直方圖總結:
4.5 邊緣檢測:
學習目标:
- 了解Sobel算子,Scharr算子和拉普拉斯算子
- 掌握canny邊緣檢測的原理及應用
原理
基于搜尋(Sobel和Scharr): 基于零穿越(Laplacian):
4.5.1 sobel和Scharr算子:
Sobel
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
# 2、計算Sobel卷積結果
x = cv.Sobel(img,cv.CV_16S,1,0)
y = cv.Sobel(img,cv.CV_16S,0,1)
# 3、将資料進行轉換
Scale_absX = cv.convertScaleAbs(x)
Scale_absY = cv.convertScaleAbs(y)
# 4、結果合成
result = cv.addWeighted(Scale_absX,0.5,Scale_absY,0.5,0)
# 5、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('img')
plt.subplot(122),plt.imshow(result,cmap=plt.cm.gray),plt.title('Sobel img')
plt.show()
Scharr
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
# # 2、計算Sobel卷積結果
# x = cv.Sobel(img,cv.CV_16S,1,0)
# y = cv.Sobel(img,cv.CV_16S,0,1)
# 2、計算Scharr卷積結果
x = cv.Sobel(img,cv.CV_16S,1,0,ksize=-1)
y = cv.Sobel(img,cv.CV_16S,0,1,ksize=-1)
# 3、将資料進行轉換
Scale_absX = cv.convertScaleAbs(x)
Scale_absY = cv.convertScaleAbs(y)
# 4、結果合成
result = cv.addWeighted(Scale_absX,0.5,Scale_absY,0.5,0)
# 5、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('img')
# plt.subplot(122),plt.imshow(result,cmap=plt.cm.gray),plt.title('Sobel img')
plt.subplot(122),plt.imshow(result,cmap=plt.cm.gray),plt.title('Scharr img')
plt.show()
4.5.2 Laplacian算子:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
# 2、計算Laplacian卷積結果
result = cv.Laplacian(img,cv.CV_16S)
Scale_abs = cv.convertScaleAbs(result)
# 3、将資料進行轉換
# 5、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('img')
plt.subplot(122),plt.imshow(Scale_abs,cmap=plt.cm.gray),plt.title('Laplacian img')
plt.show()
4.5.3 Canny邊緣檢測:
原理:四個步驟
- 噪聲去除
由于邊緣檢測很容易受到噪聲點影響,是以先用5*5高斯濾波器去除噪聲。
- 計算圖像梯度
- 非極大值抑制
- 滞後門檻值
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、以灰階圖的方式讀入
img = cv.imread('1.jpg',0)
# 2、Canny檢測
lowThreshold = 0
maxThreshold = 100
canny = cv.Canny(img,lowThreshold,maxThreshold)
# 3、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('img')
plt.subplot(122),plt.imshow(canny,cmap=plt.cm.gray),plt.title('Laplacian img')
plt.show()
4.5.4 邊緣檢測總結:
4.6 模闆比對和霍夫變換:
4.6.1 模闆比對:
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、圖像和模闆讀取
img = cv.imread('1.jpg')
template = cv.imread('template.png')
h,w,l = template.shape
# 2.1 模闆比對
res = cv.matchTemplate(img,template,cv.TM_CCORR)
# 2.2 傳回圖像中最比對的位置,确定左上角的坐标,并将比對位置繪制在圖像上
min_val,max_val,min_loc,max_loc = cv.minMaxLoc(res)
# 使用平方差時最小值為最佳比對位置
top_left = max_loc
bottom_right = (top_left[0] + w,top_left[1] + h)
cv.rectangle(img,top_left,bottom_right,(0,255,0),2)
# 圖像顯示
plt.imshow(img[:,:,::-1])
plt.title('Match Result')
plt.show()
模闆: 效果圖:(比對并沒有很準,新手還需要鍛煉)
4.6.2 霍夫變換原理:
實作流程:
4.6.3 霍夫線檢測:
首先進行邊緣檢測,獲得一些點,然後周遊點,做霍夫線檢測,最後得到直線。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1、圖像和模闆讀取
img = cv.imread('1.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150)
# 2.霍夫直線變換
lines = cv.HoughLines(edges,0.8,np.pi/180,150)
# 3、将檢測的線繪制在圖像上(注意是極坐标)
for line in lines:
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 *(-b))
y1 = int(y0 + 1000 *(a))
x2 = int(x0 - 1000 * (-b))
y2 = int(y0 - 1000 * (a))
cv.line(img,(x1,y1),(x2,y2),(0,255,0))
# 4、圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1])
plt.show()
這個圖簡直了
4.6.4 霍夫圓檢測(了解):
沒看,後續再加吧。感覺這個霍夫檢測很沒勁。
4.6.5 總結:
4.7 圖像特征提取與描述:
4.7.1 角點特征:
4.7.2 Harris和Shi-Tomas算法:
4.7.2.1 Harris角點檢測
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('1.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 輸入圖像必須是float32
gray = np.float32(gray)
# 最後一個參數在0.04到0.05之間
dst = cv.cornerHarris(gray,2,3,0.04)
# 設定門檻值,将角點繪制出來,門檻值根據圖像進行選擇
img[dst>0.001*dst.max()] = [0,0,255]
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1])
plt.show()
4.7.2.2 Shi-Tomasi角點檢測
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('1.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 角點檢測
corners = cv.goodFeaturesToTrack(gray,1000,0.01,10)
# 繪制角點
for corner in corners:
x,y = corner.ravel()
cv.circle(img,(int(x),int(y)),2,(0,0,255),-1)
# x,y 一定要轉成整型
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1])
plt.show()
4.7.3 總結
4.8 SIFT/SURF算法:
4.8.1 SIFT:
- 之前的兩個角點檢測的方法具有旋轉不變性,但是沒有尺度不變性。
- 比如說:之前的小圖可以檢測小的角點,但是當角點被放大後,之前的小圖就很難找出角點了。