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

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)]

上面的公式可以用掩膜矩阵表示成如下的形式。
在这里插入图片描述

2. 自定义的滤波器实现

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>

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_<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;
}

3 . filter2D API实现

#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>

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_<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三通道的说明

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

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WFForstar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值