OpenCV(5)-圖像掩碼操作(卷積)-銳化


銳化概念

圖像平滑過程是去除噪聲的過程。圖像的主要能量在低頻部分,而噪聲主要集中在高頻部分。圖像的邊緣信息主要也在高頻部分,在平滑處理后,將會丟不部分邊緣信息。因此需要使用銳化技術來增強邊緣。

平滑處理的本質是圖像經過平均或積分運算,銳化進行逆運算(如微分)即可。微分運算是求信號變化頻率,可以增強高頻分量的作用。在對圖像進行銳化處理前要確定圖像有較高的信噪比,否則處理后的圖像增加的噪聲比信號多。

常用的微分運算有一階微分和二階微分。一階微分

\[\frac{\partial f}{\partial x}=f(x+1)-f(x) \]

二階微分

\[\frac{\partial^2 f}{\partial x^2}=f(x+1)+f(x-1)-f(x) \]

一階微分特點:
1、平坦段為0
2、灰度階梯和斜坡起始點為非0
3、斜坡面為非0

二階微分特點:
1、平坦段為0
2、灰度階梯和斜坡起始、終止處為非0
3、沿着常數斜率斜坡段為0

可以看出:
1、一階微分能產生比較寬的邊緣(沿斜坡很長一段為非0),而二階微對細節更敏感(如細線、孤立點、斜坡起始點不為0)。
2、一階微分都灰度階躍反應強烈;二階微分對灰度階梯變換產生雙相應(階躍點兩邊都不為0)。
3、在大多數圖像增強應用中,二階微分效果好過一階微分。

圖像微分定義

圖像數據是離散數據,用差分代替微分

x方向

\[\nabla_xf(x,y)=f(x+1,y)-f(x,y) \]

y方向

\[\nabla_yf(x,y)=f(x,y+1)-f(x,y) \]

其模和方向

\[|\nabla_{x,y}f(x,y)|=(\nabla_xf(x,y)^2+\nabla_yf(x,y)^2)^\frac{1}{2} \]

\[\alpha = arctan\frac{\nabla_xf(x,y)}{\nabla_yf(x,y)} \]

同理,可以得到二階微分(差分公式)
x方向

\[\nabla_x^2f(x,y)=f(x+1,y)+f(x-1,y)-f(x,y) \]

y方向

\[\nabla_y^2f(x,y)=f(x,y+1)+f(x,y-1)-f(x,y) \]

其模和方向

\[|\nabla_{x,y}^2f(x,y)|=(\nabla_x^2f(x,y)^2+\nabla_y^2f(x,y)^2)^\frac{1}{2} \]

\[\alpha = arctan\frac{\nabla_x^2f(x,y)}{\nabla_y^2f(x,y)} \]

單方向一階微分銳化

單方向一階微分銳化是指銳化某一方向的邊緣。最簡單的就是銳化水平方向和垂直方向。
銳化水平方向

\[ \left[ \begin{matrix} 1 & 1 & 1 \\ 0& 0 & 0 \\ -1 & -1 & -1 \end{matrix} \right] \tag{3} \]

銳化垂直方向

\[ \left[ \begin{matrix} 1 &0 & -1 \\ 1& 0 & -1 \\ 1 & 0 & -1 \end{matrix} \right] \tag{3} \]

銳化后可能出現像素值為負,這處理方法有:
(1):所有像素值統一加上一個值。這樣處理效果類似浮雕。
(2):所有像素取絕對值,這樣可以有效提取邊緣。

