基于opencv的多种边缘算子的边缘检测

边缘检测

边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性

的显著变化通常反映了属性的重要事件和变化。

本文主要介绍Roberts cross算子,prewitt算子,canny算子,sobel算子和laplace算子

稍后我将所以代码放在最后,也可以在:http://download.csdn.net/detail/yuansanwan123/7053677下载


Roberts cross 算子

Roberts边缘检测算子是一种利用局部差分算子寻找边缘的算子,Robert算子图像处理后结果边缘不是很平滑。经分

析,由于Robert算子通常会在图像边缘附近的区域内 产生较宽的响应,故采用上述算子检测的边缘图像常需做细化

处理,边缘定位的精度不是很高。
卷积核:         
   robert水平算子                          
10
0-1

robert垂直算子
01
-10
核心代码如下:
void on_trackbar_roberts(int thresold)
{
	int Gx=0,Gy=0,Zxy=0;
	for(int i=0;i<g_imgGray->height-1;i++)
		for(int j=0;j<g_imgGray->width-1;j++)
		{
			Gx = cvGet2D(g_imgGray,i,j).val[0]-cvGet2D(g_imgGray,i+1,j+1).val[0];
			Gy = cvGet2D(g_imgGray,i,j+1).val[0]-cvGet2D(g_imgGray,i+1,j).val[0];
			Zxy=(int)sqrt(Gx*Gx+Gy*Gy*1.0);
			if(Zxy>thresold)
			     cvSet2D(g_imgRobert,i,j,cvScalar(Zxy));
			else
               cvSet2D(g_imgRobert,i,j,cvScalar(0));
		}
		cvShowImage(psWindowRobertTitle,g_imgRobert);
}



prewitt算子

Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边
缘,去掉部分伪边缘,对噪声具有平滑作用 。其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成
的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。

卷积核如下:
水平算子
111
000
-1-1-1
垂直算子
-101
-101
-101
核心代码如下:
void on_trackbar_Prewitt(int thresold)
{
	int Gx=0,Gy=0,Zxy=0;
	for(int i=1;i<g_imgGray->height-1;i++)
		for(int j=1;j<g_imgGray->width-1;j++)
		{
			Gx = cvGet2D(g_imgGray,i,j+1).val[0]+cvGet2D(g_imgGray,i+1,j+1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]-
				 cvGet2D(g_imgGray,i,j-1).val[0]-cvGet2D(g_imgGray,i+1,j-1).val[0]-cvGet2D(g_imgGray,i-1,j-1).val[0];
			Gy = cvGet2D(g_imgGray,i-1,j-1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]+cvGet2D(g_imgGray,i-1,j).val[0]-
				 cvGet2D(g_imgGray,i+1,j-1).val[0]-cvGet2D(g_imgGray,i+1,j).val[0]-cvGet2D(g_imgGray,i+1,j+1).val[0];
			Zxy = (int)sqrt(Gx*Gx+Gy*Gy*1.0);
			if(Zxy>thresold)
				cvSet2D(g_imgPrewitt,i,j,cvScalar(Zxy));
			else
				cvSet2D(g_imgPrewitt,i,j,cvScalar(0));
		}
		cvShowImage(psWindowPrewittTitle,g_imgPrewitt);
}



sobel 算子

  是一离散性差分算子,用来运算图像亮度函数的梯度之近似值。在图像的任何一点使用此算子,将会产生对应的梯

度矢量或是其法矢量

卷积核:
水平算子
-1-2-1
000
121
垂直算子
-101
-202
-101
核心代码如下:
void on_trackbar_sobel(int thresold)
{
	int Gx=0,Gy=0,Zxy=0;
	for(int i=1;i<g_imgGray->height-1;i++)
		for(int j=1;j<g_imgGray->width-1;j++)
		{
			Gx = 2*cvGet2D(g_imgGray,i,j+1).val[0]+cvGet2D(g_imgGray,i+1,j+1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]-
				 2*cvGet2D(g_imgGray,i,j-1).val[0]-cvGet2D(g_imgGray,i+1,j-1).val[0]-cvGet2D(g_imgGray,i-1,j-1).val[0];
			Gy = cvGet2D(g_imgGray,i-1,j-1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]+2*cvGet2D(g_imgGray,i-1,j).val[0]-
				 cvGet2D(g_imgGray,i+1,j-1).val[0]-2*cvGet2D(g_imgGray,i+1,j).val[0]-cvGet2D(g_imgGray,i+1,j+1).val[0];
			Zxy = (int)sqrt(Gx*Gx+Gy*Gy*1.0);
			if(Zxy>thresold)
				cvSet2D(g_imgSobel,i,j,cvScalar(Zxy));
			else
				cvSet2D(g_imgSobel,i,j,cvScalar(0));
		}
		cvShowImage(psWindowSobelTitle,g_imgSobel);
}



