边缘检测——Sobel算子

代码依赖OpenCV来做一些数据结构和显示的工作,但主要的计算法部分是自己实现的。后面争取依次给出常见的集中边缘提取的算法实现。下次补上原理推到说明。

// Sobel.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "math.h"
#include "stdio.h"
#include "malloc.h"

IplImage *image;						//声明IplImage指针
int height,width;
CvScalar sclr;

int sobel_y[9]={1,2,1,0,0,0,-1,-2,-1};  //y方向sobel算子
int sobel_x[9]={1,0,-1,2,0,-2,1,0,-1};  //x方向sobel算子

//显示矩阵BGR
inline void cv3DoubleMatPrint( const CvMat* mat )
{
	int i, j;
	for( i = 0; i < mat->rows; i++ )
	{
		for( j = 0; j < mat->cols; j++ )
		{
			CvScalar scal = cvGet2D( mat, i, j );
			printf( "(%f,%f,%f) ", scal.val[0], scal.val[1], scal.val[2] );
		}
		printf( "\n" );
	}
}

//Sobel算法
void sobel()
{
	int i,j,k;
	int gray_x=0, gray_y=0, gray;
	int *data;
	int temp[9];
	data = (int *)malloc(height*width*sizeof(int));//分配内存空间
	for(i=0;i<height;i++)						   //将一点三个数据的矩阵转为一点单数据的矩阵
	{
		for(j=0;j<width;j++)
		{
			sclr=cvGet2D(image,i,j);
			gray=(int)sclr.val[0];
			data[i*width+j]=gray;  
		}
	}

	for(i=1;i<height-1;i++)
	{
		for(j=1;j<width-1;j++)
		{
			gray_x=0;
			gray_y=0;
			sclr=cvGet2D(image,i,j);
			temp[0]=data[width*(i-1)+j-1];  
			temp[1]=data[width*(i-1)+j];   
			temp[2]=data[width*(i-1)+j+1]; 

			temp[3]=data[width*i+j-1];     
			temp[4]=data[width*i+j];   
			temp[5]=data[width*i+j+1];

			temp[6]=data[width*(i+1)+j-1];  
			temp[7]=data[width*(i+1)+j];
			temp[8]=data[width*(i+1)+j+1];

			for(k=0;k<9;k++)
				gray_y+=temp[k]*sobel_y[k];
			for(k=0;k<9;k++)
				gray_x+=temp[k]*sobel_x[k];

			//sclr.val[0]=(gray_x+gray_y);//生成梯度图
			//=======================================//
			//根据梯度二值化得到提取边缘后的图像
			sclr.val[0]= abs(gray_x) + abs(gray_y);
			//阈值可调整,阈值大则轮廓线条少,阈值小则轮廓线密
			if (sclr.val[0]<200)
				sclr.val[0] = 0;
			else
				sclr.val[0] = 255;
			//=======================================//
			cvSet2D(image,i,j,sclr);
		}
	}
	free(data);
}


int main( int argc, char** argv )
{
	IplImage* img = cvLoadImage("test.jpg");
	cvNamedWindow( "img" );	//创建窗口
	cvShowImage( "img", img );	//显示图像
	image = cvLoadImage( "test.jpg", 0);
	height=image->height;
	width=image->width;

	sobel(); 
	//cvWaitKey(0);
	//===========================================//
	//mat = cvGetMat( image, &cvmat );
	//cv3DoubleMatPrint( mat );
	//===========================================//

	cvNamedWindow( "Image", 1 );	//创建窗口
	cvShowImage( "Image", image );	//显示图像

	cvWaitKey(0);					//等待按键

	cvDestroyWindow( "Image" );		//销毁窗口
	cvReleaseImage( &image );		//释放图像
	return 0;

}


你可能感兴趣的:(图像处理,边缘检测,sobel)