openCV专栏(五):形态学操作+梯度算子
OPENCV基礎(chǔ)操作
提示:本專欄所用版本僅供參考,其他版本也可
| python | Python 3.9.3 | 
| opencv | 4.5.5 | 
| matplotlib | 3.4.3 | 
| numpy | 1.19.5 | 
| QQ學(xué)習(xí)群 | 點(diǎn)擊加群:928357277 | 
提示:本章節(jié)將處理如下圖片,可提前下載使用,保存為.bmp格式
學(xué)習(xí)目錄
- (一)形態(tài)學(xué)操作
- 內(nèi)容
- 腐蝕
- 膨脹
- 通用形態(tài)學(xué)函數(shù)
- 通用形態(tài)學(xué)函數(shù)相關(guān)運(yùn)算
- 代碼及其運(yùn)行結(jié)果
 
- (二)圖像梯度
- soble算子
- 內(nèi)容介紹
- 使用soble獲取完整的水平方向邊緣信息
- 使用soble獲取完整的水平,垂直兩個(gè)方向邊緣信息
 
- Scharr算子
- 使用Scharr獲取完整的水平,垂直兩個(gè)方向邊緣信息
 
- Laplacian算子
- 內(nèi)容介紹
- 使用Laplacian獲取完整的水平,垂直兩個(gè)方向邊緣信息
 
 
(一)形態(tài)學(xué)操作
內(nèi)容
? ? 介紹: 形態(tài)學(xué),全名數(shù)學(xué)形態(tài)學(xué) 
? ? 主要功能: 從圖像內(nèi)提取分量信息,該分量信息對于表達(dá)和描繪圖像的形狀具有重要的意義,如文字識別,醫(yī)學(xué)圖像處理,圖像壓縮編碼,視覺檢測等 
? ? 基本操作:  
? ? 腐蝕,膨脹,開運(yùn)算,閉運(yùn)算,禮帽,黑帽,形態(tài)學(xué)梯度運(yùn)算
腐蝕
? ? 功能: 消除圖像邊界點(diǎn),使圖像沿著邊界向內(nèi)收縮;去除小于指定結(jié)構(gòu)體元素的部分 
? ? 原理:  用一個(gè)結(jié)構(gòu)元【也被成為核】來逐個(gè)像素地掃描圖像,并根據(jù)結(jié)構(gòu)元和圖像的關(guān)系確定腐蝕結(jié)果 
? ? 注意:  
? ? 只有核處于前景中才會被腐蝕算
函數(shù):
 dst = cv2.erode(src,kernel[,anchor[,iterations[,borderType[,borderValue]]]])
 
 參數(shù):
 src:[原始圖像]
 kernel: [腐蝕操作的結(jié)構(gòu)類型]
 anchor: [錨點(diǎn)的位置,默認(rèn)(-1,-1:只進(jìn)行一次腐蝕操作)]
 borderType: [邊界樣式,默認(rèn)BORDER_CONSTANT]
 borderValue: [邊界值—————————————— ??C++中采用morphologyDefaultBorderValue()來返回magic邊界值]
膨脹
? ? 功能: 對圖像的邊界進(jìn)行擴(kuò)張 
? ? 原理:  用一個(gè)結(jié)構(gòu)元【也被成為核】來逐個(gè)像素地掃描圖像,并根據(jù)結(jié)構(gòu)元和圖像的關(guān)系確定腐蝕結(jié)果 
? ? 注意:  
? ? 處于前景中的結(jié)構(gòu)元的任意一點(diǎn)會被處理為前景色
函數(shù):
 dst = cv2.dilate(src,kernel[,anchor[,iterations[,borderType[,borderValue]]]])
 
參數(shù):
>
 src: 原始圖像,圖像深度必須為【CV_8U,CV_16U,CV_16S,CV_32F,CV_64F】
 kernel: 膨脹操作的結(jié)構(gòu)類型
 anchor: 錨點(diǎn)的位置,默認(rèn)(-1,-1:只進(jìn)行一次腐蝕操作)
 borderType: 邊界樣式,默認(rèn)BORDER_CONSTANT
 borderValue: [邊界值—————————————— ??C++中采用morphologyDefaultBorderValue()來返回magic邊界值]