實驗:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char* argv[]){
	const char* path = "";
	Mat img = imread(path);
	if (img.empty())
	{
		cout << "error";
		return -1;
	}
	imshow("原圖像", img);


	//水平方向邊緣提取
	Mat h_kern = (Mat_<float>(3, 3) << 1, 1, 1,
									0, 0, 0,
									-1, -1, -1);
	Mat h_mat;
	filter2D(img, h_mat, img.depth(), h_kern);
	imshow("水平方向邊緣提取", h_mat);

	Mat v_kern = (Mat_<float>(3, 3) << 1, 0, -1,
									1, 0, -1,
									1, 0, -1);
	Mat v_mat;
	filter2D(img, v_mat, img.depth(), v_kern);
	imshow("線性非均值濾波2", v_mat);

	waitKey();
	return 0;

}

無方向一階微分銳化

對於有規則的物體,單方向銳化有比較好的效果,但是對於不規則物體,常常需要無方向一節銳化。

交叉微分(Roberts算法)

\[g(x,y)=|f(x+1,y+1)-f(x,y)|+|f(x+1,y)-f(x,y+1)| \]

\[\nabla_xf(x,y)=\left[ \begin{matrix} -1 & 0 \\ 0 & 1 \end{matrix} \right] \tag{3} \]

\[\nabla_yf(x,y)=\left[ \begin{matrix} 0 & 1 \\ -1 & 0 \end{matrix} \right] \tag{3} \]

Sobel銳化

\[g(x,y)=\{|\nabla_xf(x,y)|^2+|\nabla_yf(x,y)|^2\}^\frac{1}{2} \]

\[\nabla_xf(x,y)=\left[ \begin{matrix} -1 & -2 & -1 \\ 0 & 0 & 0\\ 1& 2 & 1 \end{matrix} \right] \tag{3} \]

\[\nabla_yf(x,y)=\left[ \begin{matrix} -1 & 0 & 1 \\ -2 & 0 & 2\\ -1& 0 & 1 \end{matrix} \right] \tag{3} \]

OpenCV函數

void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT )

Priwitt銳化

\[g(x,y)=\{|\nabla_xf(x,y)|^2+|\nabla_yf(x,y)|^2\}^\frac{1}{2} \]

\[\nabla_xf(x,y)=\left[ \begin{matrix} -1 & -1 & -1 \\ 0 & 0 & 0\\ 1& 1 & 1 \end{matrix} \right] \tag{3} \]

\[\nabla_yf(x,y)=\left[ \begin{matrix} -1 & 0 & 1 \\ -1 & 0 & 1\\ -1& 0 & 1 \end{matrix} \right] \tag{3} \]

