一、濾波器實現
我們實現這樣一個基於拉普拉斯算子的濾波器核心,並使用它進行濾波,這可以做到銳化圖像的效果,
| 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);
結果一樣,