canny算子

给大家推荐个网址:morewindows的博客:http://blog.csdn.net/morewindows/article/details/8239625

laplace算子

同样推荐个网址:小魏的修行路的博客:http://blog.csdn.net/xiaowei_cqu/article/details/7829481

好了,其他的不多说了,将所有代码贴上,在一个程序里查看各个算子的优劣。大家找个图,换一下路径并在vs2012

里运行就可以了(当然得装下opencv库)

代码如下:
//边缘检测
//by yuansanwan123

#include <iostream>
#include<opencv2/opencv.hpp>
#include <cmath>
IplImage *g_imgSrc      = cvLoadImage("f:\\carlicense\\10.jpg");
IplImage *g_imgGray     = cvCreateImage(cvGetSize(g_imgSrc),g_imgSrc->depth,1);
IplImage *g_imgRobert   = cvCreateImage(cvGetSize(g_imgSrc),g_imgSrc->depth,1);
IplImage *g_imgCanny    = cvCreateImage(cvGetSize(g_imgSrc),g_imgSrc->depth,1);
IplImage *g_imgPrewitt  = cvCreateImage(cvGetSize(g_imgSrc),g_imgSrc->depth,1);
IplImage *g_imgSobel    = cvCreateImage(cvGetSize(g_imgSrc),g_imgSrc->depth,1);
IplImage *g_imgLaplace  = cvCreateImage(cvGetSize(g_imgSrc),g_imgSrc->depth,1);
char *psWindowRobertTitle   = "robert算子边缘检测图";
char *psWindowCannyTitle    = "Canny算子边缘检测图";
char *psWindowPrewittTitle  = "Prewitt算子边缘检测图";
char *psWindowSobelTitle    = "Sobel算子边缘检测图";
char *psWindowLaplaceTitle  = "Laplace算子边缘检测图";
char *psWindowSrcTitle="源图像";
//cvCreateTrackbar的回调函数
void on_trackbar_roberts(int thresold)
{
	int Gx=0,Gy=0,Zxy=0;
	for(int i=0;i<g_imgGray->height-1;i++)
		for(int j=0;j<g_imgGray->width-1;j++)
		{
			Gx = cvGet2D(g_imgGray,i,j).val[0]-cvGet2D(g_imgGray,i+1,j+1).val[0];
			Gy = cvGet2D(g_imgGray,i,j+1).val[0]-cvGet2D(g_imgGray,i+1,j).val[0];
			Zxy=(int)sqrt(Gx*Gx+Gy*Gy*1.0);
			if(Zxy>thresold)
			     cvSet2D(g_imgRobert,i,j,cvScalar(Zxy));
			else
               cvSet2D(g_imgRobert,i,j,cvScalar(0));
		}
		cvShowImage(psWindowRobertTitle,g_imgRobert);
}
void on_trackbar_canny(int thresold)
{
	cvCanny(g_imgGray,g_imgCanny,thresold,thresold*3);
	cvShowImage(psWindowCannyTitle,g_imgCanny);
}
void on_trackbar_Prewitt(int thresold)
{
	int Gx=0,Gy=0,Zxy=0;
	for(int i=1;i<g_imgGray->height-1;i++)
		for(int j=1;j<g_imgGray->width-1;j++)
		{
			Gx = cvGet2D(g_imgGray,i,j+1).val[0]+cvGet2D(g_imgGray,i+1,j+1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]-
				 cvGet2D(g_imgGray,i,j-1).val[0]-cvGet2D(g_imgGray,i+1,j-1).val[0]-cvGet2D(g_imgGray,i-1,j-1).val[0];
			Gy = cvGet2D(g_imgGray,i-1,j-1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]+cvGet2D(g_imgGray,i-1,j).val[0]-
				 cvGet2D(g_imgGray,i+1,j-1).val[0]-cvGet2D(g_imgGray,i+1,j).val[0]-cvGet2D(g_imgGray,i+1,j+1).val[0];
			Zxy = (int)sqrt(Gx*Gx+Gy*Gy*1.0);
			if(Zxy>thresold)
				cvSet2D(g_imgPrewitt,i,j,cvScalar(Zxy));
			else
				cvSet2D(g_imgPrewitt,i,j,cvScalar(0));
		}
		cvShowImage(psWindowPrewittTitle,g_imgPrewitt);
}
void on_trackbar_sobel(int thresold)
{
	int Gx=0,Gy=0,Zxy=0;
	for(int i=1;i<g_imgGray->height-1;i++)
		for(int j=1;j<g_imgGray->width-1;j++)
		{
			Gx = 2*cvGet2D(g_imgGray,i,j+1).val[0]+cvGet2D(g_imgGray,i+1,j+1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]-
				 2*cvGet2D(g_imgGray,i,j-1).val[0]-cvGet2D(g_imgGray,i+1,j-1).val[0]-cvGet2D(g_imgGray,i-1,j-1).val[0];
			Gy = cvGet2D(g_imgGray,i-1,j-1).val[0]+cvGet2D(g_imgGray,i-1,j+1).val[0]+2*cvGet2D(g_imgGray,i-1,j).val[0]-
				 cvGet2D(g_imgGray,i+1,j-1).val[0]-2*cvGet2D(g_imgGray,i+1,j).val[0]-cvGet2D(g_imgGray,i+1,j+1).val[0];
			Zxy = (int)sqrt(Gx*Gx+Gy*Gy*1.0);
			if(Zxy>thresold)
				cvSet2D(g_imgSobel,i,j,cvScalar(Zxy));
			else
				cvSet2D(g_imgSobel,i,j,cvScalar(0));
		}
		cvShowImage(psWindowSobelTitle,g_imgSobel);
}
void on_trackbar_laplace(int thresold)
{
	int Gx=0,Gy=0,Zxy=0;
	for(int i=1;i<g_imgGray->height-1;i++)
		for(int j=1;j<g_imgGray->width-1;j++)
		{
			Gy  = 2*cvGet2D(g_imgGray,i,j).val[0]-cvGet2D(g_imgGray,i-1,j).val[0]-cvGet2D(g_imgGray,i+1,j).val[0];
			Gx = 2*cvGet2D(g_imgGray,i,j).val[0]-cvGet2D(g_imgGray,i,j-1).val[0]-cvGet2D(g_imgGray,i,j+1).val[0];
			Zxy=Gx+Gy;
			//或者直接计算
			//Zxy= 4*cvGet2D(g_imgGray,i,j).val[0]-cvGet2D(g_imgGray,i,j+1).val[0]-cvGet2D(g_imgGray,i,j-1).val[0]-
				//cvGet2D(g_imgGray,i-1,j).val[0]-cvGet2D(g_imgGray,i+1,j).val[0];
			if(Zxy>thresold)
				cvSet2D(g_imgLaplace,i,j,cvScalar(Zxy));
			else
				cvSet2D(g_imgLaplace,i,j,cvScalar(0));
		}
		cvShowImage(psWindowLaplaceTitle,g_imgLaplace);
}
int main( int argc, char** argv )
{
	//对图像灰度化
	cvCvtColor(g_imgSrc,g_imgGray,CV_BGR2GRAY);
	cvZero(g_imgRobert);
	cvZero(g_imgCanny);
	cvZero(g_imgPrewitt);
	cvZero(g_imgSobel);
	cvZero(g_imgLaplace);
	//创建窗口
	cvNamedWindow(psWindowRobertTitle);
	cvNamedWindow(psWindowSrcTitle);
	cvNamedWindow(psWindowCannyTitle);
	cvNamedWindow(psWindowPrewittTitle);
	cvNamedWindow(psWindowSobelTitle);
	cvNamedWindow(psWindowLaplaceTitle);

	//创建滑动条
	char *trackbar="robert_thresold",*trackbar_Canny="Canny_thresold",*trackbar_Prewitt="Prewitt_thresold";
	char *trackbar_Sobel="Sobel_thresold",*trackbar_Laplace="Laplace_thresold";
	int value=1;
	cvCreateTrackbar(trackbar_Laplace,psWindowLaplaceTitle,&value,255,on_trackbar_laplace);
	cvCreateTrackbar(trackbar_Sobel,psWindowSobelTitle,&value,255,on_trackbar_sobel);
	cvCreateTrackbar(trackbar_Prewitt,psWindowPrewittTitle,&value,255,on_trackbar_Prewitt);
	cvCreateTrackbar(trackbar_Canny,psWindowCannyTitle,&value,255,on_trackbar_canny);
	cvCreateTrackbar(trackbar,psWindowRobertTitle,&value,255,on_trackbar_roberts);
	on_trackbar_roberts(1);
	on_trackbar_canny(1);
	on_trackbar_Prewitt(1);
	on_trackbar_sobel(1);
	on_trackbar_laplace(1);
	//在指定窗口中显示图像
	cvShowImage(psWindowSrcTitle,g_imgSrc);
	//等待按键事件 
	cvWaitKey(0);
	//释放内存
	cvDestroyAllWindows();
	cvReleaseImage(&g_imgRobert);
	cvReleaseImage(&g_imgGray);
	cvReleaseImage(&g_imgSrc);
	cvReleaseImage(&g_imgCanny);
	cvReleaseImage(&g_imgLaplace);
	cvReleaseImage(&g_imgPrewitt);
	cvReleaseImage(&g_imgSobel);
	return 0;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值