通用形態(tài)學(xué)函數(shù)
? ? 原理 將腐蝕和膨脹操作進(jìn)行組合,組成不同形式的運(yùn)算
函數(shù): dst = cv2.morphologyEx(src,op,kernel[,anchor[,iterations[,borderType[,borderValue]]]]) 參數(shù): src:原始圖像,圖像深度必須為 CV_8U,CV_16U,CV_16S,CV_32F,CV_64F】 op: 操作類型【如:腐蝕,膨脹,先腐蝕后膨脹】 kernel:膨脹操作的結(jié)構(gòu)類型,可以通過getStructuringElement()生成 anchor:錨點(diǎn)的位置,默認(rèn)(-1,-1:只進(jìn)行一次腐蝕操作) borderType: 邊界樣式,默認(rèn)BORDER_CONSTANT borderValue: [邊界值:C++中采用morphologyDefaultBorderValue()來返回magic邊界值]通用形態(tài)學(xué)函數(shù)相關(guān)運(yùn)算
| 開運(yùn)算 | 原理:先腐蝕再膨脹 | cv2.MORPH_OPEN | 
| 閉運(yùn)算 | 原理:先膨脹再腐蝕 | cv2.MORPH_CLOSE | 
| 形態(tài)學(xué)梯度運(yùn)算 | 膨脹 - 腐蝕 | cv2.MOPRH_GRADIENT | 
| 禮帽運(yùn)算 | 原始圖像 - 開運(yùn)算 | cv2.MOPRH_TOPHAT | 
| 黑帽運(yùn)算 | 閉運(yùn)算 - 原始圖像 | cv2.MOPRH_BLACKHAT | 
代碼及其運(yùn)行結(jié)果
import matplotlib.pyplot as plt #導(dǎo)入模塊 import cv2 import numpy as np# 1:讀取圖片 filename = 'J.bmp'#保存圖片路徑 img = cv2.imread(filename,cv2.IMREAD_UNCHANGED)#加載A通道的方式讀取#2:生成核 kernel = np.ones((5,5),np.uint8) kerne2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))#3:腐蝕 erosion = cv2.erode(img,kernel,iterations =2) #4:膨脹 drosion = cv2.dilate(img,kerne2,iterations =4) #5:禮帽 brosion = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel) #6:形態(tài)學(xué)梯度 trosion = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel) #5:將結(jié)果存入自定義矩陣 C = np.ones((img.shape[0],img.shape[1],4,5),np.uint8) C[:,:,:,0] = img C[:,:,:,1] = erosion C[:,:,:,2] = drosion C[:,:,:,3] = brosion C[:,:,:,4] = trosion# 6:顯示 T = ("img","erosion","drosion","brosion","trosion") for i in range(5): plt.subplot(3,2,i+1)#將畫布分為兩行四列,當(dāng)前圖像顯示到第i+1個(gè)區(qū)塊plt.imshow(C[:,:,0,i],cmap='gray')#把圖像加載到plt畫布中plt.title(T[i])#設(shè)置當(dāng)前圖像標(biāo)題 plt.show()運(yùn)行結(jié)果:
(二)圖像梯度
 介紹:圖像梯度計(jì)算的是圖像變化的速度,一般情況下,計(jì)算的是圖像的邊緣信息
 
原理:嚴(yán)格來講,圖像梯度計(jì)算需要求導(dǎo)數(shù),但是圖像梯度一般通過計(jì)算像素值的差來得到梯度的近似值
 
基本內(nèi)容:sobel算子,Scharr算子,Laplacian算子
soble算子
內(nèi)容介紹
? ? 介紹: sobel算子是一種離散的微分算子,該算子結(jié)合了高斯平滑和微分求導(dǎo)運(yùn)算。 
? ? 原理:  利用了局部差尋找邊緣,計(jì)算所得的是一個(gè)梯度的近似值。 
? ? 注意:  
? ? 處于前景中的結(jié)構(gòu)元的任意一點(diǎn)會被處理為前景色
函數(shù):
 dst = cv2.sobel(src,ddpeth,dx,dy[,Ksize[,scale[,delta[,borderType]]]])
 
 <參數(shù)>
 【ddpeth】:輸出圖像深度,通常設(shè)置為CV_64F,可以避免信息丟失
 【dx,dy】: x,y方向上求導(dǎo)階數(shù),一般采取絕對值計(jì)算方式,
 一般數(shù)值為0,1,最大為2
 【 Ksize】:Sobel核的大小,當(dāng)為-1時(shí),使用Scharr算子進(jìn)行運(yùn)算
 【scale】:縮放因子,默認(rèn)1【沒有縮放】
 【delta】:加在目標(biāo)圖像上的值,默認(rèn)為0
 【 borderType】:邊界樣式
