圆形环绕字 从直角坐标到极坐标的转换
极坐标通常用于校正图像中的圆形物体或者包含在圆环中的物体。
如上图所示 : 设原图变换的中心坐标(即圆心坐标)为 (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;
}
作者: 小马_xiao
出处:http://www.cnblogs.com/xiaomaLV2/>
关于作者:专注halcon\opencv\机器视觉
本文版权归作者,未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接