2019-04-02 22:49:25 weixin_43227685 阅读数 688

拉普拉斯变换提取图像边缘(用OpenCV库实现)

  • 对于二维图像 f(x,y)f(x,y) ,二阶微分最简单的定义–拉普拉斯算子定义为:
    在这里插入图片描述
    对于任意阶微分算子都是线性算子,所以二阶微分算子和后面的一阶微分算子都可以用生成模板然后卷积的方式得出结果。 根据前面对二阶微分的定义有:
    在这里插入图片描述
    在这里插入图片描述
    根据上面的定义,与拉普拉斯算子的定义相结合,得到:
    在这里插入图片描述
    最后的锐化公式:
    在这里插入图片描述
    g是输出,f为原始图像,c是系数,也就是要加上多少细节的多少,先提取细节,然后再加(或者减去负细节)到原图中。 选取的模板:
    在这里插入图片描述
  • 进行增强时,算子模板中心是正:原图+边缘图;算子模板中心是负:原图-边缘图。
  • 算子模板中心若是5或9,(即4+1、8+1),不是换了算子模板,是同时做了2步:提取边缘图+和原图叠加,就是直接得到用拉普拉斯算子锐化之后的图。
  • 4、8——边缘提取器;5、9——锐化滤波器。

代码:

#include <opencv2/highgui/highgui.hpp>      
#include <opencv2/imgproc/imgproc.hpp>  
#include <iostream>  
  
using namespace cv;  
  
int main(int argc, char *argv[])  
{  
    Mat image = imread("Test2.jpg", 1);  
    if (image.empty())  
    {  
        std::cout << "打开图片失败,请检查" << std::endl;  
        return -1;  
    }  
    imshow("原图像", image);  
    Mat imageEnhance;  
    Mat kernel = (Mat_<float>(3, 3) << -1,-1,-1,-1,8,-1,-1,-1,-1);  
    filter2D(image, imageEnhance, CV_8UC3, kernel);  
	imshow("提取边界", imageEnhance);  
	Mat imageEnhance2 = image + imageEnhance;
    imshow("锐化效果", imageEnhance2);  
    waitKey();  
    return 0;  
}  

运行效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2015-10-27 11:24:42 gdut2015go 阅读数 1045

opencv-第六章-拉普拉斯变换和canny算子

opencv的拉普拉斯函数实现了拉普拉斯算子的离散模拟。因为拉普拉斯算子可以用二次导数的形式定义,可假设其离散实现类似于二阶sobel导数。事实的确如此,opencv在计算拉普拉斯算子时直接使用sobel算子。


void cvLaplace(const CvArr* src, CvArr* dst, int apertureSize=3);

cvLaplace函数通常把源图像和目标图像以及中孔大小作为变量。源图像既可以是8位(无符号)图像,也可以是32位(浮点)图像。而目标图像必须是16位(有符号)或者32位(浮点)图像。这里的中孔与sobel导数中出现的中孔完全一样,事实上主要给出区域大小,在二次求导的计算中,采样这个区域的像素。


拉普拉斯算子可用于各种情况。一个通常的应用是检测“团块”。联想到拉普拉斯算子的形式是沿着x轴和y轴的二次导数的和,这就意味着周围是更高值的单点或者小块(比中孔小)会将使这个函数值最大化。反过来说,周围是更低值的点将会使函数的负值最大化。


基于这种思想,拉普拉斯算子也可以用作边缘检测。为达此目的,只需要考虑当函数快速变化时其一阶导数变大即可。同样重要的是,当我们逼近类似边缘的不连续地方时导数会快速增长,而穿过这些不连续地方时导数又会快速减小。所以导数会在此范围内有局部极值。这样我们可以期待局部最大值位于二阶导数为0的地方。

原始图像的边缘位于拉普拉斯的值等于0的地方。不幸的是,在拉普拉斯算子中,所有实质性的和没有意义的边缘的检测都是0.但这并不是什么问题,因为我们可以过滤掉这些点,它们的一阶(sobel)导数值也很大。


