opencv学习笔记(三)——掩膜操作(C++)

文章目录

  • 1 . 定义
  • 2. 自定义的滤波器实现
  • 3 . filter2D API实现
  • 4 . 关于RGB三通道的说明

1 . 定义

掩膜操作是指根据掩膜矩阵(也称作核kernel)重新计算图像中每个像素的值。掩膜矩阵中的值表示了邻近像素值(包括该像素自身的值)对新像素值有多大的影响。从数学的观点来看,我们用自己设置的权值,对像素领域内的值做了个加权平均。
比如,下面这个公式表示用5倍当前像素的值减去该像素上、下、左、右四个像素值和,得到的结果赋值给当前像素。使用该公式可以用于提升图像的对比度。调节I(i,j)的系数权重可以得到不同的对比度提升效果。

I(i,j)=5I(i,j)[I(i−1,j)+I(i+1,j)+I(i,j−1)+I(i,j+1)]

上面的公式可以用掩膜矩阵表示成如下的形式。
opencv学习笔记(三)——掩膜操作(C++)_第1张图片

2. 自定义的滤波器实现

#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;

int main()
{
	Mat img, dst;
	img = imread("D:/VS项目/opencv3/1.jpg", IMREAD_UNCHANGED);
	//如果没有读取到图像信息,直接退出
	if (!img.data)
		return -1;

	dst = Mat::zeros(img.size(), img.type());  //自己定义的全零图像
	int rows = img.rows;
	int cols = (img.cols - 1) * img.channels();  //因为原图是个RGB图像,所以需要乘以通道数,因为每个列都是三个值
	int offsetx = img.channels();

	for (int row = 1; row < rows - 1; row++)  //从第二行开始到倒数第二行结束
	{
		//uchar是指无符号字符型
		const uchar* previous = img.ptr<uchar>(row - 1);  //指向上一行
		const uchar* current = img.ptr<uchar>(row); //指向当前行
		const uchar* next = img.ptr<uchar>(row + 1);  //指向下一行
		uchar* output = dst.ptr<uchar>(row);  // 指向定义的全零图像
		for (int col = offsetx; col < cols; col++)  // 因为是RGB三通道图像,所以要从第三个开始
		{
			//进行掩膜操作:I(i,j)=5∗I(i,j)−[I(i−1,j)+I(i+1,j)+I(i,j−1)+I(i,j+1)],增加对比度
			//saturate_cast是为为了确保像素的大小在(0,255)之间
			output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));//中间的像素值*5减去周围的像素值--前面是防止像素超过256
		}
	}
	//调用opencv的API
	//Mat kernel = (Mat_(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);  //自定义掩膜(卷积核)
	//filter2D(img, dst, img.depth(), kernel);//对图像进行掩膜操作

	namedWindow("result view", CV_WINDOW_AUTOSIZE);
	imshow("result view", dst);
	imshow("origin view", img);
	waitKey(0);
	return 0;
}

3 . filter2D API实现

#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;

int main()
{
	Mat img, dst;
	img = imread("D:/VS项目/opencv3/1.jpg", IMREAD_UNCHANGED);
	//如果没有读取到图像信息,直接退出
	if (!img.data)
		return -1;

	dst = Mat::zeros(img.size(), img.type());  //自己定义的全零图像
	/*
	int rows = img.rows;
	int cols = (img.cols - 1) * img.channels();  //因为原图是个RGB图像,所以需要乘以通道数,因为每个列都是三个值
	int offsetx = img.channels();

	for (int row = 1; row < rows - 1; row++)  //从第二行开始到倒数第二行结束
	{
		//uchar是指无符号字符型
		const uchar* previous = img.ptr(row - 1);  //指向上一行
		const uchar* current = img.ptr(row); //指向当前行
		const uchar* next = img.ptr(row + 1);  //指向下一行
		uchar* output = dst.ptr(row);  // 指向定义的全零图像
		for (int col = offsetx; col < cols; col++)  // 因为是RGB三通道图像,所以要从第三个开始
		{
			//进行掩膜操作:I(i,j)=5∗I(i,j)−[I(i−1,j)+I(i+1,j)+I(i,j−1)+I(i,j+1)],增加对比度
			//saturate_cast是为为了确保像素的大小在(0,255)之间
			output[col] = saturate_cast(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));//中间的像素值*5减去周围的像素值--前面是防止像素超过256
		}
	}
	*/
	//调用opencv的API
	Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);  //自定义掩膜(卷积核)
	filter2D(img, dst, img.depth(), kernel);//对图像进行掩膜操作

	namedWindow("result view", CV_WINDOW_AUTOSIZE);
	imshow("result view", dst);
	imshow("origin view", img);
	waitKey(0);
	return 0;
}

4 . 关于RGB三通道的说明

在这里插入图片描述
这段代码老是看的云里雾里的,于是就去查了点资料。
在这里插入图片描述
一个像素需要多个矩阵元素来保存,矩阵中的列会包含多个子列,且子列数和通道数相等,就如上图所示。

你可能感兴趣的:(opencv,计算机视觉,c++)