OpenCV 通过掩膜操作提高对比度

本文深入探讨了图像处理中的一种滤波技术,通过具体的代码示例详细解释了如何使用OpenCV库在C++环境中实现图像滤波。文章首先介绍了滤波的基本原理,包括如何对每个像素点及其周围像素进行数学运算,然后展示了如何使用saturate_cast函数确保像素值在有效范围内。此外,还介绍了如何利用filter2D方法实现同样的滤波效果,并对比了两种方法的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

公式及原理

公式:

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

原理上大概是对每个像素点运用公式将其与其周围的四个像素点进行修改操作

 

代码 

#include<iostream>
#include<vector>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main() {
    Mat Img = imread("1.jpg");//选定一张目标图片
	namedWindow("nochange", CV_WINDOW_NORMAL);
	imshow("nochange", Img);//显示原图

	int rows = Img.rows;//需要遍历的行
	int cols = (Img.cols - 1)*Img.channels();//需要遍历的列
	int offsetx = Img.channels();//基本操作单位

	Mat Img2 = Mat::zeros(Img.size(), Img.type());//一个与Img类型大小相同的全0矩阵

	for (int i = 1; i < rows - 1; i++) {
		//定义行指针
		uchar* previous = Img.ptr<uchar>(i - 1);
		uchar* current = Img.ptr<uchar>(i);
		uchar* next = Img.ptr<uchar>(i + 1);
		uchar* output = Img2.ptr<uchar>(i);//传地址 所以下面对output进行的修改直接改在Img2上
		for (int j = offsetx; j < cols; j++) {
                //saturate_cast<uchar>();函数的调用
			output[j] = saturate_cast<uchar>(current[j] * 5 - (current[j - offsetx] + current[j + offsetx] + previous[j] + next[j]));
		}
	}
	namedWindow("change", CV_WINDOW_NORMAL);
	imshow("change", Img2);//显示修改后的图片
    waitkey();
}

需要遍历的列数和图片本身的列数可能是不一样的,这涉及到图片通道数的问题。比如说,如果图片是单通道,那么需要遍历的列数=图片本身的列数,因为单通道图片每个像素点只有一个值来表示;但是如果图片是三通道的RGB图片,那么需要遍历的列数=3*图片本身的列数,因为三通道图片的每个像素点都有三个值来表示。

在用公式的时候要用到offsetx数值,这里即图片的通道数。因为每次进行的实际上是每个像素点与周围四个像素点的对应数值上的操作。单通道图片倒没什么影响,因为它每个像素点只有一个数值表示;而三通道图片有三个数值,第一个数值就应该跟周围四个像素点的第一个数值进行操作,以此类推。

自动处理像素范围函数saturate_cast<typename _Tp>()

用于确保经修改后每个像素点RGB数值在0~255之间

 

用filter2D方法实现

部分代码

    Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义一个掩膜 这个是上面的代码对应的掩膜
	filter2D(Img, Img2, Img.depth(), kernel);
	namedWindow("change", CV_WINDOW_NORMAL);
	imshow("change", Img2);

实现效果跟上面的代码一样。只是你定义了什么样的掩膜,他就会执行什么样的操作,然后出对应的效果。

Img和Img2是Mat类型变量,是把Img修改后的内容赋给Img2(此时Img本身没有被改变)。

depth是图片的深度属性,有32、24、8。如果不知道的话就用-1或者原图.depth(),表示深度和原图一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值