图像匹配之距离变换匹配法

来源:互联网 发布:cydia下载软件 编辑:程序博客网 时间:2024/06/05 07:31

距离变换是一种常见的二值图像处理算法,用来计算图像中任意位置到最近边缘点的距离,常见的距离测度函数有切削距离,街区距离和欧式距。切削距离和街区距离是欧式距离的一种近似。

基于距离变换的匹配的原理是计算模板图覆盖下的那块子图与模板图之间的距离,也就是计算子图中的边缘点到模板图中最近的边缘点的距离,这里采用欧式距离,并对欧式距离进行近似,认为与边缘4邻域相邻的点的距离为0.3,8邻域相邻的点的距离为0.7,不相邻的点的距离都为1。

opencv程序如下:

#include "stdafx.h"     #include <opencv2/opencv.hpp>  #include "highgui.h"  #include <math.h>  typedef  unsigned long uint32;typedef  unsigned int  uint16;typedef  unsigned char uint8;IplImage *src_gray1, *src_gray2, *src_gray3;    IplImage *temp_gray1, *temp_gray2, *temp_gray3; IplImage *Dist;uint8    TemplatePixelm10 = 0;uint8    TemplatePixelm01 = 0;uint8    TemplatePixeln01 = 0;uint8    TemplatePixeln10 = 0;uint8    TemplatePixelm1n1 = 0;uint8    TemplatePixelm1n0 = 0;uint8    TemplatePixelm0n1 = 0;uint8    TemplatePixelm0n0 = 0;void AllocateImage(IplImage* I,IplImage* T)   //给图像分配大小    {        CvSize sz   = cvGetSize(I);        CvSize sz_T = cvGetSize(T);                    src_gray1 = cvCreateImage( sz, IPL_DEPTH_8U, 1);    //原图的三个通道        src_gray2 = cvCreateImage( sz, IPL_DEPTH_8U, 1);        src_gray3 = cvCreateImage( sz, IPL_DEPTH_8U, 1);            temp_gray1 = cvCreateImage( sz_T, IPL_DEPTH_8U, 1);    //模板的三个通道        temp_gray2 = cvCreateImage( sz_T, IPL_DEPTH_8U, 1);        temp_gray3 = cvCreateImage( sz_T, IPL_DEPTH_8U, 1);    Dist = cvCreateImage(sz_T,IPL_DEPTH_8U,1);    } void CalTemplateDist(IplImage* I,IplImage* Dist, long* Nb)    //计算在模板图对应位置上的距离{int i,j;float dis;for ( i=0; i<I->height; i++ ){uint8* ptr = (uint8*)( I->imageData + i*I->widthStep );for ( j=0; j<I->width; j++ ){uint8 Pixel = ptr[j];if(Pixel==0){dis = 0;(*Nb)++;}else{if( i==0 && j==0 )                     //第一行第一个点{TemplatePixelm10  = ptr[j+1];TemplatePixeln10  = *( I->imageData + (i+1)*I->widthStep + j );TemplatePixelm1n1 = *( I->imageData + (i+1)*I->widthStep + j+1 );if( TemplatePixelm10==0 || TemplatePixeln10==0 )dis = 0.3;else if( TemplatePixelm1n1==0 )dis = 0.7;elsedis = 1;}else if( i==0 && j>0 && j<(I->width-1) )    //第一行{TemplatePixelm10  = ptr[j+1];TemplatePixelm01  = ptr[j-1];TemplatePixeln10  = *( I->imageData + (i+1)*I->widthStep + j );TemplatePixelm1n1 = *( I->imageData + (i+1)*I->widthStep + j+1 );TemplatePixelm0n1 = *( I->imageData + (i+1)*I->widthStep + j-1 );if( TemplatePixelm10==0 || TemplatePixeln10==0 || TemplatePixelm01==0 )dis = 0.3;else if( TemplatePixelm1n1==0 || TemplatePixelm0n1==0 )dis = 0.7;elsedis = 1;} else if( i==0 && j==(I->width-1) )           //第一行最后一个点{TemplatePixelm01  = ptr[j-1];TemplatePixeln10  = *( I->imageData + (i+1)*I->widthStep + j );TemplatePixelm0n1 = *( I->imageData + (i+1)*I->widthStep + j-1 );if( TemplatePixeln10==0 || TemplatePixelm01==0 )dis = 0.3;else if( TemplatePixelm0n1==0 )dis = 0.7;elsedis = 1;}else if( j==0 && i>0 && i<(I->height-1) )    //第一列{TemplatePixelm10  = ptr[j+1];TemplatePixeln01  = *( I->imageData + (i-1)*I->widthStep + j );TemplatePixeln10  = *( I->imageData + (i+1)*I->widthStep + j );TemplatePixelm1n1 = *( I->imageData + (i+1)*I->widthStep + j+1 );TemplatePixelm1n0 = *( I->imageData + (i-1)*I->widthStep + j+1 );if( TemplatePixelm10==0 || TemplatePixeln10==0 || TemplatePixeln01==0 )dis = 0.3;else if( TemplatePixelm1n1==0 || TemplatePixelm1n0==0 )dis = 0.7;elsedis = 1;}else if( i>0 && i<(I->height-1) && j==(I->width-1) )     //最后一列{TemplatePixelm01  = ptr[j-1];TemplatePixeln01  = *( I->imageData + (i-1)*I->widthStep + j );TemplatePixeln10  = *( I->imageData + (i+1)*I->widthStep + j );TemplatePixelm0n1 = *( I->imageData + (i+1)*I->widthStep + j-1 );TemplatePixelm0n0 = *( I->imageData + (i-1)*I->widthStep + j-1 );if( TemplatePixeln10==0 || TemplatePixelm01==0 || TemplatePixeln01==0 )dis = 0.3;else if( TemplatePixelm0n1==0 || TemplatePixelm0n0==0 )dis = 0.7;elsedis = 1;}else if( j==0 && i==(I->height-1) )    //最后一行最后一个点{TemplatePixelm10  = ptr[j+1];TemplatePixeln01  = *( I->imageData + (i-1)*I->widthStep + j );TemplatePixelm1n0 = *( I->imageData + (i-1)*I->widthStep + j+1 );if( TemplatePixelm10==0 || TemplatePixeln01==0 )dis = 0.3;else if( TemplatePixelm1n0==0 )dis = 0.7;elsedis = 1;}else if( j>0 && j<(I->width-1) && i==(I->height-1) )    //最后一行{TemplatePixelm10  = ptr[j+1];TemplatePixelm01  = ptr[j-1];TemplatePixeln01  = *( I->imageData + (i-1)*I->widthStep + j );TemplatePixelm1n0 = *( I->imageData + (i-1)*I->widthStep + j+1 );TemplatePixelm0n0 = *( I->imageData + (i-1)*I->widthStep + j-1 );if( TemplatePixelm10==0 || TemplatePixeln01==0 || TemplatePixelm01==0 )dis = 0.3;else if( TemplatePixelm1n0==0 || TemplatePixelm0n0==0 )dis = 0.7;elsedis = 1;}else if( j==(I->width-1) && i==(I->height-1) )    //最后一行最后一个点{TemplatePixelm01  = ptr[j-1];TemplatePixeln01  = *( I->imageData + (i-1)*I->widthStep + j );TemplatePixelm0n0 = *( I->imageData + (i-1)*I->widthStep + j-1 );if( TemplatePixeln01==0 || TemplatePixelm01==0 )dis = 0.3;else if( TemplatePixelm0n0==0 )dis = 0.7;elsedis = 1;}else{TemplatePixelm10  = ptr[j+1];TemplatePixelm01  = ptr[j-1];TemplatePixeln01  = *( I->imageData + (i-1)*I->widthStep + j );TemplatePixeln10  = *( I->imageData + (i+1)*I->widthStep + j );TemplatePixelm1n0 = *( I->imageData + (i-1)*I->widthStep + j+1 );TemplatePixelm0n0 = *( I->imageData + (i-1)*I->widthStep + j-1 );TemplatePixelm1n1 = *( I->imageData + (i+1)*I->widthStep + j+1 );TemplatePixelm0n1 = *( I->imageData + (i+1)*I->widthStep + j-1 );if( TemplatePixeln01==0 || TemplatePixelm01==0 || TemplatePixelm10==0 || TemplatePixeln10==0 )dis = 0.3;else if( TemplatePixelm0n0==0 || TemplatePixelm1n0==0 || TemplatePixelm0n1==0 || TemplatePixelm1n1==0 )dis = 0.7;elsedis = 1;}}*(Dist->imageData + i*Dist->widthStep + j) = (uint8)(dis*255);}}}void dist_match(IplImage* src_img, IplImage* Dist,double MinMatch, CvPoint* pt, long* Na, long* Nb)  //距离匹配{int i,j,m,n;double SigmaGT;uint8 SrcValue;double DistValue;double Match;for ( i=0; i<(src_img->height - Dist->height); i++ ){for ( j=0; j<( src_img->width - Dist->width ); j++ ){SigmaGT = 0;*Na = 0;for( m=0; m<Dist->height; m++ ){for( n=0; n<Dist->width; n++ ){SrcValue  = *( src_img->imageData + (i+m)*src_img->widthStep +j+n );if(SrcValue==0){DistValue = (double)*( Dist->imageData +m*Dist->widthStep + n )/255;SigmaGT += DistValue;(*Na)++;}}}if( (*Na) > (*Nb) ){Match = ( SigmaGT + (*Na) - (*Nb) )/( (*Na) + (*Nb) );}else{Match = ( SigmaGT + (*Nb) - (*Na) )/( (*Na) + (*Nb) );}if( Match < MinMatch ){MinMatch = Match;                //距离匹配的最小值就是匹配的位置pt->x = j;pt->y = i;}}}}int _tmain(int argc, _TCHAR* argv[]){IplImage* src_img, *temp_img;                                 //定义变量double MinMatch = 1000;CvPoint MatchPoint = cvPoint(1,1);long Na=0,Nb=0;//像素0的个数src_img  = cvLoadImage("Images/距离变换.bmp");                 //读入两幅图temp_img = cvLoadImage("Images/距离变换模板.bmp");AllocateImage( src_img, temp_img );cvSplit( src_img, src_gray1, src_gray2, src_gray3, 0);        //将两幅三通道图像分解为3幅单通道图像    cvSplit( temp_img, temp_gray1, temp_gray2, temp_gray3, 0);CalTemplateDist(temp_gray1, Dist, &Nb);dist_match(src_gray1, Dist, MinMatch, &MatchPoint, &Na, &Nb);cvRectangle(src_img, MatchPoint, cvPoint(MatchPoint.x+49, MatchPoint.y+39), cvScalar(0, 0, 255, 0), 1,8,0);cvNamedWindow("my picture",CV_WINDOW_AUTOSIZE);      cvNamedWindow("my template",CV_WINDOW_AUTOSIZE);cvNamedWindow("my Dist",CV_WINDOW_AUTOSIZE);cvShowImage("my picture",src_img);                 cvShowImage("my template",temp_gray1);cvShowImage("my Dist",Dist);cvWaitKey(0);      cvReleaseImage(&src_img);      cvReleaseImage(&temp_img);      cvReleaseImage(&src_gray1);      cvReleaseImage(&src_gray2);      cvReleaseImage(&src_gray3);      cvReleaseImage(&temp_gray1);      cvReleaseImage(&temp_gray2);      cvReleaseImage(&temp_gray3); cvDestroyWindow("my picture");      cvDestroyWindow("my template");  return 0;}


0 0
原创粉丝点击