使用soble獲取完整的水平方向邊緣信息
import cv2 import numpy as np import matplotlib.pyplot as pltimg = cv2.imread('J.bmp',cv2.IMREAD_UNCHANGED)# 2:使用sobel算子 Sx = cv2.Sobel(img,cv2.CV_64F,1,0) Sx = cv2.convertScaleAbs(Sx)# 3:保存至當(dāng)前文件夾 cv2.imwrite('Sx.jpg',Sx)運(yùn)行結(jié)果:
 
使用soble獲取完整的水平,垂直兩個(gè)方向邊緣信息
img = cv2.imread('J.bmp',cv2.IMREAD_UNCHANGED) # 2:使用sobel算子 Sx = cv2.Sobel(img,cv2.CV_64F,1,0) Sx = cv2.convertScaleAbs(Sx)Sy = cv2.Sobel(img,cv2.CV_64F,0,1) Sy = cv2.convertScaleAbs(Sy)Sxy = cv2.addWeighted(Sx,0.5,Sy,0.5,0)# 3:保存至當(dāng)前文件夾 cv2.imwrite("Sxy.jpg",Sxy)運(yùn)行結(jié)果:
 
Scharr算子
? ? 介紹: 在使用3*3的sobel算子時(shí),可能計(jì)算結(jié)果不太精確。所以出現(xiàn)了精度更高的Scharr算子 
? ? 核:  [[-3,0,3],[-10,0,10],[-3,0,3]]
 ?? - ?? [[-3,-10,-3],[0,0,0],[3,10,3]] 
使用Scharr獲取完整的水平,垂直兩個(gè)方向邊緣信息
運(yùn)行程序:
import cv2 import numpy as np import matplotlib.pyplot as pltimg = cv2.imread('J.bmp',cv2.IMREAD_UNCHANGED)# 1:稍微處理下圖像 mask = img[:,:,:]>100 img[:,:,:] = 0 img[mask] = 255# 2:使用sobel算子 Sx = cv2.Scharr(img,cv2.CV_64F,1,0) Sx = cv2.convertScaleAbs(Sx)Sy = cv2.Scharr(img,cv2.CV_64F,0,1) Sy = cv2.convertScaleAbs(Sy)Scxy = cv2.addWeighted(Sx,0.5,Sy,0.5,0)# 3:保存至當(dāng)前文件夾 cv2.imwrite("Scxy.jpg",Scxy)運(yùn)行結(jié)果:
 
Laplacian算子
內(nèi)容介紹
? ? 介紹: 中文【拉普拉斯】算子是一種二階導(dǎo)數(shù)算子,其具有旋轉(zhuǎn)不變性,可以滿足不同方向的圖像邊緣銳化的要求 
? ? 核:  [[0,1,0],[1,-4,1],[0,1,0]] 
使用Laplacian獲取完整的水平,垂直兩個(gè)方向邊緣信息
運(yùn)行程序:
import cv2 import numpy as np import matplotlib.pyplot as pltimg = cv2.imread('J.bmp',cv2.IMREAD_UNCHANGED)# 1:稍微處理下圖像 mask = img[:,:,:]>100 img[:,:,:] = 0 img[mask] = 255# 2:使用sobel算子 Lx = cv2.Laplacian(img,cv2.CV_64F) Lx = cv2.convertScaleAbs(Lx)# 3:保存至當(dāng)前文件夾 cv2.imwrite("Lx.jpg",Lx)運(yùn)行結(jié)果:
 
總結(jié)
以上是生活随笔為你收集整理的openCV专栏(五):形态学操作+梯度算子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: PCBA测试是什么意思
- 下一篇: 端口镜像站群301蜘蛛强引+廉价域名泛站
