#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