当前位置: 首页 > news >正文

opencv 学习: 09 邻近像素处理,以高通滤波图片锐化为例

1.说明

在图像处理中,经常需要根据相邻像素值来计算当前像素值。

比如下面表格为例,计算 (1,1) 位置的这个像素值,需要参考它周边相邻这一圈的,不同行或列的像素的值。

0,00,10,2
1,01,11,2
2,02,12,2

具体的,以图像锐化为例子,进行说明;其中用到了 “拉普拉斯算子”,这里先不深入原理细节,在后面的部分补充。

图像锐化:

就是图像中边缘对比度增加,使得交界变得明显,锐利,细节增加。

适度锐化,可以消除一些模糊,增强一些边界信息。

过度锐化,会使得细节信息变得过度突出,反而引入噪声和伪影。

拉普拉斯算子:

[ 0, -1, 0]
[-1, 5, -1]
[ 0, -1, 0]

简化成式子就是:

当前像素新值 = 当前像素值 * 5 - 上下左右四个相邻像素值

另外,因为图像边缘的行和列没有完整的四个相邻的像素,所以不做处理。

2.实现代码

#include <iostream>
#include <opencv2/opencv.hpp>
#include <chrono>//at方式实现,效率低,但是直观一些
//也限制为彩色图片,主要为了说明计算过程
void sharpen_v1(const cv::Mat& origin, cv::Mat& result)
{//分配结果图片空间//当为同源图片时,会直接返回,引用同一张图片数据,修改原图result.create(origin.size(), origin.type());//遍历行,跳过第一行,最后一行for (size_t i = 1; i < (origin.rows-1); i++){//遍历列,跳过第一列和最后一列for (size_t j = 1; j < (origin.cols-1); j++){//当前像素cv::Vec3b* pixel = result.ptr<cv::Vec3b>(i, j);
#if 0  //有问题版本//原图中像素,及其相邻像素值//不能这么直接用Vec3b,因为cv::Vec3b 是 3个uchar 组成的,//5*pixel_center 会溢出,截取溢出剩余的值进行计算cv::Vec3b pixel_center = origin.at<cv::Vec3b>(i, j);cv::Vec3b pixel_up = origin.at<cv::Vec3b>(i-1, j);cv::Vec3b pixel_down = origin.at<cv::Vec3b>(i+1, j);cv::Vec3b pixel_left = origin.at<cv::Vec3b>(i, j-1);cv::Vec3b pixel_right = origin.at<cv::Vec3b>(i, j+1);#else  //正确版本//原图中像素,及其相邻像素值//cv::Vec3s 是 3个short 组成的,不会溢出,计算完成再转换为uchar,  当然如果算子过大,也可能会溢出cv::Vec3s pixel_center = origin.at<cv::Vec3b>(i, j);cv::Vec3s pixel_up = origin.at<cv::Vec3b>(i-1, j);cv::Vec3s pixel_down = origin.at<cv::Vec3b>(i+1, j);cv::Vec3s pixel_left = origin.at<cv::Vec3b>(i, j-1);cv::Vec3s pixel_right = origin.at<cv::Vec3b>(i, j+1);
#endif//pixel_center 等为,cv::Vec3s 时将结果做个隐式转换*pixel = 5 * pixel_center - pixel_up - pixel_down - pixel_left - pixel_right;}}
}//指针方式实现,效率高
void sharpen_v2(const cv::Mat& origin, cv::Mat& result)
{//分配结果图片空间//当为同源图片时,会直接返回,引用同一张图片数据,修改原图result.create(origin.size(), origin.type());int nchannels = origin.channels();//遍历行,跳过第一行,最后一行for (int j = 1; j < origin.rows - 1; j++){const uchar *previous = origin.ptr<const uchar>(j - 1); // previous rowconst uchar *current = origin.ptr<const uchar>(j); // current rowconst uchar *next = origin.ptr<const uchar>(j + 1); // next rowuchar *output = result.ptr<uchar>(j); // output row//遍历列,跳过第一列和最后一列for (int i = nchannels; i < (origin.cols - 1) * nchannels; i++){//current[i - nchannels]: 当前像素左侧像素对应通道值//current[i + nchannels]:当前像素右侧像素对应通道值//previous[i]:当前像素上一行像素对应通道值//next[i]:当前像素下一行像素对应通道值*output = cv::saturate_cast<uchar>( 5 * current[i] - current[i - nchannels] -current[i + nchannels] - previous[i] - next[i]);output++;}}
}int main(int argc, char *argv[])
{// 检查命令行参数if (argc != 3){std::cerr << "Usage: " << argv[0] << " <input_image> <output_image>" << std::endl;return -1;}// 读取输入图像和logo图像cv::Mat input_image = cv::imread(argv[1]);// 检查输入图像和logo图像是否成功读取if (input_image.empty()){std::cerr << "Error: Could not open or find input image" << std::endl;}cv::namedWindow("input_image", cv::WINDOW_NORMAL);cv::imshow("input_image", input_image);cv::waitKey(0);cv::Mat sharpen_image;const int64 start = cv::getTickCount();
#if 0sharpen_v1(input_image, sharpen_image);#elsesharpen_v2(input_image, sharpen_image);
#endifconst int64 end = cv::getTickCount();std::cout << "sharpen used time: " << (end - start) / cv::getTickFrequency() << "s" << std::endl;cv::imwrite(argv[2], sharpen_image);cv::namedWindow("sharpen_image", cv::WINDOW_NORMAL);cv::imshow("sharpen_image", sharpen_image);cv::waitKey(0);return 0;
}

