OpenCV圖像處理之自定義濾波
圖像處理中,"空間域" 指的是圖像平面,因此,空間濾波可定義為:在圖像平面內(nèi)對(duì)像素灰度值進(jìn)行的濾波
1 空間濾波
1.1 濾波過(guò)程
如圖,F(xiàn)ilter 是一個(gè) 3x3 濾波核,當(dāng)它從圖像的左上角開始,逐個(gè)像素沿水平方向掃描,最后到右下角時(shí),便會(huì)產(chǎn)生濾波后的圖像

假設(shè)輸入圖像 $f(x, y)$,濾波后的圖像為$g(x, y)$,則其中$g(2,2)$ 和 $g(4,4)$ 的計(jì)算過(guò)程如下:

上圖中,以像素 (4,4) 為中心的 3x3 鄰域,和濾波核的向量點(diǎn)乘之積,即為 g(4,4)
g(4,4) = 240*0.1111 + 183*0.1111 + 0*0.1111 + 250*0.1111 + 12*0.1111 + 87*0.1111 + 255*0.1111 + 1*0.1111 + 94*0.1111
= 26.6666 + 20.3333 + 0 + 27.7777 + 1.3333 + 9.6666 + 28.3333 + 0 + 10.4444
= 124.55
1.2 相關(guān)和卷積
空間濾波中,相關(guān)和卷積,是容易混淆的概念,定義如下:
-相關(guān) (Correlation),和上述的濾波過(guò)程一樣,即 濾波核 逐行掃描圖像,并計(jì)算每個(gè)位置像素點(diǎn)積的過(guò)程
-卷積 (Convolution),和 "相關(guān)" 過(guò)程類似,但 濾波核 要先旋轉(zhuǎn) 180°,然后再執(zhí)行和 “相關(guān)” 一樣的操作
(二維中的旋轉(zhuǎn) 180°,等于濾波核沿一個(gè)坐標(biāo)軸翻轉(zhuǎn),然后再沿另一個(gè)坐標(biāo)軸翻轉(zhuǎn))

注意:如果濾波核是對(duì)稱的,則對(duì)圖像進(jìn)行相關(guān)和卷積的結(jié)果是一致的
2 OpenCV 函數(shù)
2.1 filter2D 函數(shù)
在 OpenCV 中,可自定義濾波核,然后通過(guò) filter2D() 來(lái)完成圖像濾波
void filter2D(
InputArray src, // 輸入圖像
OutputArray dst, // 輸出圖像(大小和通道數(shù),同 src)
int ddepth, // 輸出圖像的 depth
InputArray kernel, // 濾波核,準(zhǔn)確地說(shuō),是相關(guān)核
Point anchor = Point(-1,-1), // 錨點(diǎn)位置,濾波核尺寸為奇數(shù)時(shí),不用指定,一般取默認(rèn)值 Point(-1,-1);濾波核尺寸為偶數(shù)時(shí),需指定錨點(diǎn)位置
double delta = 0, // optional value added to the filtered pixels before storing them in dst
int borderType = BORDER_DEFAULT // 邊界處理方法
);
filter2D() 求的是相關(guān),并非卷積,只有當(dāng)濾波核對(duì)稱時(shí),filte2D() 才可視為卷積運(yùn)算,其公式如下:

假定濾波核 kernel 大小為 3x3,以一個(gè)像素點(diǎn) src(4,4) 為例,則有:
dst(4,4) = kernel(0,0)*src(4+0-1, 4+0-1) + kernel(0,1)*src(4+0-1, 4+1-1) + kernel(0,2)*src(4+0-1, 4+2-1)
+ kernel(1,0)*src(4+1-1, 4+0-1) + kernel(1,1)*src(4+1-1, 4+1-1) + kernel(1,2)*src(4+1-1, 4+2-1)
+ kernel(2,0)*src(4+2-1, 4+0-1) + kernel(2,1)*src(4+2-1, 4+1-1) + kernel(2,2)*src(4+2-1, 4+2-1)
濾波核與輸入圖像的卷積點(diǎn)乘,對(duì)應(yīng)關(guān)系如下:

