距离变换

来源:互联网 发布:乔丹生涯场均数据 编辑:程序博客网 时间:2024/05/20 16:01

出处:桑卡, 《图像处理分析与机器视觉》

 

计算全局图像中各个像素点对子图像的距离。

ALALALPAL 

                           Mask  1

 BRPBRBRBR

                           Mask 2

 

1. 将图像进行二值化,子图像值为0,背景为255;

2. 利用Mask 1从左向右,从上到下扫描,p点是当前像素点,q点是Mask 1中AL邻域中的点,D()为距离计算,包括棋盘距离、城市距离和欧式距离。F(p)为p点的像素值,计算

F(p) = min( F(p),  F(q)+D(p,q) ), 其中,q属于AL.

3. 再利用Mask 2从右向左,从下向上扫描,计算

F(p) = min( F(p),  F(q)+D(p,q) ), 其中,q属于BR

4. F(p) 则为距离变换后的图像。

 

代码如下,基于OpenCV 2.4

#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include "math.h"#include <stdio.h>using namespace cv;Mat& DistTran(Mat& I);Mat& NormImage(Mat& I);static float Round(float f){return ( ceil(f)-f > f-floor(f) ) ? floor(f) : ceil(f);}int ChessBoardDist(int x1, int y1, int x2, int y2){return (abs(x1-x2) > abs(y1-y2)) ? abs(x1-x2) : abs(y1-y2);}int CityBlockDist(int x1, int y1, int x2, int y2){return ( abs(x1-x2) + abs(y1-y2) );}float EuclideanDist(int x1, int y1, int x2, int y2){return sqrt( (float)((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) );}int MyMin(int x, int y){return (x < y) ? x : y;}float MyMin(float x, float y){return (x < y) ? x : y;}/** * @function main */int main( int argc, char** argv ){  char* imageName = "test_wushuang.bmp";  Mat image;  image = imread(imageName,1);  if(!image.data)  {  printf("No image data\n");  }  Mat gray_image;  cvtColor( image, gray_image, CV_RGB2GRAY );    DistTran( gray_image );  NormImage( gray_image );    imwrite("EuclideanDist_wushuang.bmp", gray_image);  namedWindow( imageName, CV_WINDOW_AUTOSIZE );  namedWindow( "Gray image", CV_WINDOW_AUTOSIZE );  imshow( imageName, image );  imshow( "Gray image", gray_image );  waitKey(0);    return 0;}Mat& DistTran(Mat& I){    // accept only char type matricesCV_Assert(I.depth() != sizeof(uchar));int channels = I.channels();int nRows = I.rows * channels;int nCols = I.cols;//if (I.isContinuous())//{//nCols *= nRows;//nRows = 1;//}int i,j;uchar* p;uchar* q;//int min = 0;//int dis = 0;float fMin = 0.0;float fDis = 0.0;// pass throuth from top to bottom, left to rightfor( i = 1; i < nRows-1; ++i){p = I.ptr<uchar>(i);for ( j = 1; j < nCols; ++j){/*q = I.ptr<uchar>(i-1);dis = CityBlockDist(i, j, i-1, j-1);min = MyMin( p[j], dis+q[j-1] );dis = CityBlockDist(i, j, i-1, j);min = MyMin( min, dis+q[j] );q = I.ptr<uchar>(i);dis = CityBlockDist(i, j, i, j-1);min = MyMin( min, dis+q[j-1] );q = I.ptr<uchar>(i+1);dis = CityBlockDist(i, j, i+1, j-1);min = MyMin( min, dis+q[j-1] );p[j] = min;*/q = I.ptr<uchar>(i-1);fDis = EuclideanDist(i, j, i-1, j-1);fMin = MyMin( (float)p[j], fDis+q[j-1] );fDis = EuclideanDist(i, j, i-1, j);fMin = MyMin( fMin, fDis+q[j] );q = I.ptr<uchar>(i);fDis = EuclideanDist(i, j, i, j-1);fMin = MyMin( fMin, fDis+q[j-1] );q = I.ptr<uchar>(i+1);fDis = EuclideanDist(i, j, i+1, j-1);fMin = MyMin( fMin, fDis+q[j-1] );p[j] = (uchar)Round(fMin);}}// pass throuth from bottom to top, right to leftfor( i = nRows-2; i > 0; i-- ){p = I.ptr<uchar>(i);for( j = nCols-1; j >= 0; j-- ){/*q = I.ptr<uchar>(i+1);dis = CityBlockDist(i, j, i+1, j);min = MyMin( p[j], dis+q[j] );dis = CityBlockDist(i, j, i+1, j+1);min = MyMin( min, dis+q[j+1] );q = I.ptr<uchar>(i);dis = CityBlockDist(i, j, i, j+1);min = MyMin( min, dis+q[j+1] );q = I.ptr<uchar>(i-1);dis = CityBlockDist(i, j, i-1, j+1);min = MyMin( min, dis+q[j+1] );p[j] = min;*/q = I.ptr<uchar>(i+1);fDis = EuclideanDist(i, j, i+1, j);fMin = MyMin( (float)p[j], fDis+q[j] );fDis = EuclideanDist(i, j, i+1, j+1);fMin = MyMin( fMin, fDis+q[j+1] );q = I.ptr<uchar>(i);fDis = EuclideanDist(i, j, i, j+1);fMin = MyMin( fMin, fDis+q[j+1] );q = I.ptr<uchar>(i-1);fDis = EuclideanDist(i, j, i-1, j+1);fMin = MyMin( fMin, fDis+q[j+1] );p[j] = (uchar)Round(fMin);}}return I;}Mat& NormImage(Mat& I){// accept only char type matricesCV_Assert(I.depth() != sizeof(uchar));int channels = I.channels();int nRows = I.rows * channels;int nCols = I.cols;//if (I.isContinuous())//{//nCols *= nRows;//nRows = 1;//}int i,j;uchar* p;int min = 256;int max = -1;// Do not count the outer boundaryfor( i = 1; i < nRows-1; ++i){p = I.ptr<uchar>(i);for ( j = 1; j < nCols-1; ++j){if( min > p[j] )  min = p[j];if( max < p[j] )  max = p[j];}}for( i = 1; i < nRows-1; ++i){p = I.ptr<uchar>(i);for ( j = 1; j < nCols-1; ++j){p[j] = (p[j] - min) * 255 / (max - min);}}return I;}


 

 

                                        原图                                                                                              棋盘距离变换 

 

 

                                           城市距离变换                                                                               欧式距离变换