OpenCV-数字图像处理之拉普拉斯算子
OpenCV-数字图像处理之拉普拉斯算子
Laplace算子和Sobel算子一样,属于空间锐化滤波操作。起本质与前面的Spatial Filter操作大同小异,下面就通过Laplace算子来介绍一下空间锐化滤波,并对OpenCV中提供的Laplacian函数进行一些说明。
- 数学原理
离散函数导数
离散函数的导数退化成了差分,一维一阶差分公式和二阶差分公式分别为,
Laplace算子的差分形式
分别对Laplace算子x,y两个方向的二阶导数进行差分就得到了离散函数的Laplace算子。
在一个二维函数f(x,y)中,x,y两个方向的二阶差分分别为,
所以Laplace算子的差分形式为,
写成filter mask的形式如下,
0 | 1 | 0 |
1 | -4 | 1 |
0 | 1 | 0 |
1 | 1 | 1 |
1 | -8 | 1 |
1 | 1 | 1 |
注:
有时我们也会见到不同于上述结果的Laplace算子的filter mask,
0 | -1 | 0 |
-1 | 4 | -1 |
0 | -1 | 0 |
-1 | -1 | -1 |
-1 | 8 | -1 |
-1 | -1 | -1 |
其原因是在定义二阶导数的时候采用了相反的定义,这个无关紧要,但是要注意,当用Laplace算子滤波后的图像与原图叠加时,混合操作是加还是减因上述的定义而异。
图像的Laplace操作
如同本文开始时说的那样,将Laplace算子写成filter mask后,其操作大同小异于其他的空间滤波操作。将filter mask在原图上逐行移动,然后mask中数值与其重合的像素相乘后求和,赋给与mask中心重合的像素,对图像的第一,和最后的行和列无法做上述操作的像素赋值零,就得到了拉普拉斯操作结果。
拉普拉斯操作结果与原图的混合
因为Laplace算子是二阶导数操作,其在强调图像素中灰度不连续的部分的同时也不在强调灰度值连续的部分。这样会产生一个具有很明显的灰度边界,但是没有足够特征的黑色背景。背景特征可以通过原图像与Laplace算子操作后的图像混合恢复。用公式,
其中的参数c的取值和上面的两种mask定义有关,当mask中心的数值取正时c=-1,相反c=1;
- 基于OpenCV的Laplace算子的计算
OpenCV中Laplacian函数可以实现对图像的Laplace操作,具体用法如下,
Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );
参数意义为,
- src_gray,输入图像
- dst,Laplace操作结果
- ddepth,输出图像深度,因为输入图像一般为CV_8U,为了避免数据溢出,输出图像深度应该设置为CV_16S
- kernel_size,filter mask的规模,我们的mask时3x3的,所以这里应该设置为3
- scale,delta,BORDER_DEFAULT,默认设置就好
基于OpenCV的Laplace算子仿真代码段如下,
//load the Original Image and get some informations Mat src = imread("012.jpg",0); namedWindow("OriginalImage"); imshow("OriginalImage",src); CV_Assert(src.depth() == CV_8U);//OpenCV solution - Laplacian Mat dst,abs_dst_laplace; Laplacian(src,dst,CV_16S,3); convertScaleAbs(dst,abs_dst_laplace);//show the result namedWindow("result_laplacian"); imshow("result_laplacian",abs_dst_laplace);
其中convertScaleAbs函数功能是将CV_16S型的输出图像转变成CV_8U型的图像。
仿真结果:
原图:
Laplace操作结果:
- 基于mask operation原理仿真
Laplace算子滤波仿真
根据数学原理中介绍的算法,编写相应代码,进行相关仿真。其中对Laplace操作结果进行了图像拉伸显示,因为Laplace操作结果的像素值范围可能落在了[0,255]之外,而计算机在显示的时候将赋值全部置为0,大于255的像素全部显示成255。
代码段如下,
//get some informations of original image int nr = src.rows; int nc = src.cols; int n = nr*nc; int arr[9] = {0};//scan the whole pixels of original image //and do Laplacian Operation int* table_lap = new int[n]; int* table_orig = new int[n]; int l; for (int i=0;i<n;i++) {table_lap[i] = 0;table_orig[i] = 0; } for (int i=1;i<nr-1;i++) {const uchar* previous = src.ptr<uchar>(i-1);const uchar* current = src.ptr<uchar>(i);const uchar* next = src.ptr<uchar>(i+1);for (int j=1;j<nc-1;j++){for (int k=0;k<3;k++){arr[k] = previous[j+k-1];arr[k+3] = current[j+k-1];arr[k+6] = next[j+k-1];}l = nc*i+j; //calculate the location in the table of current pixelLmaskoperation(table_lap,arr,l);table_orig[l] = arr[4];} }//pixels scale uchar* La_scaled = new uchar[n]; table_scale(table_lap,La_scaled,n);//padding values Mat LaResult_own; LaResult_own.create(src.size(),src.type()); uchar* p = NULL; for (int i=0;i<nr;i++) {p = LaResult_own.ptr<uchar>(i);for (int j=0;j<nc;j++){l = nc*i+j;p[j] = La_scaled[l];} }//show results namedWindow("LaResult_own"); imshow("LaResult_own",LaResult_own);
其中Lmaskoperation是我写的mask为Laplace mask的mask operation操作函数,函数段如下,
//**********************// //Laplacian mask operation //**********************// void Lmaskoperation(int* table,int* arr,int l) {int tmp[9] = {-1,-1,-1,-1,8,-1,-1,-1,-1};for (int i=0;i<9;i++){table[l] = table[l] + tmp[i]*arr[i];} }
tabel_scale函数就是我写的图像拉伸函数,将Laplace操作结果拉伸到[0,255],具体函数段如下,
//*****************************// //scale the pixels to [0 255] //*****************************// void table_scale(int* table,uchar* result,int n) {int min = table[0];int max = table[0];for (int i=0;i<n;i++){if(min>table[i]){min = table[i];}if(max<table[i]){max = table[i];}}for (int i=0;i<n;i++){result[i] = (uchar)(255*(table[i]-min)/(max-min));} }
仿真结果,拉伸后Laplace算子的操作结果
以灰色为主色调的显示结果就是Laplace算子操作拉伸后显示的一大特点。
Laplace滤波图像与原图像的混合
我使用的mask中心值为正,所以混合操作需要原图减去Laplace滤波图像,代码段如下,
//blending with the original image using Eq g(x,y)=f(x,y)+c*Lap(x,y) int* table_blend = new int[n]; for(int i=0;i<n;i++) {table_blend[i] = table_orig[i] - table_lap[i];if(table_blend[i]<0){table_blend[i] = 0;}else if (table_blend[i]>255){table_blend[i] = 255;} }//padding values to blending result Mat Blresult; Blresult.create(src.size(),src.type()); for (int i=0;i<nr;i++) {p = Blresult.ptr<uchar>(i);for(int j=0;j<nc;j++){l = nc*i+j;p[j] = table_blend[l];} }//show blending result namedWindow("blending result_laplacian"); imshow("blending result_laplacian",Blresult);
仿真结果:
最后给出冈萨雷斯在介绍Laplacian时所给素材的仿真结果
转载自:https://www.cnblogs.com/german-iris/p/4840647.html
OpenCV-数字图像处理之拉普拉斯算子相关推荐
- 数字图像处理之拉普拉斯算子
OpenCV-跟我一起学数字图像处理之拉普拉斯算子 Laplace算子和Sobel算子一样,属于空间锐化滤波操作.起本质与前面的Spatial Filter操作大同小异,下面就通过Laplace算子来 ...
- OpenCV数字图像处理基于C++:灰度变换
OpenCV数字图像处理基于C++:灰度变换 1.1 灰度变换概念 在图像预处理中,图像的灰度变换是图像增强的重要手段,灰度变换可以使图像对比度扩展,图像清晰,特征明显,灰度变换主要利用点运算来修正像 ...
- OpenCV数字图像处理学习平台
原始图像1-1 处理中的图像1-2 处理结果1-3(检测到所有圆) OpenCV数字图像处理学习平台,是一款可视化.交互式方式学习OpenCV的工具软件,由资深计算机视觉专家精心打造,花费近两年整理成 ...
- 《opencv 数字图像处理 图像基础》
<opencv 数字图像处理 图像基础> 矩阵 通道分离和合并 彩色图像转灰度图像 灰度图转二值化图像 图像运算 矩阵 定义一个显示图像的函数,对于灰度图,里面添加了vmin=0,vmax ...
- c++ opencv数字图像处理:访问图像像素,遍历图像像素
文章目录 前言 一.访问图像像素 1.访问(j,i)处像素 2.例子:在图像中加入白色椒盐噪声 二.遍历图像像素 1.指针扫描 2.opencv自带的卷积运算:filter2D 前言 数字图像处理c+ ...
- c++ opencv数字图像处理:频率域滤波--高通滤波--高斯高通滤波
文章目录 前言 一.高斯高通滤波器(GHPF) 二.代码 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.高斯高通滤波器(GHPF) D 2 ( u , v ...
- c++ opencv数字图像处理:频率域滤波--低通滤波--理想低通滤波
文章目录 前言 一.理想低通滤波器(ILPF) 二.代码 三.说明 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.理想低通滤波器(ILPF) 通过设置频率半 ...
- c++ opencv数字图像处理:频率域滤波--低通滤波--巴特沃斯低通滤波
文章目录 前言 一.巴特沃斯低通滤波器(BLPF) 二.代码 三.说明 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.巴特沃斯低通滤波器(BLPF) D2( ...
- c++ opencv数字图像处理:频率域滤波--高通滤波--巴特沃斯高通滤波
文章目录 前言 一.巴特沃斯高通滤波器(BHPF) 二.代码 前言 数字图像处理c++ opencv(VS2019 opencv4.53)持续更新 一.巴特沃斯高通滤波器(BHPF) D2(u,v)为 ...
最新文章
- VS2008显示代码行号
- HarmonyOS之深入解析通知的使用
- python卡尔曼滤波跟踪_使用卡尔曼滤波器以圆周运动跟踪机器人
- android dialog加载中动画效果
- opencv 多线程加速_线程池给你写好了,想加速拿来用就行哈
- SQL取最大值编码(自动编码)
- 三星手机 java_如何在三星手机上安装Java ME应用程序?
- e-Learning案例分享(一)
- exe机器码加密视频如何破解提取脱壳
- 任务调度ScheduledExecutorService
- PMP是什么?PMP证书在国用处大吗?
- linux docker安装 制作Elasticsearch容器镜像 并上传docker hub
- 基于双月数据集利用感知层进行分类
- 使用Docker提交代码参加天池比赛流程
- HDFS物理块存储大小
- 流行的ORM框架简介
- 大数据面试题(一)----HADOOP 面试题
- 自动识别图片验证码登录
- SDK对于APP主流量变现意味着什么?
- 盛大游戏面试题目小结
热门文章
- JavaScript性能优化【上】-- 内存管理、垃圾回收
- css flex 小记
- C do...while 循环
- C#LeetCode刷题-贪心算法
- 面向对象设计原则之5-接口隔离原则
- seo外链重要性_为什么网站速度对于SEO至关重要?以及如何加快网站速度
- django 部署_狂野的Django:部署生存的技巧
- 如果我用你待我的方式来待你 恐怕你早已离去
- oracle批量插入报错,[数据库]Mybatis 批量插入数据 关于Oracle 批量插入报错:ORA
- 安装低版本的R语言、和自行下载安装各个版本的R语言包、以及多环境运行R