canny算子

canny边缘检测法把以上的描述完善了。首先在x和y方向求一阶导数,然后组合为4个方向的导数。这些方向导数达到局部最大值的点就是组成边缘的候选点。

然而,canny算法最重要的一个新特点是试图将独立边的候选像素拼接成轮廓。轮廓的形成是对这些像素运用滞后性阈值。这意味着有两个阈值,上限和下限。如果一个像素的梯度大于上限阈值,则被认为是边缘像素,如果低于下限阈值,则被抛弃,如果介于二者之间,只有当其与高于上限阈值的像素连接时才会被接受。canny推荐的上下限阈值比为2:1到3:1之间。


void cvCanny(const CvArr* img, CvArr* edges, double lowThresh, 

double highThresh, int apertureSize=3);

cvCanny函数需要输入一幅灰度图,输出图也一定是灰度的(实际上是布尔图像)。接下来两个参数是下限阈值与上限阈值,最后一个参数是另一个中孔。通常,这个被sobel算子用到的中孔是cvCanny在内部使用的。





2018-10-27 17:10:52 qq_33835307 阅读数 382
2017-04-04 19:07:22 u013108511 阅读数 8683

博客用于知识记录和学习交流,欢迎大家互动学习。
作者:JackGao16 CSDN文章链接:http://blog.csdn.net/u013108511/article/details/69148804
邮箱:gshuai16@mail.ustc.edu.cn

1、拉普拉斯变换锐化图像的原理

拉普拉斯锐化图像是根据图像某个像素的周围像素到此像素的突变程度有关,也就是说它的依据是图像像素的变化程度。我们知道,一个函数的一阶微分描述了函数图像是朝哪里变化的,即增长或者降低;而二阶微分描述的则是图像变化的速度,急剧增长下降还是平缓的增长下降。那么据此我们可以猜测出依据二阶微分能够找到图像的色素的过渡程度,例如白色到黑色的过渡就是比较急剧的。

或者用官方点的话说:当邻域中心像素灰度低于它所在的领域内其它像素的平均灰度时,此中心像素的灰度应被进一步降低,当邻域中心像素灰度高于它所在的邻域内其它像素的平均灰度时,此中心像素的灰度应被进一步提高,以此实现图像的锐化处理。

下面我们来推导二阶微分和像素的关系:
这里写图片描述
一阶微分可以检测边缘是否存在。

那么二阶微分,也就是拉普拉斯算子就可以确定边缘位置。

拉普拉斯掩膜重心系数:
这里写图片描述
这样就可以找到一个四邻域矩阵的模板:
这里写图片描述

而八邻域的表示方法以及二阶微分表示如下:
这里写图片描述
这样可以找到一个八邻域的矩阵的模板:
这里写图片描述

将算得的值替换原(x,y)处的像素值,可以得到类似边界的地方,然后根据下式得到锐化图像:
这里写图片描述

2、C++代码

这里只是处理单通道的灰度图像,彩色的三通道的图像同理。

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<cv.h>
using namespace cv;

//拉普拉斯锐化图像
IplImage *Laplacian_cx(IplImage *src){
    IplImage *dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,0);
    cvLaplace(src,dst);
    return dst;
}

int main(){
    IplImage * srcImage = cvLoadImage("pic3.jpg",0);

    //窗口定义函数
    cvNamedWindow("源灰度图像",CV_WINDOW_AUTOSIZE);
    //显示源图像
    cvShowImage("源灰度图像",srcImage);

    //显示Laplace变换后的灰度图像
    cvNamedWindow("Laplacian变换后的灰度图像",CV_WINDOW_AUTOSIZE);
    cvShowImage("Laplacian变换后的灰度图像",Laplacian_cx(srcImage));

    // 等待60000 ms后窗口自动关闭  
    waitKey(60000);  

}

直接调用了库函数cvLaplace(src,dst)

3、结果显示

这里写图片描述

解释原理处参考学习了该地址下的博客:http://blog.csdn.net/zb1165048017/article/details/49330171
使用matlab的朋友可以看一看。

我是Jack,学无止境。

2017-08-01 17:48:00 weixin_30376509 阅读数 20

一、引言

       图像锐化处理的作用是使灰度反差增强,从而使模糊图像变得更加清晰。图像模糊的实质就是图像受到平均运算或积分运算,因此可以对图像进行逆运算,如微分运算能够突出图像细节,使图像变得更为清晰。由于拉普拉斯是一种微分算子,它的应用可增强图像中灰度突变的区域,减弱灰度的缓慢变化区域。

二、卷积算法

2.1卷积原理

          因此,锐化处理可选择拉普拉斯算子对原图像进行处理,产生描述灰度突变的图像,再将拉普拉斯图像与原始图像叠加而产生锐化图像。此原理实际为卷积操作,也可以理解为一种图像变换,最常见的图像变换(image transform,即将一幅图像转变成图像数据)就是傅里叶变换(Fourier transform),即将图像转换成源图像数据的另一种表示,而卷积是大多数变换的基础。

我们可以用方程来表示这个过程。我们首先定义图像为I(x,y),核为G(x,y),

参考点位于相应核的(ai,aj)坐标上,则卷积H(x,y)定义如下:

边缘部分使用复制处理,计算方法如下图所示:

2 .2 opencv卷积函数说明

void cvFilter2D( const CvArr* src, CvArr* dst,  const CvMat* kernel,  CvPoint  chor=cvPoint(-1,-1));
src:输入图像
dst:输出图像
kernel:卷积核, 单通道浮点矩阵. 如果想要应用不同的核于不同的通道,先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理。
anchor:核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。

其实在利用此卷积函数是,根据核的不同可以产生各种的图像处理,比如:

[转载]卷积滤波模板

#include <iostream>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/core/core.hpp>  
#include <opencv/cv.hpp>  
  
using namespace std;  
using namespace cv;  
int main()  
{  
    string picName="lena.jpg";  
    Mat A=imread (picName,CV_LOAD_IMAGE_COLOR);  
      
    Mat mask=(Mat_<char>(3,3)<<0,-1,0,   -1,5,-1,    0,-1,0);    
      
    Mat B;  
    filter2D (A,B,A.depth (),mask);  
      
    imshow("A的图像",A);  
    imshow("B的图像",B);  
      
    waitKey ();  
    return 0;  
}

20131110141151937

三、拉普拉斯算法

3.1 拉普拉斯原理说明

        普拉斯算子是最简单的各向同性微分算子,具有旋转不变性。一个二维图像函数 的拉普拉斯变换是各向同性的二阶导数,定义为:

165749739.jpg?_=1939020

      在一个二维函数f(x,y)中,x,y两个方向的二阶差分分别为,

CodeCogsEqn(3)

CodeCogsEqn(4)

       为了更适合于数字图像处理,将该方程表示为离散形式:

165821853.jpg?_=1939020

写成filter mask的形式如下,

165916806.jpg?_=1939020


        注意该(a)的mask的特点,mask在上下左右四个90度的方向上结果相同,也就是说在90度方向上无方向性。为了让该mask在45度的方向上也具有该性质,对该filter mask进行扩展定义为(b)。

         将Laplace算子写成filter mask后,其操作大同小异于其他的空间滤波操作。将filter mask在原图上逐行移动,然后mask中数值与其重合的像素相乘后求和,赋给与mask中心重合的像素,对图像的第一,和最后的行和列无法做上述操作的像素赋值零,就得到了拉普拉斯操作结果。

3.2 opencv函数应用

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,默认设置就好
//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);

original810956-20150926131143569-1606809590.jpg

上图中上图为原图像,有图为拉普拉斯之后的图像。


转载于:https://www.cnblogs.com/polly333/p/7269843.html

没有更多推荐了,返回首页