2.2 flip 函數(shù)
當(dāng)濾波核不對(duì)稱時(shí),要得到真正的卷積運(yùn)算,還需 flip() 函數(shù)來(lái)完成 kernel 的二維翻轉(zhuǎn)
如果濾波核的大小為奇數(shù),則 filter2D() 中的錨點(diǎn)位置可設(shè)為 Point(-1,-1),此時(shí),默認(rèn)濾波核的中心為錨點(diǎn);如果濾波核的大小為偶數(shù),則需要自定義錨點(diǎn)位置
OpenCV 中錨點(diǎn)位置的實(shí)現(xiàn)函數(shù)normalizeAnchor() 如下:
void flip(
InputArray src, // input array
OutputArray dst, // output array
int flipCode // 0, flip around x-axis; positive value, flip around y-axis; negative value, flip around both axes.
);
3 代碼示例
3.1 偏導(dǎo)數(shù)
自定義濾波核,利用 filter2D() 函數(shù),實(shí)現(xiàn)圖像的一階和二階偏導(dǎo)運(yùn)算
1) 一階偏導(dǎo)
圖像在 x 和 y 方向的一階偏導(dǎo)如下:

對(duì)應(yīng)濾波核為 
2) 二階偏導(dǎo)
同樣,在 x 和 y 方向的二階偏導(dǎo)如下:

對(duì)應(yīng)濾波核為 
3.2 代碼示例
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main()
{
// 讀取圖像
Mat src = imread("fangtze.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
return -1;
}
Mat kx = (Mat_<float>(1, 2) << -1, 1); // 1行2列的 dx 濾波核
Mat ky = (Mat_<float>(2, 1) << -1, 1); // 2行1列的 dy 濾波核
Mat kxx = (Mat_<float>(1, 3) << 1, -2, 1); // 1行3列的 dxx 濾波核
Mat kyy = (Mat_<float>(3, 1) << 1, -2, 1); // 3行1列的 dyy 濾波核
Mat kxy = (Mat_<float>(2, 2) << 1, -1, -1, 1); // 2行2列的 dxy 濾波核
// 一階偏導(dǎo)
Mat dx, dy;
filter2D(src, dx, CV_32FC1, kx);
filter2D(src, dy, CV_32FC1, ky);
// 二階偏導(dǎo)
Mat dxx, dyy, dxy;
filter2D(src, dxx, CV_32FC1, kxx);
filter2D(src, dyy, CV_32FC1, kyy);
filter2D(src, dxy, CV_32FC1, kxy);
// 顯示圖像
imshow("dx", dx);
waitKey();
}
輸出的偏導(dǎo)圖像如下,第一行從左到右:原圖 - dx - dy;第二行從左至右:dxy - dxx -dyy






參考資料
OpenCV Tutorials / imgproc module /Making your own linear filters
Gonzalez,《Digital Image Processing》4th ch3 Intesity Transformations and Spatial Filtering
CS425 Lab: Intensity Transformations and Spatial Filtering
總結(jié)
到此這篇關(guān)于OpenCV圖像處理之自定義濾波的文章就介紹到這了,更多相關(guān)OpenCV自定義濾波內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python基礎(chǔ)之包的導(dǎo)入和__init__.py的介紹
這篇文章主要介紹了python基礎(chǔ)之包的導(dǎo)入和__init__.py的相關(guān)資料,需要的朋友可以參考下2018-01-01
大家都說(shuō)好用的Python命令行庫(kù)click的使用
這篇文章主要介紹了大家都說(shuō)好用的Python命令行庫(kù)click的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
實(shí)例探究Python以并發(fā)方式編寫高性能端口掃描器的方法
端口掃描器就是向一批端口上發(fā)送請(qǐng)求來(lái)檢測(cè)端口是否打開的程序,這里我們以實(shí)例探究Python以并發(fā)方式編寫高性能端口掃描器的方法2016-06-06
Python實(shí)現(xiàn)將圖片轉(zhuǎn)換為ASCII字符畫
這篇文章主要介紹了Python實(shí)現(xiàn)將圖片轉(zhuǎn)換為ASCII字符畫,要將圖片轉(zhuǎn)換為字符圖其實(shí)很簡(jiǎn)單,我們首先將圖片轉(zhuǎn)換為灰度圖像,這樣圖片的每個(gè)像素點(diǎn)的顏色值都是0到255,然后我們選用一些在文字矩形框內(nèi)占用面積從大到小的ASCII碼字符2022-08-08
Python實(shí)現(xiàn)暴力匹配算法(字符串匹配)
本文主要介紹了Python實(shí)現(xiàn)暴力匹配算法,其主要思想是逐個(gè)字符地比較文本串和模式串,從文本串的每個(gè)可能的起始位置開始,依次檢查是否有匹配的子串,下面就來(lái)介紹 一下如何實(shí)現(xiàn)2023-09-09
Python學(xué)習(xí)_幾種存取xls/xlsx文件的方法總結(jié)
今天小編就為大家分享一篇Python學(xué)習(xí)_幾種存取xls/xlsx文件的方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05

