概述
OpenCV在使用卷積進(jìn)行圖像處理過(guò)程種,如何處理邊緣像素與錨定輸出兩個(gè)技術(shù)細(xì)節(jié)一直是很多人求而不得的疑惑。其實(shí)OpenCV在做卷積濾波時(shí)會(huì)對(duì)圖像進(jìn)行邊界填充,實(shí)現(xiàn)對(duì)邊緣像素的卷積計(jì)算的支持,不同填充方式與不同錨定點(diǎn)會(huì)得到圖像卷積輸出不同的結(jié)果。
邊界填充
我們首先來(lái)看一下OpenCV種支持標(biāo)準(zhǔn)卷積邊緣填充做法,OpenCV支持的有如下幾種卷積邊緣填充算法:
常量邊界
BORDER_CONSTANT
iiiiii|abcdefgh|iiiiiii
邊界復(fù)制
BORDER_REPLICATE
aaaaaa|abcdefgh|hhhhhhh
邊界反射
BORDER_REFLECT
fedcba|abcdefgh|hgfedcb
邊界換行
BORDER_WRAP
cdefgh|abcdefgh|abcdefg
邊界反射101
BORDER_REFLECT_101
gfedcb|abcdefgh|gfedcba
邊界透明-很不幸運(yùn)的是OpenCV4已經(jīng)不支持啦!
BORDER_TRANSPARENT
uvwxyz|abcdefgh|ijklmno
默認(rèn)填充方式
OpenCV中 filter2D, blur, GaussianBlur等卷積操作默認(rèn)支持為BORDER_DEFAULT(BORDER_REFLECT_101)
各種不同方式對(duì)邊緣的填充效果如下:
上圖背景為紅色,填充上下左右四個(gè)像素大小邊緣!右下角為原圖,左上角圖像為常量邊緣填充效果(i=0黑色)。
相關(guān)代碼實(shí)現(xiàn)如下:
image=cv.imread("D:/images/qxx.png"); ih,iw=image.shape[:2] border=4 #邊界填充 b1=cv.copyMakeBorder(image,border,border,border,border,cv.BORDER_CONSTANT) b2=cv.copyMakeBorder(image,border,border,border,border,cv.BORDER_REPLICATE) b3=cv.copyMakeBorder(image,border,border,border,border,cv.BORDER_REFLECT) b4=cv.copyMakeBorder(image,border,border,border,border,cv.BORDER_WRAP) b5=cv.copyMakeBorder(image,border,border,border,border,cv.BORDER_REFLECT_101) #邊界填充類(lèi)型說(shuō)明 cv.putText(image,"input",(20,20),cv.FONT_HERSHEY_PLAIN,1.0,(255,0,0)) cv.putText(b1,"BORDER_CONSTANT",(20,20),cv.FONT_HERSHEY_PLAIN,1.0,(255,0,0)) cv.putText(b2,"BORDER_REPLICATE",(20,20),cv.FONT_HERSHEY_PLAIN,1.0,(255,0,0)) cv.putText(b3,"BORDER_REFLECT",(20,20),cv.FONT_HERSHEY_PLAIN,1.0,(255,0,0)) cv.putText(b4,"BORDER_WRAP",(20,20),cv.FONT_HERSHEY_PLAIN,1.0,(255,0,0)) cv.putText(b5,"BORDER_REFLECT_101",(20,20),cv.FONT_HERSHEY_PLAIN,1.0,(255,0,0)) #拼接結(jié)果輸出 h=b1.shape[0]*2+8 w=b1.shape[1]*3+16 bh,bw=b1.shape[:2] result=np.zeros([h,w,3],dtype=np.uint8) result[:,:,:]=(0,0,255) result[0:bh,0:bw,:]=b1; result[0:bh,bw+8:bw+bw+8,:]=b2; result[0:bh,bw+bw+16:bw+bw+bw+16,:]=b3; result[bh+8:bh+bh+8,0:bw,:]=b4; result[bh+8:bh+bh+8,bw+8:bw+bw+8,:]=b5; result[bh+12:bh+12+ih,bw+bw+20:bw+bw+20+iw,:]=image; #顯示 cv.imshow("result",result) cv.imwrite("D:/border_result.png",result) cv.waitKey(0) cv.destroyAllWindows()
錨定位置
在進(jìn)行卷積處理的時(shí)候,卷積mask與對(duì)應(yīng)的像素塊點(diǎn)乘得到輸出,把輸出結(jié)果賦值給哪個(gè)像素點(diǎn)是由錨定參數(shù)anchor決定,以自定義濾波函數(shù)filter2D為例說(shuō)明
voidcv::filter2D( InputArraysrc, OutputArraydst, intddepth, InputArraykernel, Pointanchor=Point(-1,-1), doubledelta=0, intborderType=BORDER_DEFAULT ) 其中 kernel - 表示輸入的自定義卷積核大小 anchor - 表示錨定點(diǎn)位置,默認(rèn)情況Point(-1,-1)表示是卷積核的中心位置 borderType - 表示邊緣填充的像素大小,ksize/2其中ksize表示卷積核大小
上述函數(shù)在卷積核為奇數(shù)的時(shí)候,卷積核的中心位置很容易確定,比如3x3的卷積核大小,中心位置為Point(1,1),5x5的卷積核大小中心位置為Point(2,2)
但是當(dāng)卷積核大小為偶數(shù)的時(shí)候,很多人都搞不清楚中心位置是如何確定的,其實(shí)這個(gè)時(shí)候中心也為(ksize/2), 對(duì)2x2的卷積核,中心位置為Point(1,1),4x4的卷積核中心位置為Point(2,2)。
錨定位置對(duì)卷積結(jié)果的影響
以2x2與4x4的卷積核為與3x3與5x5的像素?cái)?shù)據(jù)為例
情況一
2x2卷積核對(duì)3x3的像素塊
當(dāng)錨定點(diǎn)為默認(rèn)(1,1)/(-1,-1)時(shí)候:
當(dāng)錨定點(diǎn)設(shè)置為(0,0)時(shí):
可以看到二者的輸出結(jié)果全然不同,原因在于當(dāng)錨定點(diǎn)不同的時(shí)候,卷積mask的開(kāi)始位置也會(huì)不不同,圖示如下:
情況二:
4x4卷積核對(duì)5x5的像素塊:
使用BORDER_DEFAULT填充方式,填充之后為:
不同錨定位置的均值卷積輸出結(jié)果:
三個(gè)不同錨定點(diǎn)對(duì)應(yīng)卷積mask的起始位置與錨定像素輸出:
代碼演示如下:
src=np.zeros([3,3],dtype=np.uint8) src[0,0]=16 src[1,1]=8 src[2,2]=4 print(" inputimage: ",src) k1=[[1,0],[0,-1]] print(" kernel: ",k1) result=cv.copyMakeBorder(src,1,1,1,1,cv.BORDER_DEFAULT) print(" BORDER_DEFAULT邊界填充: ",result) dst=cv.filter2D(src,cv.CV_32F,np.asarray(k1),None,anchor=(0,0),borderType=cv.BORDER_DEFAULT) print(" filter2D: ",dst) print(" ") src=np.zeros([5,5],dtype=np.uint8) src[0,0]=32 src[1,1]=16 src[2,2]=8 src[3,3]=4 src[4,4]=2 print(" input: ",src) k2=np.ones([4,4],dtype=np.int32) print(" kernel: ",k2) result=cv.copyMakeBorder(src,3,3,3,3,cv.BORDER_DEFAULT) print(" 邊界填充: ",result) dst=cv.filter2D(src,cv.CV_32F,np.asarray(k2),None,anchor=(-1,-1),borderType=cv.BORDER_DEFAULT) print(" filter2DResult: ",dst)
原文標(biāo)題:詳解OpenCV卷積濾波之邊緣處理與錨定輸出
文章出處:【微信公眾號(hào):OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4331瀏覽量
62622 -
代碼
+關(guān)注
關(guān)注
30文章
4788瀏覽量
68616 -
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41352
原文標(biāo)題:詳解OpenCV卷積濾波之邊緣處理與錨定輸出
文章出處:【微信號(hào):CVSCHOOL,微信公眾號(hào):OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論