灰度图像--图像增强 Robert算子、Sobel算子
生活随笔
收集整理的這篇文章主要介紹了
灰度图像--图像增强 Robert算子、Sobel算子
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
灰度圖像--圖像增強(qiáng) Robert算子、Sobel算子
???????
開篇廢話 圖像梯度介紹 Robert算子 Sobel算子 代碼 結(jié)果 總結(jié)
? ? ? ? 繼續(xù)廢話,之前介紹了二階微分,和非銳化掩蔽,按照順序該說一階微分了,一階微分與二階微分一樣,是線性算子,線性算子的計(jì)算方法多半是生成模板,然后與圖像卷積,一階微分同樣,幾天簡單的介紹兩個(gè)一階微分算子,Robert算子和Sobel算子,這兩個(gè)算子應(yīng)該算是大名鼎鼎了,因?yàn)檫@兩個(gè)算子在后面的邊緣檢測中都是里程碑似的算法,在增強(qiáng)部分,他們也主要用在邊緣增強(qiáng),本文只簡要介紹下兩個(gè)算子的大概使用和增強(qiáng)效果,具體的數(shù)學(xué)原理推導(dǎo)和其他性質(zhì),將在圖像分割部分完整介紹。
? ? ? 首先介紹下梯度,梯度并非是一個(gè)數(shù)值,梯度嚴(yán)格意義上是一個(gè)向量,這個(gè)向量指向當(dāng)前位置變化最快的方向,可以這么理解,當(dāng)你站在一個(gè)山上,你有360°的方向可以選擇,哪個(gè)方向下降速度最快(最陡峭),便是梯度方向,梯度的長度,表示為向量的長度,表示最大的變化速率。 ? ? ? ?梯度的數(shù)學(xué)表達(dá):
? ? ? ?其中表示微分算子。梯度在三維坐標(biāo)中表示為:
? ? ? ?同樣在二維中只取前兩項(xiàng),也就是由x方向的偏微分和y方向的偏微分組成。對于圖像f中點(diǎn)(x,y)處的梯度,定義為:
與上面所述保持一致,圖像梯度方向給出圖像變化最快方向,當(dāng)前點(diǎn)的梯度長度為:
次長度計(jì)算中有平方和開平方,所以將不再是現(xiàn)行操作。 為了簡單計(jì)算,將上面求距離簡化成:
然而上面式子最大的問題在于不具有旋轉(zhuǎn)不變形,也就是不是各向同性的,具體原因是三角形三遍關(guān)系原理,因?yàn)樘荻确较蚝烷L度對于旋轉(zhuǎn)是不變的,所以,x軸和y軸發(fā)生旋轉(zhuǎn)的時(shí)候,直角三角形兩邊發(fā)生變化,但保持斜邊長度和方向不變,因此兩個(gè)直角邊的長度和必然發(fā)生改變,也就是上面的M值必然會改變,顧其不具有旋轉(zhuǎn)不變形。 ? ? ? ?為了表達(dá)方便先重新來定義下模板位置,如下圖 ? ? ? ? 其中z5表示模板中心。
? ? ? ?奇葩算子Robert,說它奇葩確實(shí)奇葩,因?yàn)椴恢繰obert哪來的勇氣或者推導(dǎo)過程,使用一個(gè)2x2的模板,而且是對角線做差,其差分為:
因?yàn)橄蛄繜o法在圖像中顯示,我們要計(jì)算梯度向量的長度:
簡化為絕對值方法:
這個(gè)就是Robert交叉算子。模板:
因?yàn)镽obert算子是2x2的模板,不是對稱的奇數(shù)模板,我們更喜歡3x3的模板,所以,要根據(jù)上面的Robert算子改造出來一個(gè)3x3模板,提出了下面這個(gè)計(jì)算方法:
? ? ? ?怎么來的?說實(shí)話我一開始也不知道,只是說根據(jù)上面Robert算子,搞出來一個(gè)等價(jià)的,其數(shù)字模板為:
? ? ? ?并且其下降速率(梯度的長度)計(jì)算公式:
? ? ? ?所有上面的疑惑就是這個(gè)公式: ? ? ? ?到底是怎么來的,為什么中間會有2,以及為什么是隔行相減,下面的過程是我自己發(fā)明的,沒有數(shù)學(xué)依據(jù),只是自己的猜測,根據(jù)Robert算子的兩個(gè)式子,橫向劃過3x3的所有位置,然后相加,就得到了Sobel算子:
這個(gè)過程就用Robert產(chǎn)生了Sobel,同樣的縱向移動(dòng)就會產(chǎn)生x軸方向的算子。Sobel算子原理的論文不多,但都說這是個(gè)很好的邊緣檢測算子。
Robert: [cpp] view plaincopyprint?void?Robert(double?*src,double?*dst,int?width,int?height){?? ????double?RobertMask_x[9]={0,0,0,0,-1,0,0,0,1};?? ????double?RobertMask_y[9]={0,0,0,0,0,-1,0,1,0};?? ????double?*dst_x=(double?*)malloc(sizeof(double)*width*height);?? ????double?*dst_y=(double?*)malloc(sizeof(double)*width*height);?? ????RealConvolution(src,?dst_x,?RobertMask_x,?width,?height,?ROBERT_MASK_SIZE,ROBERT_MASK_SIZE);?? ????RealConvolution(src,?dst_y,?RobertMask_y,?width,?height,?ROBERT_MASK_SIZE,ROBERT_MASK_SIZE);?? ????for(int?j=0;j<height;j++)?? ????????for(int?i=0;i<width;i++){?? ????????????dst[j*width+i]=abs(dst_x[j*width+i])+abs(dst_y[j*width+i]);?? ?????????????? ????????}?? ????free(dst_x);?? ????free(dst_y);?? ?????? }?? ?? void?RobertSharpen(double?*src,double?*dst,int?width,int?height,double?c){?? ????Robert(src,dst,width,height);?? ????for(int?j=0;j<height;j++)?? ????????for(int?i=0;i<width;i++){?? ????????????dst[j*width+i]=src[j*width+i]+c*dst[j*width+i];?? ????????}?? ?????? ?????? }<span?style="color:#ffffff;">?? </span>?? void Robert(double *src,double *dst,int width,int height){double RobertMask_x[9]={0,0,0,0,-1,0,0,0,1};double RobertMask_y[9]={0,0,0,0,0,-1,0,1,0};double *dst_x=(double *)malloc(sizeof(double)*width*height);double *dst_y=(double *)malloc(sizeof(double)*width*height);RealConvolution(src, dst_x, RobertMask_x, width, height, ROBERT_MASK_SIZE,ROBERT_MASK_SIZE);RealConvolution(src, dst_y, RobertMask_y, width, height, ROBERT_MASK_SIZE,ROBERT_MASK_SIZE);for(int j=0;j<height;j++)for(int i=0;i<width;i++){dst[j*width+i]=abs(dst_x[j*width+i])+abs(dst_y[j*width+i]);}free(dst_x);free(dst_y);}void RobertSharpen(double *src,double *dst,int width,int height,double c){Robert(src,dst,width,height);for(int j=0;j<height;j++)for(int i=0;i<width;i++){dst[j*width+i]=src[j*width+i]+c*dst[j*width+i];}}<span style="color:#ffffff;">
</span>
Sobel: [cpp] view plaincopyprint?void?Sobel(double?*src,double?*dst,int?width,int?height){?? ????double?SobelMask_x[9]={-1,-2,-1,0,0,0,1,2,1};?? ????double?SobelMask_y[9]={-1,0,1,-2,0,2,-1,0,1};?? ????double?*dst_x=(double?*)malloc(sizeof(double)*width*height);?? ????double?*dst_y=(double?*)malloc(sizeof(double)*width*height);?? ????RealRelevant(src,?dst_x,?SobelMask_x,?width,?height,?SOBEL_MASK_SIZE,SOBEL_MASK_SIZE);?? ????RealRelevant(src,?dst_y,?SobelMask_y,?width,?height,?SOBEL_MASK_SIZE,SOBEL_MASK_SIZE);?? ????for(int?j=0;j<height;j++)?? ????????for(int?i=0;i<width;i++){?? ????????????dst[j*width+i]=abs(dst_x[j*width+i])+abs(dst_y[j*width+i]);?? ?????????? ????????}?? ????free(dst_x);?? ????free(dst_y);?? ?????? }?? ?? void?SobelSharpen(double?*src,double?*dst,int?width,int?height,double?c){?? ????Sobel(src,dst,width,height);?? ????for(int?j=0;j<height;j++)?? ????????for(int?i=0;i<width;i++){?? ????????????dst[j*width+i]=src[j*width+i]+c*dst[j*width+i];?? ????????}?? ?? ?? }?? void Sobel(double *src,double *dst,int width,int height){double SobelMask_x[9]={-1,-2,-1,0,0,0,1,2,1};double SobelMask_y[9]={-1,0,1,-2,0,2,-1,0,1};double *dst_x=(double *)malloc(sizeof(double)*width*height);double *dst_y=(double *)malloc(sizeof(double)*width*height);RealRelevant(src, dst_x, SobelMask_x, width, height, SOBEL_MASK_SIZE,SOBEL_MASK_SIZE);RealRelevant(src, dst_y, SobelMask_y, width, height, SOBEL_MASK_SIZE,SOBEL_MASK_SIZE);for(int j=0;j<height;j++)for(int i=0;i<width;i++){dst[j*width+i]=abs(dst_x[j*width+i])+abs(dst_y[j*width+i]);}free(dst_x);free(dst_y);}void SobelSharpen(double *src,double *dst,int width,int height,double c){Sobel(src,dst,width,height);for(int j=0;j<height;j++)for(int i=0;i<width;i++){dst[j*width+i]=src[j*width+i]+c*dst[j*width+i];}}
原圖:
Robert:
Robert Sharpen:
Sobel: Sobel Sharpen:
可以觀察出Sobel邊緣較寬,來觀察簡單圖形的Robert和Sobel局部放大圖:
Robert:
Sobel: Robert局部放大1,2,3:
目錄(?)[+]
學(xué)習(xí)DIP第36天
轉(zhuǎn)載請標(biāo)明本文出處:http://blog.csdn.net/tonyshengtan,歡迎大家轉(zhuǎn)載,發(fā)現(xiàn)博客被某些論壇轉(zhuǎn)載后,圖像無法正常顯示,無法正常表達(dá)本人觀點(diǎn),對此表示很不滿意。有些網(wǎng)站轉(zhuǎn)載了我的博文,很開心的是自己寫的東西被更多人看到了,但不開心的是這段話被去掉了,也沒標(biāo)明轉(zhuǎn)載來源,雖然這并沒有版權(quán)保護(hù),但感覺還是不太好,出于尊重文章作者的勞動(dòng),轉(zhuǎn)載請標(biāo)明出處!!!!
文章代碼已托管,歡迎共同開發(fā):https://github.com/Tony-Tan/DIPpro
開篇廢話
? ? ? ? 繼續(xù)廢話,之前介紹了二階微分,和非銳化掩蔽,按照順序該說一階微分了,一階微分與二階微分一樣,是線性算子,線性算子的計(jì)算方法多半是生成模板,然后與圖像卷積,一階微分同樣,幾天簡單的介紹兩個(gè)一階微分算子,Robert算子和Sobel算子,這兩個(gè)算子應(yīng)該算是大名鼎鼎了,因?yàn)檫@兩個(gè)算子在后面的邊緣檢測中都是里程碑似的算法,在增強(qiáng)部分,他們也主要用在邊緣增強(qiáng),本文只簡要介紹下兩個(gè)算子的大概使用和增強(qiáng)效果,具體的數(shù)學(xué)原理推導(dǎo)和其他性質(zhì),將在圖像分割部分完整介紹。
圖像梯度介紹
? ? ? 首先介紹下梯度,梯度并非是一個(gè)數(shù)值,梯度嚴(yán)格意義上是一個(gè)向量,這個(gè)向量指向當(dāng)前位置變化最快的方向,可以這么理解,當(dāng)你站在一個(gè)山上,你有360°的方向可以選擇,哪個(gè)方向下降速度最快(最陡峭),便是梯度方向,梯度的長度,表示為向量的長度,表示最大的變化速率。 ? ? ? ?梯度的數(shù)學(xué)表達(dá):
? ? ? ?其中表示微分算子。梯度在三維坐標(biāo)中表示為:
? ? ? ?同樣在二維中只取前兩項(xiàng),也就是由x方向的偏微分和y方向的偏微分組成。對于圖像f中點(diǎn)(x,y)處的梯度,定義為:
與上面所述保持一致,圖像梯度方向給出圖像變化最快方向,當(dāng)前點(diǎn)的梯度長度為:
次長度計(jì)算中有平方和開平方,所以將不再是現(xiàn)行操作。 為了簡單計(jì)算,將上面求距離簡化成:
然而上面式子最大的問題在于不具有旋轉(zhuǎn)不變形,也就是不是各向同性的,具體原因是三角形三遍關(guān)系原理,因?yàn)樘荻确较蚝烷L度對于旋轉(zhuǎn)是不變的,所以,x軸和y軸發(fā)生旋轉(zhuǎn)的時(shí)候,直角三角形兩邊發(fā)生變化,但保持斜邊長度和方向不變,因此兩個(gè)直角邊的長度和必然發(fā)生改變,也就是上面的M值必然會改變,顧其不具有旋轉(zhuǎn)不變形。 ? ? ? ?為了表達(dá)方便先重新來定義下模板位置,如下圖 ? ? ? ? 其中z5表示模板中心。
Robert算子
? ? ? ?奇葩算子Robert,說它奇葩確實(shí)奇葩,因?yàn)椴恢繰obert哪來的勇氣或者推導(dǎo)過程,使用一個(gè)2x2的模板,而且是對角線做差,其差分為:
因?yàn)橄蛄繜o法在圖像中顯示,我們要計(jì)算梯度向量的長度:
簡化為絕對值方法:
這個(gè)就是Robert交叉算子。模板:
Sobel算子
因?yàn)镽obert算子是2x2的模板,不是對稱的奇數(shù)模板,我們更喜歡3x3的模板,所以,要根據(jù)上面的Robert算子改造出來一個(gè)3x3模板,提出了下面這個(gè)計(jì)算方法:
? ? ? ?怎么來的?說實(shí)話我一開始也不知道,只是說根據(jù)上面Robert算子,搞出來一個(gè)等價(jià)的,其數(shù)字模板為:
? ? ? ?并且其下降速率(梯度的長度)計(jì)算公式:
? ? ? ?所有上面的疑惑就是這個(gè)公式: ? ? ? ?到底是怎么來的,為什么中間會有2,以及為什么是隔行相減,下面的過程是我自己發(fā)明的,沒有數(shù)學(xué)依據(jù),只是自己的猜測,根據(jù)Robert算子的兩個(gè)式子,橫向劃過3x3的所有位置,然后相加,就得到了Sobel算子:
這個(gè)過程就用Robert產(chǎn)生了Sobel,同樣的縱向移動(dòng)就會產(chǎn)生x軸方向的算子。Sobel算子原理的論文不多,但都說這是個(gè)很好的邊緣檢測算子。
代碼
Robert: [cpp] view plaincopyprint?
Sobel: [cpp] view plaincopyprint?
結(jié)果
原圖:
Robert:
Robert Sharpen:
Sobel: Sobel Sharpen:
可以觀察出Sobel邊緣較寬,來觀察簡單圖形的Robert和Sobel局部放大圖:
Robert:
Sobel: Robert局部放大1,2,3:
Sobel局部放大圖1,2,3:
?
總結(jié)
? ? ? Sobel和Robert都能對邊緣有較強(qiáng)的響應(yīng),而且Sobel對邊緣的響應(yīng)較寬而且更加強(qiáng)烈,Robert算子對邊緣響應(yīng)較弱,而且對彎曲的邊緣敏感度第(Robert1中圓形弧形部分亮度低)。 ?待續(xù)。。。。 總結(jié)
以上是生活随笔為你收集整理的灰度图像--图像增强 Robert算子、Sobel算子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 灰度图像--图像增强 非锐化掩蔽 (Un
- 下一篇: 灰度图像--图像增强 平滑之均值滤波、高