自适应canny检测

自适应Canny阈值算法

求取灰度图像的梯度图imge和梯度的最大值maxv;
设置梯度图的直方图hist的hist_size=maxv, ranges在[0, maxv]范围内,并计算直方图hist;
设置非边缘像素点占整幅图像像素点的比例PercentOfPixelsNotEdges;
设置total阈值,total = size.height * size.width * PercentOfPixelsNotEdges;
遍历直方图hist中,每个梯度值对应的像素点个数,并求和保存在sum变量中;
如果sum变量的值大于total的值,退出hist遍历的循环;
计算Canny的低阈值和高阈值。
a.如果某一像素位置的幅值超过高阈值, 该像素被保留为边缘像素。
b.如果某一像素位置的幅值小于低阈值, 该像素被排除。
c.如果某一像素位置的幅值在两个阈值之间, 该像素仅仅在连接到一个高于高阈值的像素时被保留。
Canny 推荐的 高:低 阈值比在 2:1 到3:1之间。

cvCanny函数中, 高低阈值自适应计算方法 - cay22的专栏 - CSDN博客
https://blog.csdn.net/bagboy_taobao_com/article/details/47158987

StraightLineFinder.rar StraightLineFinder.cpp
http://read.pudn.com/downloads171/sourcecode/graph/texture_mapping/791537/StraightLineFinder/StraightLineFinder/StraightLineFinder.cpp__.htm
在OpenCV中自适应确定canny算法的分割门限 - sunlylorn的专栏 - CSDN博客
https://blog.csdn.net/sunlylorn/article/details/8015825

Canny边缘检测及自适应门限 - NoNeil - CSDN博客
https://blog.csdn.net/debug__boy/article/details/8179730
一种自适应阈值的Canny边缘检测算法_图文_百度文库
https://wenku.baidu.com/view/607820c16137ee06eff9187b.html

#include <cv.h>
#include <highgui.h>
#include <math.h>
#include <iostream>
 
using namespace std;
 
void AdaptiveFindThreshold(const CvArr* image, double *low, double *high, int aperture_size=3);
void _AdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high);
 
int main(int argc, char** argv)
{
	IplImage* pImg = NULL;    
	IplImage* pCannyImg = NULL;
 
	double low_thresh = 0.0;
	double high_thresh = 0.0;
 
	if( argc == 2 && (pImg = cvLoadImage( argv[1], 0)) != 0 )   
	{   		
		pCannyImg = cvCreateImage(cvGetSize(pImg), IPL_DEPTH_8U, 1);
		
		CvMat *dx = (CvMat*)pImg;
		CvMat *dy = (CvMat*)pCannyImg;
		if(low_thresh == 0.0 && high_thresh == 0.0)
		{  
			AdaptiveFindThreshold(pImg, &low_thresh, &high_thresh);
			cout << "low_thresh:  " << low_thresh << endl;
			cout << "high_thresh: " << high_thresh << endl;
		}
		cvCanny(pImg, pCannyImg, low_thresh, high_thresh, 3);   
 
		cvNamedWindow("src", 1);   
		cvNamedWindow("canny",1);   
 
		cvShowImage( "src", pImg );   
		cvShowImage( "canny", pCannyImg );   
 
		cvWaitKey(0);    
 
		cvDestroyWindow( "src" );   
		cvDestroyWindow( "canny" );   
 
		cvReleaseImage( &pImg );    
		cvReleaseImage( &pCannyImg );    
	}
	return 0; 
}
 
void AdaptiveFindThreshold(const CvArr* image, double *low, double *high, int aperture_size)
{                                                                              
	cv::Mat src = cv::cvarrToMat(image);                                   
	const int cn = src.channels();                                         
	cv::Mat dx(src.rows, src.cols, CV_16SC(cn));                           
	cv::Mat dy(src.rows, src.cols, CV_16SC(cn));                           
                                                                               
	cv::Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, cv::BORDER_REPLICATE);
	cv::Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv::BORDER_REPLICATE);
                                                                               
	CvMat _dx = dx, _dy = dy;                                              
	_AdaptiveFindThreshold(&_dx, &_dy, low, high);                         
                                                                               
}                                                                              
                                                                               
// 仿照matlab,自适应求高低两个门限                                            
void _AdaptiveFindThreshold(CvMat *dx, CvMat *dy, double *low, double *high)   
{                                                                              
	CvSize size;                                                           
	IplImage *imge=0;                                                      
	int i,j;                                                               
	CvHistogram *hist;                                                     
	int hist_size = 255;                                                   
	float range_0[]={0,256};                                               
	float* ranges[] = { range_0 };                                         
	double PercentOfPixelsNotEdges = 0.7;                                  
	size = cvGetSize(dx);                                                  
	imge = cvCreateImage(size, IPL_DEPTH_32F, 1);                          
	// 计算边缘的强度, 并存于图像中                                        
	float maxv = 0;                                                        
	for(i = 0; i < size.height; i++ )                                      
	{                                                                      
		const short* _dx = (short*)(dx->data.ptr + dx->step*i);        
		const short* _dy = (short*)(dy->data.ptr + dy->step*i);        
		float* _image = (float *)(imge->imageData + imge->widthStep*i);
		for(j = 0; j < size.width; j++)                                
		{                                                              
			_image[j] = (float)(abs(_dx[j]) + abs(_dy[j]));        
			maxv = maxv < _image[j] ? _image[j]: maxv;             
	                                                                       
		}                                                              
	}                                                                      
	if(maxv == 0){                                                         
		*high = 0;                                                     
		*low = 0;                                                      
		cvReleaseImage( &imge );                                       
		return;                                                        
	}                                                                      
                                                                               
	// 计算直方图                                                          
	range_0[1] = maxv;                                                     
	hist_size = (int)(hist_size > maxv ? maxv:hist_size);                  
	hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);          
	cvCalcHist( &imge, hist, 0, NULL );                                    
	int total = (int)(size.height * size.width * PercentOfPixelsNotEdges); 
	float sum=0;                                                           
	int icount = hist->mat.dim[0].size;                                    
                                                                               
	float *h = (float*)cvPtr1D( hist->bins, 0 );                           
	for(i = 0; i < icount; i++)                                            
	{                                                                      
		sum += h[i];                                                   
		if( sum > total )                                              
			break;                                                 
	}                                                                      
	// 计算高低门限                                                        
	*high = (i+1) * maxv / hist_size ;                                     
	*low = *high * 0.4;                                                    
	cvReleaseImage( &imge );                                               
	cvReleaseHist(&hist);                                                  
}                                                                              

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值