一、滤波器实现
我们实现这样一个基于拉普拉斯算子的滤波器核心,并使用它进行滤波,这可以做到锐化图像的效果,
0 | -1 | 0 |
-1 | 5 | -1 |
0 | -1 | 0 |
首先我们完全手动的进行滤波,依赖指针操作,
void sharpen(const cv::Mat &image, cv::Mat &result) { result.create(image.size(), image.type()); std::cout << image.size() << std::endl; int col = image.cols; int row = image.rows; int channels = image.channels(); for (int i = 1; i < row - 1; i++ ) { // 必须添加const,因为image是const的 const uchar* previous_row = image.ptr<uchar>(i - 1); const uchar* current_row = image.ptr<uchar>(i); const uchar* next_row = image.ptr<uchar>(i + 1); uchar* out_line = result.ptr<uchar>(i); for (int j = channels; j < (col - 1)*channels; j++) { // cv::saturate_cast<uchar>将输入截断在0到255 *out_line++ = cv::saturate_cast<uchar>( 5 * current_row[j] - current_row[j - channels] - current_row[j + channels] - previous_row[j] - next_row[j]); } } result.row(0).setTo(cv::Scalar(0,0,0)); result.row(row - 1).setTo(cv::Scalar(0, 0, 0)); result.col(0).setTo(cv::Scalar(0, 0, 0)); result.col(col - 1).setTo(cv::Scalar(0,0,0)); }
OpenCV提供了cv::filter2D函数,当我们指定滤波核(一个Mat格式数据)可以自动代我们完成循环过程,依赖API实现本函数如下:
void sharpen2D(const cv::Mat image, cv::Mat &result) { cv::Mat kernel(3, 3, CV_32F, cv::Scalar(0)); kernel.at<float>(1, 1) = 5; kernel.at<float>(0, 1) = -1; kernel.at<float>(1, 0) = -1; kernel.at<float>(2, 1) = -1; kernel.at<float>(1, 2) = -1; cv::filter2D(image, result, image.depth(), kernel); }
对两个版本函数都进行调用,
cv::Mat image = cv::imread("test.jpg"); std::cout << (int)image.data << std::endl; // 自行锐化滤波 cv::Mat image1; sharpen(image, image1); show(image1, "锐化"); cv::Mat image2; sharpen2D(image, image2); show(image2, "API锐化");
查看输出(可右键查看大图),
原图如下:
二、高斯滤波
OpenCV将大部分常用滤波函数进行封装,资料很多,自行查阅。其中高斯核函数多提一句,它是可拆分核函数,一个二维核可以拆解为两个一维核,我们既可以这样调用:
cv::GaussianBlur( image, result, cv::Size(5, 5), // 窗口大小 1.5 // sigma );
也可以这样调用,
cv::Mat gauss = cv::getGaussianKernel(5, 1.5, CV_32F); cv::sepFilter2D(image, result, -1, gauss, gauss); // -1代表输入图深度 cv::imshow("双一维高斯滤波", result);
结果一样,