圆形环绕字 从直角坐标到极坐标的转换

 
 
极坐标通常用于校正图像中的圆形物体或者包含在圆环中的物体。
如上图所示 : 设原图变换的中心坐标(即圆心坐标)为 (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,&center,&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;
}
 





posted @ 2012-06-19 16:22  小马_xiaoLV2  阅读(4097)  评论(4编辑  收藏  举报