自定义线性滤波
自定義線性濾波
線性濾波器:將小滑塊與圖像做卷積,小滑塊就是所謂的核,它是一個固定大小的數(shù)值數(shù)組。在該數(shù)組中有一個錨點,一般位于數(shù)組中央。
如何將核與圖像做卷積?
將核的錨點放在特定的像素上,同時核內(nèi)其他值與該像素鄰域的各像素重合。
將核內(nèi)各值與對應(yīng)的圖像像素值相乘,然后相加,再將得到的結(jié)果放在與錨點對應(yīng)的像素上。
對圖像中的所有像素都進行以上的操作。
下面來看一下,對與三階的手動實現(xiàn):
Mat Filter(const Mat src,const Mat kernel) {Mat dst,temp,s;dst = Mat::zeros(src.size(),src.type());kernel.copyTo(s);int height = src.rows;int width = src.cols;int k_size = kernel.rows;int add = (k_size - 1)/2;copyMakeBorder(src,temp,add,add,add,add,BORDER_CONSTANT,Scalar::all(1));uchar* pre;uchar* cur;uchar* next;int* ker = s.ptr<int>(0);for(int row = 0;row < height-1;row++){pre = temp.ptr<uchar>(row-1);cur = temp.ptr<uchar>(row);next = temp.ptr<uchar>(row+1);for(int col = 0;col < width - 1;col++){dst.at<uchar>(row,col) = saturate_cast<uchar>(pre[col-1]*int(ker[0])+pre[col]*int(ker[1])+pre[col+1]*int(ker[2])+cur[col-1]*int(ker[3])+cur[col]*int(ker[4])+cur[col+1]*int(ker[5])+next[col-1]*int(ker[6])+next[col]*int(ker[7])+next[col+1]*int(ker[8]));}}imshow("dst",dst);return dst; }其中,copyMakeBorder()用來給原圖像添加邊框。其他的都是常規(guī)操作。
有個坑,需要注意的是,當我們的核中存在負數(shù)時,我們千萬要注意,如何取值。
Tips:在變成的過程中,如何出現(xiàn)不是圖像的矩陣,一般使用Mat_來定義,如果是圖像,就使用Mat 來定義。
當然了,OpenCV也給我們提供了相關(guān)的API:
下面時完整的代碼:
#include "opencv2/opencv.hpp"using namespace std; using namespace cv;Mat Filter(const Mat src,const Mat kernel);int main(int argc,char** argv) {Mat src = imread("/home/dynamicw/Project/C++_Project/opencvtest/src/lesson01/source/map.png",0);imshow("src",src);Mat kernel = (Mat_<int>(3,3) << 1,-2,1,2,-4,2,1,-2,1);Filter(src,kernel);Mat dst;filter2D(src,dst,-1,kernel,Point(-1,-1),0,BORDER_DEFAULT);imshow("api",dst);waitKey(0);return 0; }Mat Filter(const Mat src,const Mat kernel) {Mat dst,temp,s;dst = Mat::zeros(src.size(),src.type());kernel.copyTo(s);int height = src.rows;int width = src.cols;int k_size = kernel.rows;int add = (k_size - 1)/2;copyMakeBorder(src,temp,add,add,add,add,BORDER_CONSTANT,Scalar::all(1));uchar* pre;uchar* cur;uchar* next;int* ker = s.ptr<int>(0);for(int row = 0;row < height-1;row++){pre = temp.ptr<uchar>(row-1);cur = temp.ptr<uchar>(row);next = temp.ptr<uchar>(row+1);for(int col = 0;col < width - 1;col++){dst.at<uchar>(row,col) = saturate_cast<uchar>(pre[col-1]*int(ker[0])+pre[col]*int(ker[1])+pre[col+1]*int(ker[2])+cur[col-1]*int(ker[3])+cur[col]*int(ker[4])+cur[col+1]*int(ker[5])+next[col-1]*int(ker[6])+next[col]*int(ker[7])+next[col+1]*int(ker[8]));}}imshow("dst",dst);return dst; }總結(jié)
- 上一篇: 可视化戒烟对身体的影响!从20分钟到15
- 下一篇: 人群频率 | gnomAD数据库 (二)