圖像的掩膜操作



注:原創不易,轉載請務必注明原作者和出處,感謝支持!

所涉及的API

void cv::filter2D(
	InputArray src,						// 輸入圖像
    OutputArray dst,					// 輸出圖像
    int ddepth,							// 輸出圖像深度
    InputArray kernel,					// 掩膜矩陣(核)
    Point anchor = Point(-1, -1),
    double delta = 0,
    int borderType = BORDER_DEFAULT
);

圖像的掩膜操作

什么是圖像的掩膜操作?

掩膜操作是指根據掩膜矩陣(也稱作核kernel)重新計算圖像中每個像素的值。掩膜矩陣中的值表示了鄰近像素值(包括該像素自身的值)對新像素值有多大的影響。從數學的觀點來看,我們用自己設置的權值,對像素領域內的值做了個加權平均。

比如,下面這個公式表示用5倍當前像素的值減去該像素上、下、左、右四個像素值和,得到的結果賦值給當前像素。使用該公式可以用於提升圖像的對比度。調節\(I(i,j)\)的系數權重可以得到不同的對比度提升效果。

\[I(i, j) = 5 * I(i, j) - [I(i-1, j) + I(i+1, j) + I(i, j-1) + I(i, j+1)] \]

上面的公式可以用掩膜矩陣表示成如下的形式。

\[\begin{bmatrix} 0&-1&0\\ -1&5&-1\\ 0&-1&0 \end{bmatrix} \]

如果不使用OpenCV提供的API,直接利用OpenCV提供的對圖像像素的訪問功能,則上述公式所對應的掩膜操作可以用下面的代碼實現。

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

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{
	// load image and show
	Mat src = imread("D:\\IMG\\lena.jpg", IMREAD_COLOR);
	if (!src.data)
	{
		cout << "Error : could not load image." << endl;
		return -1;
	}
	imshow("input image", src);

	// image sharpen
	auto rows = src.rows;
	auto cols = src.cols;
	auto channels = src.channels();
	Mat dst = Mat::zeros(src.size(), src.type());

	decltype(src.rows) row, col;
	for (row = 1; row < (rows - 1); ++row)
	{
		// get points pointed to rows of the source image
		const uchar *prev = src.ptr<uchar>(row - 1);
		const uchar *curr = src.ptr<uchar>(row);
		const uchar *next = src.ptr<uchar>(row + 1);
		uchar *output = dst.ptr<uchar>(row);

		for (col = channels; col < ((cols - 1) * channels); ++col)
		{
			output[col] = saturate_cast<uchar>(7 * curr[col] - curr[col - channels]
				- curr[col + channels] - prev[col] - next[col]);
		}
	}
	imshow("sharpen image", dst);

	waitKey(0);
	return 0;
}

如果使用filter2D()則可以將上述公式作如下的實現。

// by filter2D()
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 9, -1, 0, -1, 0);
filter2D(src, dst, src.depth(), kernel);

對於上述兩種實現方式,有一些需要注意的地方:
(1) 在不使用API直接手寫實現方式中,圖像最外邊的一圈像素將會是黑色的。因為核的大小是3x3的,無法對圖像的最邊緣一圈像素進行掩膜計算。
(2) 使用APIfilter2D()通常的性能會比自己手寫更好。因為OpenCV針對API的性能進行了很好的優化。

實現效果

  • 原圖

  • 直接手寫實現,I(i,j)的權重分別為5, 7, 9

  • 使用filter2D實現,I(i,j)的權重分別為5, 7, 9



免責聲明!

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



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