3.执行效果

如下图:锐化后,图片的细节会增多。视觉上感受就是变清晰了。有些纹理细节也会便突出。

将GIF拖拽到单独页面,再放大查看。会比较明显,特别是中部的人物衣物纹理等。

在这里插入图片描述

4. cv::filter2D 函数

由于 滤波 (filtering)是个很常见的操作,所以 opencv 提供了一个对应的 cv::filter2D 函数。

需要先定义一个算子,然后将目标图片和算子传入,获得处理结果。重新实现的方法如下:

void sharpen_v3(const cv::Mat& origin, cv::Mat& result)
{//分配结果图片空间//当为同源图片时,会直接返回,引用同一张图片数据,修改原图result.create(origin.size(), origin.type());//定义算子cv::Mat kernel = (cv::Mat_<float>(3, 3) <<0, -1, 0,-1, 5, -1,0, -1, 0);cv::filter2D(origin, result, origin.depth(), kernel);
}
http://www.dtcms.com/a/611292.html

相关文章:

  • 湖北省建设工程造价管理协会网站优化软件
  • 建设vip网站相关视频企业营业执照
  • cnzz统计代码放在网站泉州微信网站建设
  • 算法备案全攻略:材料清单与避坑指南
  • 做外贸电商网站有哪个国家最新防疫政策
  • 诸几建设银行网站洛可可在线设计平台
  • 电子商务网站开发价格安徽工程造价信息网
  • 快看点自媒体平台网站怎样做优化
  • 微信小程序 点击某个marker改变其大小
  • 51Sim 4DGS闭环仿真架构,让基于真实数据的闭环仿真成为可能
  • 基于质谱的蛋白质组学能用来研究多肽的结构和功能吗?
  • 网站速度优化方案一般可以在哪些网站做推广
  • deep-oc-sort——yolov5/8/9/10/11/12/13+deep-oc-sort算法的目标跟踪实现
  • Gitee使用笔记
  • 看摄影作品的网站长沙seo研究中心
  • 襄樊网站制作公司怎么在阿里云建网站
  • idea2022.3.3常用配置
  • 分销小程序开发研发公司赣榆网站建设xxiaoseo
  • 让数据“开口说话”:商城大数据如何预测元器件价格波动与供应风险?
  • 尼罗发表小说做的的网站是哪个长沙关键词快速排名
  • 建立主题网站的顺序一般是西安知名网站建设公司排名
  • HTML 脚本:基础、应用与未来趋势
  • 网站建设费属于业务宣传费吗网站程序组成
  • Blazor全栈是个陷阱
  • 【多源 BFS】3.地图中的最⾼点(medium)
  • 网站建设需要学代码吗巴中企业网站建设
  • 开发网站公司交税网站建设php的心得和体会
  • 超参数调优:Grid Search 和 Random Search 的实战对比
  • 编译语言有哪些 | 探索编译语言的种类及其应用领域
  • 网站的弹窗是怎么做的ol游戏大全排行榜