收入囊中



 (图片来自http://blog.csdn.net/likezhaobin/article/details/6892176)
(图片来自http://blog.csdn.net/likezhaobin/article/details/6892176)在上个步骤中,产生了梯度幅值, (upper and lower):
如果一个像素点的梯度值大于upper,则是边界
如果一个像素点的梯度值小于lower,则不是边界
如果介于两者之间,仅当这个点和边界点连通才会被认为是边界点
根据高阈值得到一个边缘图像,这样一个图像含有很少的假边缘,但是由于阈值较高,产生的图像边缘可能不闭合,为解决这样一个问题采用了另外一个低阈值。在高阈值图像中把边缘链接成轮廓,当到达轮廓的端点时,该算法会在断点的8邻域点中寻找满足低阈值的点,再根据此点收集新的边缘,直到整个图像边缘闭合。
Canny推荐upper:lower 的比例为 2:1 或者 3:1.
小提示:因为 ,所以最高阀值不是255而是360!还有处于[lower,upper]的点检测是否是边界肯定要放在最后一步,也就是[0,lower),(upper,360]的点都处理完再处理,这样才能判连通!
,所以最高阀值不是255而是360!还有处于[lower,upper]的点检测是否是边界肯定要放在最后一步,也就是[0,lower),(upper,360]的点都处理完再处理,这样才能判连通!
| 
 | 
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
/// Global variables
Mat src, src_gray;
Mat dst, detected_edges;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
const char* window_name = "Edge Map";
static void CannyThreshold(int, void*)
{
    blur( src_gray, detected_edges, Size(3,3) );
    Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );
    dst = Scalar::all(0);
    //detected_edges是mask,只有detected_edges被置上(边缘),才会从原始彩色图像copy到dot中,所以展示的是彩色边缘
    src.copyTo( dst, detected_edges);
    imshow( window_name, dst );
}
int main( int, char** argv )
{
  src = imread( argv[1] );
  dst.create( src.size(), src.type() );
  cvtColor( src, src_gray, CV_BGR2GRAY );
  namedWindow( window_name, CV_WINDOW_AUTOSIZE );
  createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );
  CannyThreshold(0, 0);
  waitKey(0);
  return 0;
}public int[][] CannyEdgeDetect(int[][] oldmat)
	{
		
		int[][] tempI = gaussFilter(oldmat); 
		
		//////////////////?¨—??…“‘”√≤a?¨μ?o?≤???/////////////////////////  
		/////    P[i,j]=(S[i,j+1]-S[i,j]+S[i+1,j+1]-S[i+1,j])/2     /////  
		/////    Q[i,j]=(S[i,j]-S[i+1,j]+S[i,j+1]-S[i+1,j+1])/2     /////  
		/////////////////////////////////////////////////////////////////  
		float[][] P = new float[height][width];                 //x?ú?′μo ?  
		float[][] Q = new float[height][width];                 //y?ú?′μo ?  
		int[][] M = new int[height][width];                       //????∑?÷μ  
		float[][] Theta = new float[height][width];             //????∑Ω?ú  
		//o?à?x,y∑Ω?úμ??′μo ?  
		for(int i=0; i<(width-1); i++)  
		{  
			for(int j=0; j<(height-1); j++)  
			{  
				P[j][i] = (float)(tempI[j][Math.min(i+1, width-1)] - tempI[j][i] + tempI[Math.min(j+1, height-1)][Math.min(i+1, width-1)] - tempI[Math.min(j+1, height-1)][i])/2;  
				Q[j][i] = (float)(tempI[j][i] - tempI[Math.min(j+1, height-1)][i] + tempI[j][Math.min(i+1, width-1)] - tempI[Math.min(j+1, height-1)][Math.min(i+1, width-1)])/2; 
				
			}  
		}  
		//o?à?????∑?÷μ∫?????μ?∑Ω?ú  
		for(int i=0; i<width; i++)  
		{  
			for(int j=0; j<height; j++)  
			{  
				M[j][i] = (int)(Math.sqrt(P[j][i]*P[j][i] + Q[j][i]*Q[j][i])+0.5); 
				//System.out.println(M[j][i]);
				Theta[j][i] = (float) (Math.atan2(Q[j][i], P[j][i]) * 57.3);  
				if(Theta[j][i] < 0)  
					Theta[j][i] += 360;              //Ω′’?∏?Ω?????aaμΩ0~360∑???  
			}  
		}  
		
		
		int[][] N = new int[height][width];  			//∑?o′¥?÷μ“÷÷?Ω·π?  
		int g1=0, g2=0, g3=0, g4=0;                     //”√”?Ωˉ––≤?÷죨μ√μΩ—??òà?μ??ˉ±í÷μ  
		double dTmp1=0.0, dTmp2=0.0;                    //±£¥ê?Ω∏?—??òà?μ?≤?÷μμ√μΩμ?a“?? ???  
		double dWeight=0.0;                             //≤?÷μμ??®÷?  
		
		//±?Ωá≥? oa?
		for(int i=0; i<width; i++)  
		{  
		        N[0][i] = 0;  
		        N[height-1][i] = 0;  
		}  
		for(int j=0; j<height; j++)  
		{  
		        N[j][0] = 0;  
		        N[j][width-1] = 0;  
		}  
		
		//Ωˉ––?÷≤??ó¥?÷μ—∞’“
		for(int i=1; i<(width-1); i++)  
		{  
		    for(int j=1; j<(height-1); j++)  
		    {  
		        if(M[j][i] == 0)  
		            N[j][i] = 0;         //?áπ?μ±?∞????∑?÷μ??0£¨‘ú≤a ??÷≤??ó¥??‘∏√μ?∏≥??0  
		        else  
		        {  
		        //////// ???≈–?? ù”???÷÷?è??£¨?a∫?∏????è??≤?÷μ///////  
		        ////////////////////μ?“a÷÷?è??///////////////////////  
		        /////////       g1  g2                  /////////////  
		        /////////           C                   /////////////  
		        /////////           g3  g4              /////////////  
		        /////////////////////////////////////////////////////  
		        if( ((Theta[j][i]>=90)&&(Theta[j][i]<135)) ||   
		                ((Theta[j][i]>=270)&&(Theta[j][i]<315)))  
		            {  
		                //////∏???–±? ∫?à?∏?÷–o‰÷μΩˉ––≤?÷μ??Ω?  
		                g1 = M[j-1][i-1];  
		                g2 = M[j-1][i];  
		                g3 = M[j+1][i];  
		                g4 = M[j+1][i+1];  
		                dWeight = Math.abs(P[j][i])/Math.abs(Q[j][i]);   //∑¥’??–  
		                dTmp1 = g1*dWeight+g2*(1-dWeight);  
		                dTmp2 = g4*dWeight+g3*(1-dWeight);  
		            }  
		        ////////////////////μ???÷÷?è??///////////////////////  
		        /////////       g1                      /////////////  
		        /////////       g2  C   g3              /////////////  
		        /////////               g4              /////////////  
		        /////////////////////////////////////////////////////  
		            else if( ((Theta[j][i]>=135)&&(Theta[j][i]<180)) ||   
		                ((Theta[j][i]>=315)&&(Theta[j][i]<360)))  
		            {  
		                g1 = M[j-1][i-1];  
		                g2 = M[j][i-1];  
		                g3 = M[j][i+1];  
		                g4 = M[j+1][i+1];  
		                dWeight = Math.abs(Q[j][i])/Math.abs(P[j][i]);   //’??–  
		                dTmp1 = g2*dWeight+g1*(1-dWeight);  
		                dTmp2 = g4*dWeight+g3*(1-dWeight);  
		            }  
		        ////////////////////μ???÷÷?è??///////////////////////  
		        /////////           g1  g2              /////////////  
		        /////////           C                   /////////////  
		        /////////       g4  g3                  /////////////  
		        /////////////////////////////////////////////////////  
		            else if( ((Theta[j][i]>=45)&&(Theta[j][i]<90)) ||   
		                ((Theta[j][i]>=225)&&(Theta[j][i]<270)))  
		            {  
		                g1 = M[j-1][i];  
		                g2 = M[j-1][i+1];  
		                g3 = M[j+1][i];  
		                g4 = M[j+1][i-1];  
		                dWeight = Math.abs(P[j][i])/Math.abs(Q[j][i]);   //∑¥’??–  
		                dTmp1 = g2*dWeight+g1*(1-dWeight);  
		                dTmp2 = g3*dWeight+g4*(1-dWeight);  
		            }  
		            ////////////////////μ?à?÷÷?è??///////////////////////  
		            /////////               g1              /////////////  
		            /////////       g4  C   g2              /////////////  
		            /////////       g3                      /////////////  
		            /////////////////////////////////////////////////////  
		            else if( ((Theta[j][i]>=0)&&(Theta[j][i]<45)) ||   
		                ((Theta[j][i]>=180)&&(Theta[j][i]<225)))  
		            {  
		                g1 = M[j-1][i+1];  
		                g2 = M[j][i+1];  
		                g3 = M[j+1][i-1];  
		                g4 = M[j][i-1];  
		                dWeight = Math.abs(Q[j][i])/Math.abs(P[j][i]);   //’??–  
		                dTmp1 = g1*dWeight+g2*(1-dWeight);  
		                dTmp2 = g3*dWeight+g4*(1-dWeight);  
		            }  
		        }         
		        //////////Ωˉ––?÷≤??ó¥?÷μ≈–??£¨≤¢–¥??o?≤?Ω·π?////////////////  
		        if((M[j][i]>=dTmp1) && (M[j][i]>=dTmp2))  
		            N[j][i] = 128;  
		        else  
		            N[j][i] = 0;  
		        
		        //System.out.println(N[j][i]);
		        }  
		}  
		
		
		//à′∑?÷μo?≤? μ?÷
		int []nHist = new int[1024];   
		int nEdgeNum;             //?…??±?Ωá ?  
		int nMaxMag = 0;          //?ó¥????? ?  
		int nHighCount;  
		
		//?≥o?÷±∑Ω?o
		for(int i=0;i<1024;i++)  
	        nHist[i] = 0;  
		for(int i=0; i<width; i++)  
		{  
	        for(int j=0; j<height; j++)  
	        {  
	              if(N[j][i]==128)  
	                   nHist[M[j][i]]++;  
	        }  
		}  
		
		//aò?°?ó¥?????∑?÷μo∞?±‘?±?‘μμ?∏? ?
		nEdgeNum = nHist[0];  
		nMaxMag = 0;                    //aò?°?ó¥?μ?????÷μ        
		for(int i=1; i<1024; i++)           //?≥o??≠π?°∞∑??ó¥?÷μ“÷÷?°±∫?”–??…??òà?  
		{  
		    if(nHist[i] != 0)       //??????0μ?μ? ?≤a?…????±?Ωáμ?μ?  
		    {  
		        nMaxMag = i;  
		    }     
		    nEdgeNum += nHist[i];   //?≠π?non-maximum suppression∫?”–??…??òà?  
		}  
		
		//o?à??Ω∏?∑?÷μ
		float  dRatHigh = 0.79f;  
		float  dThrHigh;  
		float  dThrLow;  
		float  dRatLow = 0.5f;  
		nHighCount = (int)(dRatHigh * nEdgeNum + 0.5);  
		int k = 1;  
		nEdgeNum = nHist[1];  
		while((k<(nMaxMag-1)) && (nEdgeNum < nHighCount))  
		{  
		       k++;  
		       nEdgeNum += nHist[k];  
		}  
		dThrHigh = k;                                   //∏??–÷μ  
		dThrLow = (int)((dThrHigh) * dRatLow + 0.5);    //μ??–÷μ  
		System.out.println("high = " + dThrHigh + "low = " + dThrLow);
		//dThrHigh = 10;
		//dThrLow = 5;
		
		
		//Ωˉ––±?‘μo?≤? 
		int cx = width;  
		int cy = height;  
		for(int i=0; i<width; i++)  
		{  
		    for(int j=0; j<height; j++)  
		    {  
		        if((N[j][i]==128) && (M[j][i] >= dThrHigh))  
		        {  
		            N[j][i] = 255;  
		            TraceEdge(j, i, (int)(dThrLow+0.5), N, M);  
		        }  
		    }  
		}  
		
		//Ω′aπ√a”–…?÷√??±?Ωáμ?μ?…?÷√??∑?±?Ωáμ?  
		for(int i=0; i<width; i++)  
		{  
		    for(int j=0; j<height; j++)  
		    {  
		        if(N[j][i] != 255)  
		        {  
		            N[j][i]  = 0 ;   // …?÷√??∑?±?Ωáμ?  
		        }  
		        N[j][i] = N[j][i] + (N[j][i] << 8) + (N[j][i] << 16);
		    }  
		}  
		
		
		return N;
		
	}
	
	/*
	 * cancy ∏®÷˙∫? ?
	 */
	private void TraceEdge(int y, int x, int nThrLow, int[][] pResult, int[][] pMag)  
	{  
	    //?‘8??”ú?òà?Ωˉ––≤è—?  
	    int[] xNum = {1,1,0,-1,-1,-1,0,1};  
	    int[] yNum = {0,1,1,1,0,-1,-1,-1};  
	    int yy,xx,k;  
	    for(k=0;k<8;k++)  
	    {  
	        yy = y+yNum[k];  
	        xx = x+xNum[k];  
	        if(pResult[yy][xx]==128 && pMag[yy][xx]>=nThrLow )  
	        {  
	            //∏√μ?…???±?Ωáμ?  
	            pResult[yy][xx] = 255;  
	            //“‘∏√μ???÷––?‘?Ωˉ––∏˙??  
	            TraceEdge(yy,xx,nThrLow,pResult,pMag);  
	        }  
	    }  
	}  OpenCV2马拉松第17圈——边缘检测(Canny边缘检测),布布扣,bubuko.com
OpenCV2马拉松第17圈——边缘检测(Canny边缘检测)
原文地址:http://blog.csdn.net/abcd1992719g/article/details/25612389