扫描图像并访问相邻像素
在图像处理中经常有这样的处理函数,他在计算每个像素的数值时,需要使用周边像素的值,如果相邻像素在上一行或下一行,就需要同时扫描图像的多行。
这里使用一个锐化图像的处理函数。他基于拉普拉斯算子。
在图像处理领域有一个众所周知的结论:如果从图像中减去拉普拉斯算子部分,图像的边缘就会放大,因而图像会变得更加尖锐
效果:
代码:
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
void sharpen(const cv::Mat &image, cv::Mat &result){
// 判断是否需要分配图像数据。如果需要,就分配
result.create(image.size(),image.type());
int nchannels = image.channels(); // 获取通道数
// 处理所有行(除了第一行和最后一行)
for (int j=1; j<image.rows-1; j++){
const uchar* previous = image.ptr<const uchar>(j-1); // 上一行
const uchar* current = image.ptr<const uchar>(j); // 当前行
const uchar* next = image.ptr<const uchar>(j+1); // 下一行
uchar* output = result.ptr<uchar>(j); // 输出行
for (int i=nchannels; i<(image.cols - 1)*nchannels; i++){
// 应用锐化算子
*output++ = cv::saturate_cast<uchar>(
5*current[i] - current[i-nchannels] -
current[i+nchannels] - previous[i] - next[i]);
}
}
// 把未处理的像素设为0
result.row(0).setTo(cv::Scalar(0));
result.row(result.rows - 1).setTo(cv::Scalar(0));
result.col(0).setTo(cv::Scalar(0));
result.col(result.cols - 1).setTo(cv::Scalar(0));
// ******注意这个函数是如何同时适应灰度图像和彩色图像的。
}
int main()
{
cv::Mat image = cv::imread("/home/jason/work/01-img/dog.png");
const int64 start = cv::getTickCount();
cv::Mat result;
sharpen(image, result);
// 经过的时间 (单位:秒)
double duration = (cv::getTickCount() - start)/
cv::getTickFrequency();
std::cout << "duration: " << duration * 1000 << "ms" << "\n";
cv::imshow("dog", image);
cv::imshow("result",result);
cv::waitKey(0);
return 0;
}