實驗

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;
int main(int argc, char* argv[]){
	const char* path = "";
	Mat img = imread(path);
	if (img.empty())
	{
		cout << "error";
		return -1;
	}
	imshow("原圖像", img);
	

	/****************************Roberts**************************/
	Mat Roberts_kern_x = (Mat_<float>(2, 2) << -1, 0,
									0, 1);
	
	Mat Roberts_kern_y = (Mat_<float>(2, 2) << 0, 1,
											- 1, 0);
	
	Mat Roberts_Mat_x, Roberts_Mat_y, Roberts_Mat;
	
	filter2D(img, Roberts_Mat_x, img.depth(), Roberts_kern_x);
	filter2D(img, Roberts_Mat_y, img.depth(), Roberts_kern_y);
	Mat Roberts_abs_x, Roberts_abs_y;
	convertScaleAbs(Roberts_Mat_x, Roberts_abs_x);
	convertScaleAbs(Roberts_Mat_y, Roberts_abs_y);
	addWeighted(Roberts_abs_x, 0.5, Roberts_abs_y, 0.5, 0, Roberts_Mat);
	imshow("Roberts", Roberts_Mat);
	/****************************Roberts**************************/

	/****************************Sobel**************************/

	Mat Sobel_Mat_x, Sobel_Mat_y, Sobel_Mat;
	Sobel(img, Sobel_Mat_x, img.depth(), 1, 0);
	Sobel(img, Sobel_Mat_y, img.depth(), 0, 1);
	convertScaleAbs(Sobel_Mat_x, Sobel_Mat_x);
	convertScaleAbs(Sobel_Mat_y, Sobel_Mat_y);
	addWeighted(Sobel_Mat_x, 0.5, Sobel_Mat_y, 0.5, 0,  Sobel_Mat);
	imshow("Sobel", Sobel_Mat);

	/****************************Sobel**************************/

	/****************************Priwitt**************************/
	Mat Priwitt_kern_x = (Mat_<float>(3, 3) << -1, -1, -1, 0, 0, 0, 1, 1, 1);
	Mat Priwitt_kern_y = (Mat_<float>(3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);

	Mat Priwitt_Mat_x, Priwitt_Mat_y, Priwitt_Mat;
	filter2D(img, Priwitt_Mat_x, img.depth(), Priwitt_kern_x);
	filter2D(img, Priwitt_Mat_y, img.depth(), Priwitt_kern_y);
	convertScaleAbs(Priwitt_Mat_x, Priwitt_Mat_x);
	convertScaleAbs(Priwitt_Mat_y, Priwitt_Mat_y);
	addWeighted(Priwitt_Mat_x, 0.5, Priwitt_Mat_y, 0.5, 0, Priwitt_Mat);
	imshow("Peiwitt", Priwitt_Mat);

	waitKey();
	return 0;

}

結論:
Roberts算法的模板為2 * 2,提取邊緣能力較弱。
Sobel算法與Priwitt算法的模板大小相同,屬於同一類型,因此處理效果基本相同。

二階微分銳化

有些灰度特性,一階微分並不能有效提取,這時需要二階微分

\[\frac{\partial^2 f_x(x,y)}{\partial x^2}=\partial f_x(x+1)-\partial f_x(x)=[f(x,y) - f(x-1,y)]-[f(x+1,y)-f(x,y)] \]

\[\frac{\partial^2 f_y(x,y)}{\partial x^2}=\partial f_y(x+1)-\partial f_y(x)=[f(x,y) - f(x,y -1)]-[f(x,y + 1)-f(x,y)] \]

\[\frac{\partial^2 f(x,y)}{\partial x^2}=4f(x,y) - f(x+1,y) - f(x-1,y)- f(x,y+1)-f(x,y-1) \]

對應矩陣

\[H_1=\left[ \begin{matrix} 0 & -1 & 0 \\ -1 & 4 & -1\\ 0& -1 &0 \end{matrix} \right] \tag{3} \]

上面矩陣即為Laplacian算子。Laplacian算子還有變形

Laplacian算子

\[H_2=\left[ \begin{matrix} -1 & -1 & -1 \\ -1 & 8 & -1\\ -1& -1 & -1 \end{matrix} \right] \tag{3} \]

\[H_3=\left[ \begin{matrix} 1 & -2 & 1 \\ -2 & 4 & -2\\ 1& -2 & 1 \end{matrix} \right] \tag{3} \]

\[H_4=\left[ \begin{matrix} 0 & -1 & 0 \\ -1 & 5 & -1\\ 0& -1 & 0 \end{matrix} \right] \tag{3} \]

上面幾個算子,\(H_1\)\(H_2\)效果接近,\(H_3\)效果比較差,\(H_4\)相加后為1,接近原圖。

Wallis算子

在處理時,加入對數處理過程。

\[g(x,y)=log[f(x,y)] -\frac{1}{4}[logf(x-1,y) + logf(x+1,y)+logf(x,y-1)+logf(x,y-1)] \]

在前面的算法公式中注意以下幾點:
1)為了防止對0取對數,計算時實際上是用log(f(i, j) + 1);
2)因為對數值很小log(256) = 5.45, 所以計算
時用46*log(f(i, j) + 1)。
(46 = 255 / log(256))

高斯-拉普拉斯算子

Laplacian算子對噪聲很敏感,所以在進行銳化之前,需要先對圖像進行平滑,減小噪聲影響。高斯拉普拉斯算子將平滑和銳化結合在一起,適應了上面的需求。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM