用sobel求图像sobel算子梯度 matlab,图像的边角处的sobel算子梯度 matlab怎么处理

拉普拉斯算子、prewitt算子、sobel算子对图像锐化处理_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
拉普拉斯算子、prewitt算子、sobel算子对图像锐化处理
上传于||文档简介
&&数​字​图​像​处​理​课​程​要​求​对​以​上​三​种​算​子​利​用​M​A​T​L​A​B​软​件​编​写​程​序​进​行​仿​真​实​现​,​并​加​以​性​能​分​析​、​对​比​,​完​成​本​次​课​程​设​计​论​文
阅读已结束,如果下载本文需要使用2下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩4页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢opencv中如何用sobel得到边缘的各个点的梯度_百度知道
opencv中如何用sobel得到边缘的各个点的梯度
3)得到所有点的梯度,如何获得边缘各个点的梯度sobel(src,1,dst,0
提问者采纳
你要把边缘提取出来啊
不是,我已经用canny算子提取了,只是要求得边缘上每个点的切线,想用sobel得到每点的dx,dy,然后用dy/dx得到斜率
看边缘的情况了,一般从图像提取的边缘都很复杂,这样得到的斜率不是太好如果要求不高,你可以用边缘上某点的前后两点来近似获得斜率
我一开始就是用前后两点来近似获得斜率的,这样有些数值与资料上的不符,就想说用sobel,但是好像得到的结果差值更大
图片贴一下看看
其他类似问题
为您推荐:
opencv的相关知识
其他1条回答
你这段程序有三个bug,都改好了. 你这50分还真难拿.. 自己比较一下吧,有不懂的再问:-)
blood = imread('test.jpg');
[x,y,z]=size(blood);
% 求出图象大小
b=double(blood);
N =sqrt(100) * randn(x,y,z);
生成方差为10的白噪声
噪声干扰图象
% 实际图象的灰度为0~255
if (I(i,j)&255)
I(i,j)=255;
if (I(i,j)&0)
z0=max(max(I));
% 求出图象中最大的灰度
z1=min(min(I));
% 最小的灰度
T=(z0+z1)/2;
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁3651人阅读
OpenCV(80)
梯度、边缘和角点
使用扩展 Sobel 算子计算一阶、二阶、三阶或混合图像差分
void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );
src 输入图像. dst 输出图像. xorder x 方向上的差分阶数 yorder y 方向上的差分阶数 aperture_size 扩展 Sobel 核的大小,必须是 1, 3, 5 或 7。 除了尺寸为 1, 其它情况下, aperture_size &aperture_size 可分离内核将用来计算差分。对 aperture_size=1的情况, 使用 3x1 或 1x3 内核(不进行高斯平滑操作)。这里有一个特殊变量 CV_SCHARR (=-1),对应 3x3 Scharr 滤波器,可以给出比 3x3 Sobel 滤波更精确的结果。Scharr 滤波器系数是:
对 x-方向 以及转置矩阵对 y-方向。
函数 cvSobel 通过对图像用相应的内核进行卷积操作来计算图像差分:
由于Sobel 算子结合了 Gaussian 平滑和微分,所以,其结果或多或少对噪声有一定的鲁棒性。通常情况,函数调用采用如下参数 (xorder=1, yorder=0, aperture_size=3) 或 (xorder=0, yorder=1, aperture_size=3) 来计算一阶 x- 或 y- 方向的图像差分。第一种情况对应:
第二种对应:
核的选则依赖于图像原点的定义 (origin 来自 IplImage 结构的定义)。由于该函数不进行图像尺度变换,所以和输入图像(数组)相比,输出图像(数组)的元素通常具有更大的绝对数值(译者注:即象素的深度)。为防止溢出,当输入图像是 8 位的,要求输出图像是 16 位的。当然可以用函数 cvConvertScale 或 cvConvertScaleAbs 转换为 8 位的。除了 8-比特 图像,函数也接受 32-位浮点数图像。所有输入和输出图像都必须是单通道的,并且具有相同的图像尺寸或者ROI尺寸。
计算图像的 Laplacian 变换
void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 );
src 输入图像. dst 输出图像. aperture_size 核大小 (与 cvSobel 中定义一样).
函数 cvLaplace 计算输入图像的 Laplacian变换,方法是先用 sobel 算子计算二阶 x- 和 y- 差分,再求和:
dst(x,y) = d2src/dx2 + d2src/dy2
对 aperture_size=1 则给出最快计算结果,相当于对图像采用如下内核做卷积:
类似于 cvSobel 函数,该函数也不作图像的尺度变换,所支持的输入、输出图像类型的组合和cvSobel一致。
采用Canny算法做边缘检测
void cvCanny( const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size=3 );
image 输入图像. edges 输出的边缘图像 threshold1 第一个阈值 threshold2 第二个阈值 aperture_size Sobel 算子内核大小 (见 cvSobel).
函数 cvCanny 采用 CANNY 算法发现输入图像的边缘而且在输出图像中标识这些边缘。threshold1和threshold2 当中的
小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割。
注意事项:cvCanny只接受单通道图像作为输入。
外部链接:经典的canny自调整阈值算法的一个opencv的实现见:
PreCornerDetect
计算用于角点检测的特征图,
void cvPreCornerDetect( const CvArr* image, CvArr* corners, int aperture_size=3 );
image 输入图像. corners 保存候选角点的特征图 aperture_size Sobel 算子的核大小(见cvSobel).
函数 cvPreCornerDetect 计算函数 其中
表示一阶图像差分, 表示二阶图像差分。 角点被认为是函数的局部最大值:
// 假设图像格式为浮点数 IplImage* corners = cvCloneImage(image); IplImage* dilated_corners = cvCloneImage(image);
IplImage* corner_mask = cvCreateImage( cvGetSize(image), 8, 1 ); cvPreCornerDetect( image, corners, 3 );
cvDilate( corners, dilated_corners, 0, 1 ); cvSubS( corners, dilated_corners, corners );
cvCmpS( corners, 0, corner_mask, CV_CMP_GE );
cvReleaseImage( &corners ); cvReleaseImage( &dilated_corners );
CornerEigenValsAndVecs
计算图像块的特征值和特征向量,用于角点检测
void cvCornerEigenValsAndVecs( const CvArr* image, CvArr* eigenvv, int block_size, int aperture_size=3 );
image 输入图像. eigenvv 保存结果的数组。必须比输入图像宽 6 倍。 block_size 邻域大小 (见讨论). aperture_size Sobel 算子的核尺寸(见 cvSobel).
对每个象素,函数 cvCornerEigenValsAndVecs 考虑 block_size & block_size 大小的邻域 S(p),
然后在邻域上计算图像差分的相关矩阵:
然后它计算矩阵的特征值和特征向量,并且按如下方式(&1, &2, x1, y1, x2, y2)存储这些值到输出图像中,其中
&1, &2 - M 的特征值,没有排序 (x1, y1) - 特征向量,对 &1 (x2, y2) - 特征向量,对 &2
CornerMinEigenVal
计算梯度矩阵的最小特征值,用于角点检测
void cvCornerMinEigenVal( const CvArr* image, CvArr* eigenval, int block_size, int aperture_size=3 );
image 输入图像. eigenval 保存最小特征值的图像. 与输入图像大小一致 block_size 邻域大小 (见讨论 cvCornerEigenValsAndVecs). aperture_size Sobel 算子的核尺寸(见 cvSobel). 当输入图像是浮点数格式时,该参数表示用来计算差分固定的浮点滤波器的个数.
函数 cvCornerMinEigenVal 与 cvCornerEigenValsAndVecs 类似,但是它仅仅计算和存储每个象素点差分相关矩阵的最小特征值,
即前一个函数的 min(&1, &2)
CornerHarris
哈里斯(Harris)角点检测
void cvCornerHarris( const CvArr* image, CvArr* harris_responce, int block_size, int aperture_size=3, double k=0.04 );
image 输入图像。 harris_responce 存储哈里斯(Harris)检测responces的图像。与输入图像等大。 block_size 邻域大小(见关于cvCornerEigenValsAndVecs的讨论)。 aperture_size 扩展 Sobel 核的大小(见 cvSobel)。格式. 当输入图像是浮点数格式时,该参数表示用来计算差分固定的浮点滤波器的个数。 k Harris detector free parameter. See the formula below. harris 检测器的自由参数。请看如下公式。 The function cvCornerHarris runs the Harris edge detector on image. Similarly to cvCornerMinEigenVal and cvCornerEigenValsAndVecs, for each pixel it calculates 2x2 gradient covariation matrix M over block_size&block_size neighborhood. Then, it stores
det(M) - k*trace(M)2 to the destination image. Corners in the image can be found as local maxima of the
destination image.
函数 cvCornerHarris 对输入图像进行 Harris 边界检测。类似于 cvCornerMinEigenVal 和 cvCornerEigenValsAndVecs。对每个像素,在 block_size*block_size 大小的邻域上,计算其2*2梯度共变矩阵(或相关异变矩阵)M。然后,将 det(M) - k*trace(M)2 (此公式有待考证,最后的&2&是否应为平方符号?这里2应该是平方)保存到输出图像中。输入图像中的角点在输出图像中由局部最大值表示。
FindCornerSubPix精确角点位置void cvFindCornerSubPix( const CvArr* image, CvPoint2D32f* corners, int count, CvSize win,
CvSize zero_zone, CvTermCriteria criteria );
image 输入图像. corners 输入角点的初始坐标,也存储精确的输出坐标 count 角点数目 win 搜索窗口的一半尺寸。如果 win=(5,5) 那么使用 5*2+1 & 5*2+1 = 11 & 11 大小的搜索窗口 zero_zone 死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。它是用来避免自相关矩阵出现的某些可能的奇异性。当值为 (-1,-1) 表示没有死区。 criteria 求角点的迭代过程的终止条件。即角点位置的确定,要么迭代数大于某个设定值,或者是精确度达到某个设定值。 criteria 可以是最大迭代数目,或者是设定的精确度,也可以是它们的组合。
函数 cvFindCornerSubPix 通过迭代来发现具有子象素精度的角点位置,或如图所示的放射鞍点(radial saddle points)。
子象素级角点定位的实现是基于对向量正交性的观测而实现的,即从中央点q到其邻域点p 的向量和p点处的
图像梯度正交(服从图像和测量噪声)。考虑以下的表达式:
&i=DIpiT&(q-pi)
其中,DIpi表示在q的一个邻域点pi处的图像梯度,q的值通过最小化&i得到。通过将&i设为0,可以建立系统方程如下:
sumi(DIpi&DIpiT)&q - sumi(DIpi&DIpiT&pi) = 0
其中q的邻域(搜索窗)中的梯度被累加。调用第一个梯度参数G和第二个梯度参数b,得到:
该算法将搜索窗的中心设为新的中心q,然后迭代,直到找到低于某个阈值点的中心位置。
GoodFeaturesToTrack
确定图像的强角点
void cvGoodFeaturesToTrack( const CvArr* image, CvArr* eig_image, CvArr* temp_image,
CvPoint2D32f* corners, int* corner_count, double quality_level, double min_distance, const CvArr* mask=NULL );
image 输入图像,8-位或浮点32-比特,单通道 eig_image 临时浮点32-位图像,尺寸与输入图像一致 temp_image 另外一个临时图像,格式与尺寸与 eig_image 一致 corners 输出参数,检测到的角点 corner_count 输出参数,检测到的角点数目 quality_level 最大最小特征值的乘法因子。定义可接受图像角点的最小质量因子。 min_distance 限制因子。得到的角点的最小距离。使用 Euclidian 距离 mask ROI:感兴趣区域。函数在ROI中计算角点,如果 mask 为 NULL,则选择整个图像。必须为单通道的灰度图,大小与输入图像相同。mask对应的点不为0,表示计算该点。
函数 cvGoodFeaturesToTrack 在图像中寻找具有大特征值的角点。该函数,首先用cvCornerMinEigenVal
计算输入图像的每一个象素点的最小特征值,
并将结果存储到变量 eig_image 中。然后进行非最大值抑制(仅保留3x3邻域中的局部最大值)。
下一步将最小特征值小于 quality_level&max(eig_image(x,y)) 排除掉。最后,函数确保所有发现的角点之间具有足够的距离,
(最强的角点第一个保留,然后检查新的角点与已有角点之间的距离大于 min_distance )。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1892285次
积分:21741
积分:21741
排名:第225名
原创:278篇
转载:168篇
评论:1264条
(7)(12)(10)(5)(8)(4)(1)(3)(7)(7)(3)(2)(8)(2)(2)(8)(9)(10)(4)(4)(4)(5)(4)(4)(6)(9)(12)(1)(4)(11)(4)(5)(4)(1)(1)(3)(3)(2)(1)(2)(1)(1)(2)(3)(4)(1)(2)(2)(4)(2)(4)(2)(6)(2)(5)(4)(7)(12)(9)(1)(14)(17)(11)(15)(23)(4)(11)(20)(15)(18)(17)(2)(1)(2)君,已阅读到文档的结尾了呢~~
基于形态学梯度的图像边缘检测算法(1)知识重在应用,分享产生价值。
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
基于形态学梯度的图像边缘检测算法(1)
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口图像特征提取:Sobel边缘检测
图像特征提取:Sobel边缘检测
点和线是做图像分析时两个最重要的特征,而线条往往反映了物体的轮廓,对图像中边缘线的检测是图像分割与特征提取的基础。文章主要讨论两个实际工程中常用的边缘检测算法:Sobel边缘检测和Canny边缘检测,Canny边缘检测由于算法复杂将在另一篇文章中单独介绍,文章不涉及太多原理,因为大部分的图像处理书籍都有相关内容介绍,文章主要通过Matlab代码,一步一步具体实现两种经典的边缘检测算法。
Sobel边缘检测
Soble边缘检测算法比较简,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,尤其是对效率要求较高,而对细纹理不太关心的时候。
Soble边缘检测通常带有方向性,可以只检测竖直边缘或垂直边缘或都检测。
所以我们先定义两个梯度方向的系数:
kx=0;ky=1;% horizontal kx=1;ky=0;% vertical kx=1;ky=1;% both
然后我们来计算梯度图像,我们知道边缘点其实就是图像中灰度跳变剧烈的点,所以先计算梯度图像,然后将梯度图像中较亮的那一部分提取出来就是简单的边缘部分。
Sobel算子用了一个3*3的滤波器来对图像进行滤波从而得到梯度图像,这里面不再详细描述怎样进行滤波及它们的意义等。
竖起方向的滤波器:y_mask=op = [-1 -2 -1;0 0 0;1 2 1]/8;
水平方向的滤波器:op的转置:x_mask=op’;
定义好滤波器后,我们就开始分别求垂直和竖起方向上的梯度图像。用滤波器与图像进行卷积即可:
bx = abs(filter2(x_mask,a)); by = abs(filter2(y_mask,a));
上面bx为水平方向上的梯度图像,by为垂直方向上的梯度图像。为了更清楚的说明算法过程,下面给出一张示例图像的梯度图像。
竖直方向梯度图像:by
水平方向梯度图像:bx
而最终的梯度图像为:b = kx*bx.*bx + ky*by.*当然这里如果定义了检测方向,就会得到对应上面的图像。
这里值得注意的是为了计算效率并没有对b开平方。而涉及滤波等操作时对图像边界的处理是值得注意的一个地方。我们这里应该将梯度图像的四周1像素点都设置为0。
得到梯度图像后,我们需要的是计算阈值,这是Sobel算法很核心的一部分,也是对效果影响较大的地方,同理讲到canny边缘检测时,用到的双阈值法也是canny算法的核心。
同样这里,我并不太多的介绍算法原理,相关文献可以直接百度。阈值也可以通过自己期待的效果进行自定义阈值,如果没有,则我们计算默认阈值。
scale = 4; cutoff = scale*mean2(b); thresh = sqrt(cutoff);
其中mean2函数是求图像所有点灰度的平均值。scale是一个系数。
有了阈值后,我们就可以地得到的梯度图像进行二值化。二值化过程,不做详细说明,遍历图像中的像素点,灰度大于阈值的置为白点,灰度小于阈值的则置为黑点。
下面是示例图像梯度图像二值化后的效果:
其实很多介绍Soble算法的文章介绍到这里就结束了,印象中OpenCv的算法也是到此步为止。但是我们注意到上面的边缘图像,边缘较粗,如果我们在做边界跟踪或轮廓提取时,上面图像并不是我们期望的结果。
所以下面要介绍一个很重要的算法,用非极大值抑制算法对边缘进行1像素化。本人在开始的时候也一直以为这里用一个普通的细化算法就可以了,可是总得到到想要的结果,最后查找matlab早期版本的源码才找到方法,其实跟canny算法里原理差不多。
我们需要遍历刚才得到的梯度图像二值化结果b,对于b内的任意一点(i,j),如果满足下面条件,则保持白点,否则置为黑点。条件简单的说即是:如果是竖直边缘,则它的梯度值要比左边和右边的点都大;如果是水平连续,则该点的梯度值要比上边和下边的都大。
bx(i,j)&kx*by(i,j) && b(i,j-1)&b(i,j) && b(i,j+1)&b(i,j)
by(i,j)&ky*bx(i,j) && b(i-1,j)&b(i,j) &&b (i+1,j)&b(i,j)
经过这样的非极大值抑制我们就可以得到比较理想的边缘图像。
下面给出利用OpenCV里的一些滤波函数,从新写的一个Sobel边缘检测的函数:
1 bool Sobel(const Mat& image,Mat& result,int TYPE)
if(image.channels()!=1)
return false;
// 系数设置
int kx(0);
int ky(0);
if( TYPE==SOBEL_HORZ ){
kx=0;ky=1;
else if( TYPE==SOBEL_VERT ){
kx=1;ky=0;
else if( TYPE==SOBEL_BOTH ){
kx=1;ky=1;
return false;
// 设置mask
float mask[3][3]={{1,2,1},{0,0,0},{-1,-2,-1}};
Mat y_mask=Mat(3,3,CV_32F,mask)/8;
Mat x_mask=y_mask.t(); // 转置
// 计算x方向和y方向上的滤波
Mat sobelX,sobelY;
filter2D(image,sobelX,CV_32F,x_mask);
filter2D(image,sobelY,CV_32F,y_mask);
sobelX=abs(sobelX);
sobelY=abs(sobelY);
Mat gradient=kx*sobelX.mul(sobelX)+ky*sobelY.mul(sobelY);
// 计算阈值
int scale=4;
double cutoff=scale*mean(gradient)[0];
result.create(image.size(),image.type());
result.setTo(0);
for(int i=1;i&image.rows-1;i++)
float* sbxPtr=sobelX.ptr&float&(i);
float* sbyPtr=sobelY.ptr&float&(i);
float* prePtr=gradient.ptr&float&(i-1);
float* curPtr=gradient.ptr&float&(i);
float* lstPtr=gradient.ptr&float&(i+1);
uchar* rstPtr=result.ptr&uchar&(i);
// 阈值化和极大值抑制
for(int j=1;j&image.cols-1;j++)
if( curPtr[j]&cutoff && (
(sbxPtr[j]&kx*sbyPtr[j] && curPtr[j]&curPtr[j-1] && curPtr[j]&curPtr[j+1]) ||
(sbyPtr[j]&ky*sbxPtr[j] && curPtr[j]&prePtr[j] && curPtr[j]&lstPtr[j]) ))
rstPtr[j]=255;
return true;
发表评论:
TA的最新馆藏

我要回帖

更多关于 图像梯度 的文章

 

随机推荐