距离变换扫描实现

#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/core/core.hpp>        
#include <opencv2/highgui/highgui.hpp> 
#include <iostream> 
// 计算欧式距离
float calcEuclideanDistance(int x1, int y1, int x2, int y2)
{
	return sqrt(float((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)));
}
// 计算棋盘距离
int calcChessboardDistance(int x1, int y1, int x2,int y2)
{
	return cv::max(abs(x1-x2), abs(y1-y2));
}
// 计算街区距离
int calcBlockDistance(int x1, int y1, int x2,int y2)
{
	return abs(x1-x2) + abs(y1-y2);  
}
// 距离变换函数实现
void distanceTrans(cv::Mat &srcImage, cv::Mat &resultIamge)
{
    CV_Assert(srcImage.data != NULL);
    cv::Mat srcGray, srcBinary; 
    // 转换成灰度图像
    cv::cvtColor( srcImage, srcGray, CV_RGB2GRAY );
    // 转换成二值图像
    threshold(srcGray, srcBinary, 100, 255,cv::THRESH_BINARY);
    cv::imshow("srcBinary", srcBinary);
    int rows = srcBinary.rows;
    int cols = srcBinary.cols; 
    uchar* pDataOne;
    uchar* pDataTwo;
    float disPara = 0;
    float fDisMin = 0;
    // 第一遍遍历图像用左模板更新像素值
    for(int i = 1 ; i < rows - 1; i++)
    {
    	// 图像指针获取
        pDataOne = srcBinary.ptr<uchar>(i);
    	for(int j = 1; j < cols; j++)
    	{
    		// 分别计算其左模板掩码相关距离
    		//   pL  pL
    		//   pL  p
    		//   pL
            pDataTwo = srcBinary.ptr<uchar>(i-1); 
			disPara  = calcEuclideanDistance(i, j, i-1, j-1);
			fDisMin  = cv::min( (float)pDataOne[j],
			    disPara+pDataTwo[j-1] );
			disPara  = calcEuclideanDistance(i, j, i-1, j);
			fDisMin  = cv::min( fDisMin, 
				disPara+pDataTwo[j] );
			pDataTwo = srcBinary.ptr<uchar>(i);
			disPara  = calcEuclideanDistance(i, j, i, j-1);
			fDisMin  = cv::min( fDisMin, 
				disPara+pDataTwo[j-1] );
			pDataTwo = srcBinary.ptr<uchar>(i+1);
			disPara  = calcEuclideanDistance(i, j, i+1, j-1);
			fDisMin  = cv::min( fDisMin, 
				disPara+pDataTwo[j-1] );
			pDataOne[j] = (uchar)cvRound(fDisMin);
    	}
    }
    // 第二遍遍历图像用右模板更新像素值
    for( int i = rows-2; i > 0; i-- )  
    {  
        pDataOne = srcBinary.ptr<uchar>(i);  
        for( int  j = cols-1; j >= 0; j-- )  
        {     
            // 分别计算其右模板掩码相关距离 
            //   pR  pR
    		//   pR  p
    		//   pR     
            pDataTwo = srcBinary.ptr<uchar>(i+1);  
            disPara  = calcEuclideanDistance(i, j, i+1, j);  
            fDisMin  = cv::min( (float)pDataOne[j],
            	disPara + pDataTwo[j] );  
            disPara = calcEuclideanDistance(i, j, i+1, j+1);  
            fDisMin = cv::min( fDisMin, 
            	disPara + pDataTwo[j+1] );    
            pDataTwo = srcBinary.ptr<uchar>(i);   
            disPara = calcEuclideanDistance(i, j, i, j+1);  
            fDisMin = cv::min( fDisMin,
                disPara + pDataTwo[j+1] );   
            pDataTwo = srcBinary.ptr<uchar>(i-1); 
            disPara = calcEuclideanDistance(i, j, i-1, j+1);  
            fDisMin = cv::min( fDisMin,
                disPara + pDataTwo[j+1] );    
            pDataOne[j] = (uchar)cvRound(fDisMin);  
        }  
    }  
    resultIamge = srcBinary.clone();
}
int main()
{
	cv::Mat srcImage =  cv::imread("22.jpg");
     if( !srcImage.data ) 
	   return -1;
	cv::Mat resultIamge;
	distanceTrans(srcImage, resultIamge);
	cv::imshow("resultIamge", resultIamge);
	cv::waitKey(0);
	return 0;    
}

转载:http://blog.csdn.net/zhuwei1988


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值