图像的掩膜操作

掩码操作是根据核来重新计算每个像素点的值,也就是对该像素点根据周围的像素点做一个加权平均。 
就以增强图片对比对来展示吧,使用的是下面的这个公式: 

这里写图片描述

引用opencv中文社区的一句话:
矩阵掩码的思想是:根据掩码矩阵(也称作核)重新计算图像中每个像素的值。掩码矩阵中的值表示近邻像素值(包括该像素自身的值)对新像素值有多大影响。从数学观点看,我们用自己设置的权值,对像素邻域内的值做了个加权平均。

也就是对一个图片中的每一个像素点重新赋值。值的大小受到该像素点周围4个像素点的影响。

看上面公式,I(i,j)表示目标像素点,i和j分别表示像素点的横纵坐标。 I(i-1,j) 、I(i+1,j) 、 I(i,j-1) 、 I(i,j+1)分别表示目标像素点周围的四个像素点了。上面公式的作用就是,让自己增加4倍,然后减去周围像素点的值,所得到的值便是自己新的值。为什么要这样子做呢?假设b = [ I(i-1,j) + I(i+1,j) + I(i,j-1) + I(i,j+1)],如果目标像素颜色很鲜艳,它周围的像素点颜色不鲜艳,那么通过公式,也就是`5*I(i,j)-b >I(i,j)`,得到的值比原来的值大,也就是目标点会变得更加鲜艳。相反,目标像素点会变得更加不鲜艳。所以,这个掩码操作的作用就是突出像素点,让鲜艳的点更加鲜艳,让昏暗的点更加昏暗。这样操作之后从整个图片上看,图片就有了锐化的效果了。


掩膜操作的源代码:

#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<iostream>
#include<stdio.h>
using namespace cv;
using namespace std;
Mat Myfilter2D(Mat &srcImage)
{
	const int nChannels = srcImage.channels();//获取图像的通道数,灰度图是1通道,彩色图是3通道
	int nRows = srcImage.rows;
	int nCols = (srcImage.cols-1) * nChannels;//因为掩膜的时候最后一列没有掩膜到,所以减少一列
	int offset = nChannels;
	Mat resultImage(srcImage.size(), srcImage.type());
	//对图像进行掩膜,但是上下左右各都少了一行没有处理
	for (int i = 1; i < (nRows - 1); i++)
	{
		//获取邻域指针
		const uchar* previous = srcImage.ptr<uchar>(i - 1);//上一行的指针
		const uchar* current = srcImage.ptr<uchar>(i);//当前行的指针
		const uchar* next = srcImage.ptr<uchar>(i + 1);//下一行的指针
		uchar* output = resultImage.ptr<uchar>(i);//输出图像当前行的指针
		for (int j = offset; j < nCols; j++)//如果是多通道的话,每一个通道都进行掩膜
		{
			output[j] = saturate_cast<uchar>(5 * current[j] - (current[j - offset] + current[j + offset] + previous[j] + next[j]));
		}
	}

	//对图像的边界进行处理,因为边界没有掩膜到所以和原图的像素值一样
	//先处理上下
	const uchar* src_top= srcImage.ptr<uchar>(0);//原图的第0行的指针
	uchar* output_top = resultImage.ptr<uchar>(0);//输出图像的第0行指针
	const uchar* src_buttom = srcImage.ptr<uchar>(srcImage.rows-1);//原图的最后一行的指针
	uchar* output_buttom = resultImage.ptr<uchar>(resultImage.rows-1);//输出图像的最后一行指针
	for (int i = 0; i < nChannels * srcImage.cols; ++i) 
	{
		output_top[i] = src_top[i];
		output_buttom[i] = src_buttom[i];
	}

	//在处理左右
	for (int i = 1; i < srcImage.rows; ++i) 
	{
		const uchar* src_left = srcImage.ptr<uchar>(i);//原图第一行的指针
		uchar* output_left = resultImage.ptr<uchar>(i);//输出图第一行的指针
		const uchar* src_right = src_left + nChannels*(srcImage.cols - 1);
		uchar* output_right = output_left + nChannels*(resultImage.cols - 1);
		for (int j = 0; j < nChannels; ++j)
		{
			output_left[j] = src_left[j];
			output_right[j] = src_right[j];
		}
	}
	return resultImage;
}
int main()
{
	Mat srcImage = imread("flower.jpg");
	if (!srcImage.data)
	{
		printf("could not load image...\n");
		return -1;
	}
	imshow("srcImage", srcImage);

	Mat srcGray;
	cvtColor(srcImage, srcGray, CV_BGR2GRAY);
	imshow("srcGray", srcGray);

	Mat reultImage1 = Myfilter2D(srcImage);//原图掩膜的结果
	Mat reultImage2 = Myfilter2D(srcGray);//灰度图掩膜的结果
	imshow("res1", reultImage1);
	imshow("res2", reultImage2);
	waitKey(0);
	return 0;
}

原图与效果图:


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值