opencv實現拉普拉斯銳化的總結
阿新 • • 發佈:2018-12-21
我先粗類的介紹一下拉普拉斯運算元就是沿著x方向的二階導數和沿著y方向的二階導數之和。
由於影象都是離散的值,所以結果是得到一個簡單的線性表示式,如下圖所示
拉普拉斯運算元
寫成濾波器則是{0,1,0,
1,-4,1,
0,1,0}
其他還有幾個常用的濾波器{1,1,1,1,-8,1,1,1,1}
以及對他們的取相反數。
拉普拉斯處理結果是得到圖片的細節部分,這裡我介紹一下我理解的為什麼?
因為一階導數便是資料的變化情況,二階導數便是資料變化的速度。變化速度越快就會得到數值上越大的濾波結果。所以該濾波結果是得到了圖片的細節,再將圖片的細節加到原圖上,那麼結果就是細節部分增強,其餘部分基本不變,也就是達到了銳化的效果。
接下來介紹一下實現的具體步驟。
下面是程式碼
#include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; void toBeOne(Mat&input,Mat&output,int index=0) { float max=0,min=0; output=Mat::zeros(input.rows,input.cols,CV_8UC3); for(int i=0;i<input.rows;i++) { float *ptr=input.ptr<float>(i); for(int j=0;j<input.cols*3;j++)//影象為3通道 { if(max<ptr[j])max=ptr[j]; if(min>ptr[j])min=ptr[j]; } } //取出影象中的上下限 for(int i=0;i<input.rows;i++) { float *ptr=input.ptr<float>(i); uchar *optr=output.ptr<uchar>(i); for(int j=0;j<input.cols*3;j++) { if(index) { if(ptr[j]>1){optr[j]=255;continue;} else if(ptr[j]<0){optr[j]=0;continue;} else optr[j]=(uchar)(ptr[j]*255); } else optr[j]=(uchar)((ptr[j]-min)/(max-min)*255); } } } int main(int a,char**p) { Mat iinput=imread(p[1]),input,Tlaplas; iinput.convertTo(input,CV_32F,1.0/255,0);//把圖片轉化為float型別,這樣子可以直接進行加減而不會溢位 Mat kern=(Mat_<char>(3,3)<<1,1,1,1,-8,1,1,1,1);//濾波器 Mat laplas; Mat output; filter2D(input,laplas,input.depth(),kern);//使用濾波器kern對input進行相關操作,結果儲存在laplas中 toBeOne(laplas,Tlaplas);//自己定義的歸一函式,把float型別的laplas拉伸到型別為uchar的Tlaplas中 output=input-laplas;//如果中間的值是正的則是加號,負值則是減號 toBeOne(output,iinput,1);//把float型別的結果轉化為uchar型別,把超出範圍的直接裁剪 imshow("output_float",output); imshow("input",input); imshow("laplas",laplas); imshow("Tlaplas",Tlaplas); imshow("output_uchar",iinput); waitKey(); return 0; }
輸入
輸出結果