opencv入门(2)

2.1 矩阵的掩膜操作

2.1.1 掩膜操作

       掩膜操作是指根据掩膜矩阵(mask,也称为内核kernel)重新计算图像中每个像素的值。利用掩膜矩阵调整相邻像素对当前像素值的影响。从数学的角度来看,即是利用特定的权重值,对像素做一个加权平均。

假设有一个3*3的卷积核,矩阵参数如下图所示

用该核去遍历每个像素,及当前像素的值为5倍当前像素的值减去该像素上、下、左、右四个像素值和。如下图计算。该掩膜操作可用以调整图像的对比度。

image

 在opencv中核可以如下定义:

Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

为了进行掩膜操作,可以数组遍历或对图像数据进行像素指针的获取。

2.1.2 获取图像像素指针

▶确保输入图像是无符号字符类型(uchar)的:CV_Assert(Image.depth() == CV_8U);

▶获取像素矩阵的指针Mat.prt<uchar>(int i=0);当前row行为const uchar* currentPrt=Image.prt<uchar>(row);

▶获取(row,col)像素点的值p(row,col)=currentPrt[col];

2.1.3 获取Mat数组的像素值

可以使用图像坐标 at方法去进行像素的获取,但是效率慢,适用于随机访问。

动态地址遍历范例如下:

cv::Mat srcImg = cv::imread(sFileName, CV_8UC2); // 读灰度图时改为CV_8UC1
cv::Mat dstImg = cv::Mat::zeros(srcImg.size(), srcImg.type());
int nChannels = srcImg.channels();//获取通道数

for (int i = 0; i < srcImg.rows; i++)
{
	for (int j = 0; j < srcImg.cols; j++)
	{
		for (int k = 0; k<nChannels; k++)
		{
			dstImg.at<uchar>(i, j*nChannels +k) = 255 - srcImg.at<uchar>(i, j*nChannels + k);
		}
	}
}

2.1.4 像素值范围处理--saturate_cast<uchar>

通过掩膜操作计算后,可通过该API保证像素灰度值的大小在0~255之间。

saturate_cast< <0 >返回0
saturate_cast<0·255 >返回输入值
saturate_cast< >255 >返回255

2.1.5 掩膜操作API(卷积函数)--filter2D

opencv提供了直接可对图像进行处理的API接口。

·void filter2D( InputArray src, OutputArray dst, int depth, InputArray kernel, Point anchor = Point(-1,-1), double delta = 0,int borderType = BORDER_DEFAULT)

参数含义
作用对二维矩阵进行卷积运算
输入src

原图

dst结果图(变换后的图像)
depth输出图像的深度 [-1 将给出与输入图像相同的输出图像深度]
kernel卷积核:卷积矩阵中使用的简单二维矩阵或用于模糊、锐化和边检测图像的掩码
Point锚点:被平滑的那个点,默认值Point(-1,-1)表示这个锚点在核的中心。。
delta在将结果存储到输出图像之前添加到每个像素的可选值。默认值为 0。
borderType边界填充类型,用于指定如何处理边界像素。默认值为 cv::BORDER_DEFAULT。
返回值void

2.2 代码范例

2.2.1 通过指针遍历进行掩膜操作

	Mat srcImg = imread("D:\\testimg\\CSet12\\lena.png");
	if (srcImg.empty())
	{
		printf("Could not load the image...\n");
		return -1;
	}
	else;

	//显示窗口
	namedWindow("srcImg", WINDOW_AUTOSIZE);
	imshow("srcImg", srcImg);

	//使用指针遍历掩膜操作
	int nCols = srcImg.cols;
	int nRows = srcImg.rows;

	//由于图像位深不同,会导致所占用的字节数不同
	int nOffset = srcImg.channels();  //每个像素的占用字节数
	int nColPrt = (nCols - 1)*nOffset;//确保每个通道的值都能遍历到
	Mat dstImg= Mat::zeros(srcImg.size(), srcImg.type());
	for (int row = 1; row < (nRows - 1); row++)
	{
		const uchar* previous = srcImg.ptr<uchar>(row - 1);
		const uchar* current = srcImg.ptr<uchar>(row);
		const uchar* next = srcImg.ptr<uchar>(row + 1);
		uchar* output = dstImg.ptr<uchar>(row);
		for (int col = nOffset; col < nColPrt; col++)
		{
			output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - nOffset] + current[col + nOffset] + previous[col] + next[col]));
		}
	}

2.2.2 通过卷积操作API处理

// 使用 掩膜操作API
Mat dstImg2;
Mat kernel=(Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
filter2D(srcImg, dstImg2, srcImg.depth(), kernel);

处理结果如下图所示

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值