![](https://i-blog.csdnimg.cn/blog_migrate/339b0cf4ab4d55b81f7f51d159212f3a.jpeg)
极坐标通常用于校正图像中的圆形物体或者包含在圆环中的物体。
如上图所示 : 设原图变换的中心坐标(即圆心坐标)为 (Mr,Mc),图像上一点(r,c)极坐标变换后为(d,theta)
则 d = sqrt( (r - Mr) * (r - Mr) + (c - Mc ) * (c -Mc) )
theta = atan2( - (r - Mr) / (c - Mc))
其反变换形式为 r = Mr - d sin(theta)
c= Mc + d cos(theta)
本程序基于opencv2.3
// polar.cpp : 定义控制台应用程序的入口点。
//
# include "stdafx.h"
# include "highgui.h"
# include "cv.h"
# include "cxcore.h"
# ifdef DEBUG
# pragma comment(lib, " opencv_core231d.lib")
# pragma comment(lib, "opencv_features2d231d.lib")
# pragma comment(lib, "opencv_flann231d.lib")
# pragma comment(lib, "opencv_gpu231d.lib")
# pragma comment(lib, "opencv_highgui231d.lib")
# pragma comment(lib, "opencv_imgproc231d.lib")
# else
# pragma comment(lib, "opencv_core231.lib")
# pragma comment(lib, "opencv_features2d231.lib")
# pragma comment(lib, "opencv_flann231.lib")
# pragma comment(lib, "opencv_gpu231.lib")
# pragma comment(lib, "opencv_highgui231.lib")
# pragma comment(lib, "opencv_imgproc231.lib")
# endif
/*
函数:polar
功能:获取极坐标变换图像尺寸
参数:
anglestart angleend 起止角度 [in]
radiusstart radiusend 起止半径[in]
accuracy 角度精度 [in]
nwidth 宽 [out]
nheight 高 [out]
注:nwidth 表示角度
nheight 表示半径
*/
int getpolarsize( int anglestart, int angleend, int radiusstart, int radiusend , float accuracy, int &nwidth , int &nheight)
{
//if(radiusend <0 || radiusstart < 0 || radiusstart > radiusend ||
// anglestart <0 || angleend < 0 || anglestart> angleend )
// return 0;
nheight = radiusend - radiusstart;
nwidth = ( int)( 1. 0 * (angleend - anglestart) / accuracy);
//nwidth = (int)(2 * CV_PI * radiusend);
return 1;
}
/*
函数:polar
功能:直角坐标转到极坐标
参数:im_src 源图像 [in]
im_dst 目的图像 [out]
centerx centery 圆心坐标 [in]
anglestart angleend 起止角度 [in]
radiusstart radiusend 起止半径[in]
accuracy 角度精度 [in]
注:nwidth 表示角度
nheight 表示半径
*/
void polar(IplImage * im_src ,IplImage *im_dst , int centerx , int centery , int anglestart, int angleend, int radiusstart, int radiusend , float accuracy)
{
float d = 0. 0; // 点到圆中心的距离
float theta = 0. 0; // 角度
int nsrcwidth =im_src - >width;
int nsrcheight = im_src - >height;
int nsrcwidthstep = im_src - >widthStep;
int ndstwisdthstep = im_dst - >widthStep;
unsigned char *psrcpiexl = NULL;
unsigned char *pdstpiexl = NULL;
im_dst - >origin = 1;
//src(x) = centerx - d * sin(theta)
//src(y) = centery + d * cos(theta)
int nsrcx = 0 ;
int nsrcy = 0 ;
for ( float i = radiusstart ;i < radiusend ; ++i)
{
for ( float j = ( float)anglestart ; j <( float)angleend ; j +=accuracy)
{
nsrcx = 0 ;
nsrcy = 0 ;
nsrcx = centerx - cvRound(i * sin(j * CV_PI / 180));
nsrcy = centery + cvRound(i * cos(j * CV_PI / 180));
// printf("i:%d j:%f x:%d y:%d\n" ,cvRound(i),j,cvRound(i * sin(j)),cvRound(i * cos(j)));
psrcpiexl = ( unsigned char *)(im_src - >imageData + nsrcy * nsrcwidthstep + nsrcx);
pdstpiexl = ( unsigned char *)(im_dst - >imageData + cvRound((i -radiusstart) * ndstwisdthstep) + cvRound((j -anglestart) /accuracy));
*pdstpiexl = *psrcpiexl;
}
}
//
//for (int i = 0 ; i < nsrcheight ; ++i)
//{
// for (int j = 0 ; j < nsrcwidth ; ++j)
// {
//
// // d = 0.0 ;
// // theta = 0.0;
// // //1. 计算点到圆心距离d ,角度theta
// // d = sqrt( 1.0*(i-centery)*(i-centery) + (1.0*j-centerx)*(j-centerx));
// // theta = atan2(-1.0 * (i - centery) ,1.0*(j - centerx)) + 180;
// // if (d< radiusstart || d > radiusend || theta < anglestart || theta > angleend)
// // continue;
// // theta = theta / accuracy;
// //
// printf("d :%d theta :%d\n",(int)d,(int)theta);
// // // 2 . 映射
// // psrcpiexl = (unsigned char *)(im_src->imageData + i * nsrcwidthstep + j);
// // pdstpiexl = (unsigned char *)(im_dst->imageData + (int)((d-radiusstart) * ndstwisdthstep) +(int)(theta-1.0*anglestart/accuracy));
// pdstpiexl = (unsigned char *)(im_dst->imageData + (((int)d-radiusstart) * ndstwisdthstep) +(int)(theta-anglestart/accuracy));
// // if (*psrcpiexl !=255)
// // continue;
// // *pdstpiexl = *psrcpiexl;
// }
//}
}
int _tmain( int argc, _TCHAR * argv[])
{
IplImage * im_src = cvLoadImage( "POLRA.jpg",CV_LOAD_IMAGE_GRAYSCALE);
IplImage * im_show = cvCreateImage(cvGetSize(im_src), 8, 3);
cvConvertImage(im_src,im_show);
//1.二值化
cvNot(im_src,im_src);
IplImage * im_threshod = cvCreateImage(cvGetSize(im_src), 8, 1);
cvThreshold(im_src,im_threshod, 0, 255,CV_THRESH_OTSU);
//2.闭运算核*50 将字体连成一片
IplImage * im_close = cvCreateImage(cvGetSize(im_src), 8, 1);
int elementx = 50;
int elementy = 50;
IplConvKernel * element = cvCreateStructuringElementEx(elementx ,elementy,elementx / 2,elementy / 2,CV_SHAPE_RECT);
cvMorphologyEx(im_threshod,im_close,NULL,element,CV_MOP_CLOSE);
cvReleaseStructuringElement( &element);
cvShowImage( "close",im_close);
//3.查找轮廓
CvMemStorage *storage = cvCreateMemStorage( 0);
CvSeq * contour = NULL;
cvFindContours(im_close,storage, &contour);
CvPoint2D32f center;
float radius;
for (;contour != 0 ; contour =contour - >h_next)
{
// 4 . 最小外界圆
cvMinEnclosingCircle(contour, ¢er, &radius);
cvCircle(im_show,cvPointFrom32f(center),( int)radius,CV_RGB( 255, 0, 0));
printf( "x:%d y:%d r:%d\n",( int)center.x,( int)center.y,( int)radius);
}
int nwidth = 0;
int nheight = 0 ;
getpolarsize( 0, 360,radius - 50,radius + 50,( float) 0. 4,nwidth,nheight);
IplImage * im_dst = cvCreateImage(cvSize(nwidth,nheight), 8, 1);
cvZero(im_dst);
polar(im_threshod,im_dst,center.x,center.y, 0, 360,radius - 50,radius + 50,( float) 0. 4);
cvShowImage( "polar",im_dst);
cvShowImage( "threahold",im_threshod);
cvShowImage( "show",im_show);
cvWaitKey( - 1);
cvReleaseImage( &im_dst);
cvReleaseMemStorage( &storage);
cvReleaseImage( &im_threshod);
cvReleaseImage( &im_src);
cvReleaseImage( &im_show);
return 0;
}
//
# include "stdafx.h"
# include "highgui.h"
# include "cv.h"
# include "cxcore.h"
# ifdef DEBUG
# pragma comment(lib, " opencv_core231d.lib")
# pragma comment(lib, "opencv_features2d231d.lib")
# pragma comment(lib, "opencv_flann231d.lib")
# pragma comment(lib, "opencv_gpu231d.lib")
# pragma comment(lib, "opencv_highgui231d.lib")
# pragma comment(lib, "opencv_imgproc231d.lib")
# else
# pragma comment(lib, "opencv_core231.lib")
# pragma comment(lib, "opencv_features2d231.lib")
# pragma comment(lib, "opencv_flann231.lib")
# pragma comment(lib, "opencv_gpu231.lib")
# pragma comment(lib, "opencv_highgui231.lib")
# pragma comment(lib, "opencv_imgproc231.lib")
# endif
/*
函数:polar
功能:获取极坐标变换图像尺寸
参数:
anglestart angleend 起止角度 [in]
radiusstart radiusend 起止半径[in]
accuracy 角度精度 [in]
nwidth 宽 [out]
nheight 高 [out]
注:nwidth 表示角度
nheight 表示半径
*/
int getpolarsize( int anglestart, int angleend, int radiusstart, int radiusend , float accuracy, int &nwidth , int &nheight)
{
//if(radiusend <0 || radiusstart < 0 || radiusstart > radiusend ||
// anglestart <0 || angleend < 0 || anglestart> angleend )
// return 0;
nheight = radiusend - radiusstart;
nwidth = ( int)( 1. 0 * (angleend - anglestart) / accuracy);
//nwidth = (int)(2 * CV_PI * radiusend);
return 1;
}
/*
函数:polar
功能:直角坐标转到极坐标
参数:im_src 源图像 [in]
im_dst 目的图像 [out]
centerx centery 圆心坐标 [in]
anglestart angleend 起止角度 [in]
radiusstart radiusend 起止半径[in]
accuracy 角度精度 [in]
注:nwidth 表示角度
nheight 表示半径
*/
void polar(IplImage * im_src ,IplImage *im_dst , int centerx , int centery , int anglestart, int angleend, int radiusstart, int radiusend , float accuracy)
{
float d = 0. 0; // 点到圆中心的距离
float theta = 0. 0; // 角度
int nsrcwidth =im_src - >width;
int nsrcheight = im_src - >height;
int nsrcwidthstep = im_src - >widthStep;
int ndstwisdthstep = im_dst - >widthStep;
unsigned char *psrcpiexl = NULL;
unsigned char *pdstpiexl = NULL;
im_dst - >origin = 1;
//src(x) = centerx - d * sin(theta)
//src(y) = centery + d * cos(theta)
int nsrcx = 0 ;
int nsrcy = 0 ;
for ( float i = radiusstart ;i < radiusend ; ++i)
{
for ( float j = ( float)anglestart ; j <( float)angleend ; j +=accuracy)
{
nsrcx = 0 ;
nsrcy = 0 ;
nsrcx = centerx - cvRound(i * sin(j * CV_PI / 180));
nsrcy = centery + cvRound(i * cos(j * CV_PI / 180));
// printf("i:%d j:%f x:%d y:%d\n" ,cvRound(i),j,cvRound(i * sin(j)),cvRound(i * cos(j)));
psrcpiexl = ( unsigned char *)(im_src - >imageData + nsrcy * nsrcwidthstep + nsrcx);
pdstpiexl = ( unsigned char *)(im_dst - >imageData + cvRound((i -radiusstart) * ndstwisdthstep) + cvRound((j -anglestart) /accuracy));
*pdstpiexl = *psrcpiexl;
}
}
//
//for (int i = 0 ; i < nsrcheight ; ++i)
//{
// for (int j = 0 ; j < nsrcwidth ; ++j)
// {
//
// // d = 0.0 ;
// // theta = 0.0;
// // //1. 计算点到圆心距离d ,角度theta
// // d = sqrt( 1.0*(i-centery)*(i-centery) + (1.0*j-centerx)*(j-centerx));
// // theta = atan2(-1.0 * (i - centery) ,1.0*(j - centerx)) + 180;
// // if (d< radiusstart || d > radiusend || theta < anglestart || theta > angleend)
// // continue;
// // theta = theta / accuracy;
// //
// printf("d :%d theta :%d\n",(int)d,(int)theta);
// // // 2 . 映射
// // psrcpiexl = (unsigned char *)(im_src->imageData + i * nsrcwidthstep + j);
// // pdstpiexl = (unsigned char *)(im_dst->imageData + (int)((d-radiusstart) * ndstwisdthstep) +(int)(theta-1.0*anglestart/accuracy));
// pdstpiexl = (unsigned char *)(im_dst->imageData + (((int)d-radiusstart) * ndstwisdthstep) +(int)(theta-anglestart/accuracy));
// // if (*psrcpiexl !=255)
// // continue;
// // *pdstpiexl = *psrcpiexl;
// }
//}
}
int _tmain( int argc, _TCHAR * argv[])
{
IplImage * im_src = cvLoadImage( "POLRA.jpg",CV_LOAD_IMAGE_GRAYSCALE);
IplImage * im_show = cvCreateImage(cvGetSize(im_src), 8, 3);
cvConvertImage(im_src,im_show);
//1.二值化
cvNot(im_src,im_src);
IplImage * im_threshod = cvCreateImage(cvGetSize(im_src), 8, 1);
cvThreshold(im_src,im_threshod, 0, 255,CV_THRESH_OTSU);
//2.闭运算核*50 将字体连成一片
IplImage * im_close = cvCreateImage(cvGetSize(im_src), 8, 1);
int elementx = 50;
int elementy = 50;
IplConvKernel * element = cvCreateStructuringElementEx(elementx ,elementy,elementx / 2,elementy / 2,CV_SHAPE_RECT);
cvMorphologyEx(im_threshod,im_close,NULL,element,CV_MOP_CLOSE);
cvReleaseStructuringElement( &element);
cvShowImage( "close",im_close);
//3.查找轮廓
CvMemStorage *storage = cvCreateMemStorage( 0);
CvSeq * contour = NULL;
cvFindContours(im_close,storage, &contour);
CvPoint2D32f center;
float radius;
for (;contour != 0 ; contour =contour - >h_next)
{
// 4 . 最小外界圆
cvMinEnclosingCircle(contour, ¢er, &radius);
cvCircle(im_show,cvPointFrom32f(center),( int)radius,CV_RGB( 255, 0, 0));
printf( "x:%d y:%d r:%d\n",( int)center.x,( int)center.y,( int)radius);
}
int nwidth = 0;
int nheight = 0 ;
getpolarsize( 0, 360,radius - 50,radius + 50,( float) 0. 4,nwidth,nheight);
IplImage * im_dst = cvCreateImage(cvSize(nwidth,nheight), 8, 1);
cvZero(im_dst);
polar(im_threshod,im_dst,center.x,center.y, 0, 360,radius - 50,radius + 50,( float) 0. 4);
cvShowImage( "polar",im_dst);
cvShowImage( "threahold",im_threshod);
cvShowImage( "show",im_show);
cvWaitKey( - 1);
cvReleaseImage( &im_dst);
cvReleaseMemStorage( &storage);
cvReleaseImage( &im_threshod);
cvReleaseImage( &im_src);
cvReleaseImage( &im_show);
return 0;
}