OpenCV_tutorials 02 core module-Mask operations on matrices

#include<iostream>

#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

void sharpen(const Mat &src, Mat &dst);
void sharpenByfilter2D(const Mat &src, Mat &dst);

int main()
{
	Mat src = imread("C:\\Users\\dell\\Desktop\\xin1.jpg", 1);
	if (src.empty())
	{
		cout << "Source image load failed." << endl;
		return -1;
	}
	Mat dst1;
	sharpen(src, dst1);
	Mat dst2;
	sharpenByfilter2D(src, dst2);
	return 0;
}

//The Basic method to use mask operation on matrix
void sharpen(const Mat &src, Mat &dst)
{
	double t = (double)getTickCount();

	//accept only uchar images
	CV_Assert(src.depth() == CV_8U);

	dst.create(src.size(), src.type());
	const int nchannels = src.channels();

	for (int i = 1; i < src.rows - 1; i++)
	{
		const uchar *pPrevious = src.ptr<uchar>(i - 1);
		const uchar *pCurrent = src.ptr<uchar>(i);
		const uchar *pNext = src.ptr<uchar>(i + 1);

		uchar *pDst = dst.ptr<uchar>(i);
		for (int j = nchannels; j < (src.cols - 1) * nchannels; j++)
		{
			//pDst[j] = 5 * pCurrent[j] - (pCurrent[j - 1] + pCurrent[j + 1] + pPrevious[j] + pNext[j]);	//错误,要考虑三通道情况
			//pDst[j] = 5 * pCurrent[j] - (pCurrent[j - nchannels] + pCurrent[j + nchannels] + pPrevious[j] + pNext[j]);//考虑值超出uchar范围情况
			pDst[j] = saturate_cast<uchar>(5 * pCurrent[j] - (pCurrent[j - nchannels] + pCurrent[j + nchannels] + pPrevious[j] + pNext[j]));
		}
	}

	dst.row(0).setTo(Scalar(0));
	dst.row(src.rows - 1).setTo(Scalar(0));
	dst.col(0).setTo(Scalar(0));
	dst.col(src.cols - 1).setTo(Scalar(0));

	double tt = ((double)getTickCount() - t) / getTickFrequency();
	cout << "The basic method cost time : " << tt << "s." << endl;
}

//Use filter2D function
void sharpenByfilter2D(const Mat &src, Mat &dst)
{
	//double t = (double)getTickCount();

	CV_Assert(src.depth() == CV_8U);

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

	double t = (double)getTickCount();
	filter2D(src, dst, src.depth(), kern);

	double tt = ((double)getTickCount() - t) / getTickFrequency();
	cout << "The filter2D function cost time : " << tt << "s." << endl;
}

1.需要注意的几个问题,都是自己踩过的坑,采坑的好处之一就是增加自己的思考,而不是只是凭记忆敲代码。

(1)我一开始写的pDst[j] = 5 * pCurrent[j] - (pCurrent[j - 1] + pCurrent[j + 1] + pPrevious[j] + pNext[j]); 这句话只考虑了单通道的情况,没有考虑三通道的情况。我输入的原图是一幅彩色图,按照这种错误的方式会得下列效果


原图


pDst[j] = 5 * pCurrent[j] - (pCurrent[j - 1] + pCurrent[j + 1] + pPrevious[j] + pNext[j]);产生的效果图

(2)对上述问题进行修改之后,我改成pDst[j] = 5 * pCurrent[j] - (pCurrent[j - nchannels] + pCurrent[j + nchannels] + pPrevious[j] + pNext[j]);但是这句话依然有问题,在GAKKI的眼睛和嘴巴处出现奇怪的像素点,为什么会出现少数点的异常情况,因为按照pDst[j] = 5 * pCurrent[j] - (pCurrent[j - nchannels] + pCurrent[j + nchannels] + pPrevious[j] + pNext[j])求像素点的值会出现某些点超出uchar类型的值的范围(0-255),对于超出范围的点就会显示的很奇怪了。


超出uchar值范围的点异常

为了解决这个值超过范围的异常,可以使用saturate_cast,修改之后pDst[j] = saturate_cast<uchar>(5 * pCurrent[j] - (pCurrent[j - nchannels] + pCurrent[j + nchannels] + pPrevious[j] + pNext[j]));这才能得到正确的结果


2.边界的处理

(1)对于方法1中对边界的处理非常简单粗暴:

dst.row(0).setTo(Scalar(0));
dst.row(src.rows - 1).setTo(Scalar(0));
dst.col(0).setTo(Scalar(0));

dst.col(src.cols - 1).setTo(Scalar(0));

效果:


可以看到,图像中第一行、最后一行,第一列、最后一列的像素点的三个通道像素值都被置0.

(2)filter2D默认的边界处理方式是怎么样的?


通过查看源码可以发现默认的边界处理方式是BORDER_REFLECT_101:   gfedcb|abcdefgh|gfedcba

原图边界:


将gfedcb|abcdefgh|gfedcba这种扩展方式应用在此测试原图上就是:


所以,最后的边界效果:


学习博客:

https://blog.csdn.net/zouxy09/article/details/49080029

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值