OpenCV:椭圆上点的计算方程(2)

    使用一个仿射变换

//调整椭圆边缘到标准椭圆;在角度方向上进行拉伸 //angleOfDip 为椭圆的偏斜角,弧度值! //增加边界检查 template <class T1,class T2> float AdjustEllipseEdge( std::vector<std::pair< T1, T2 > > &closeEdgeIn, std::vector<std::pair< T1, T2 > > &closeEdgeOut, const cv::RotatedRect &ecf, const cv::Point2f &rfCentroidS, const double angleOfDipSrc, const int ww, const int hh) { assert(closeEdgeIn.size() == closeEdgeOut.size() );            int w = ww -1;            int h = hh -1;            const cv::Point2f rfCentroid = ecf.center;            //cv::Point2f rfCentroid(0,0);            std::vector< double > angleListS;//为点椭圆角度,用于求取 椭圆点到中心的距离            angleListS.resize( closeEdgeIn.size() );            int vOrH = 0;//水平或者竖直?            vOrH = ecf.size.width > ecf.size.height? 0:1;//若0,则为V;或者为1,水平            double angleOfDip = 0;            if (0 == vOrH )            {//若为水平//width 的倾角                angleOfDip  = angleOfDipSrc;            }            else            {                angleOfDip  = angleOfDipSrc - PI_1_2;            }            //double a = max(ecf.size.height/2.0,ecf.size.width /2.0);//长轴//固定后使用方程            //double b = min(ecf.size.height/2.0,ecf.size.width /2.0);            double b = ecf.size.height/2.0//长轴//固定后使用方程            double a = ecf.size.width /2.0;            double compressFactor = b /a ;//压缩或者缩放因子 #ifdef SHOW_TEMP            cv::Mat canvasSrc = cv::Mat::zeros(200,200,CV_8UC3);            cv::bitwise_not(canvasSrc,canvasSrc);            cv::ellipse(canvasSrc,ecf,cv::Scalar(0,0,255),1,8); #endif            //在此测试,cos计算的代码 #ifdef SHOW_TEMP            cv::RotatedRect ecT = RotatedRect(Point2f(100,100), Size2f(50,100), 30);            std::vector<std::pair< cv::Point2f, double > >  PointCosTest(0);            cvWish::polygon::GetElipseEdge(ecT, PointCosTest, (ecT.size.height + ecT.size.height)/5.0 );            cv::ellipse(canvasSrc, ecT, cv::Scalar(0,0,255), 1, 8);                        for ( int i=0; i< PointCosTest.size(); ++i)            {                cv::circle( canvasSrc, PointCosTest[i].first, 1, cv::Scalar(255,0,0), 1, 8, 0 );                double af = cvWish::cosCv(ecT.center,PointCosTest[i].first);//cosCv出现计算问题                std::cout<< "Cos:" << af<< std::endl;                std::cout<< "Angle:" << PointCosTest[i].second << std::endl;                cv::imshow("PointCosTest",canvasSrc);                cv::waitKey(1);            } #endif            for ( int i=0; i<closeEdgeIn.size(); ++i )            {                closeEdgeIn[i].second  = cvWish::cosCv( rfCentroid, closeEdgeIn[i].first );                //压缩方向                angleListS[i]  = closeEdgeIn[i].second;                angleListS[i] -= angleOfDip;//旋转                angleListS[i]  = angleListS[i]> PI_4_2 ? angleListS[i] - PI_4_2:angleListS[i];                //探测距离                double disPC    = cvWish::disCv(rfCentroid,closeEdgeIn[i].first);                //double alp =  angleListS[i];                //alp =  alp *180/M_PI;                //double disShould = sqrt( b*sin(alp ) *b*sin(alp ) + a*cos(alp) *a*cos(alp) );//公式无误,角度出现问题?                //可能问题,方向角度出现往长轴极点的方向进行压缩,导致生成距离变大。                //计算对应仿射圆的角度                double xDeta =  closeEdgeIn[i].first.x - rfCentroid.x;                double yDeta =  closeEdgeIn[i].first.y - rfCentroid.y;                yDeta /= compressFactor;                //计算角度                double beta = cvWish::cosCv( rfCentroid, cv::Point2f( rfCentroid.x + xDeta, rfCentroid.y+ yDeta ) );                double r = a;                                                                               xDeta  =  r* cos(beta);                yDeta  =  r* sin(beta);                yDeta *= compressFactor;                //直接计算距离                double disShould = sqrt( xDeta*xDeta + yDeta*yDeta );//公式无误,角度出现问题?                std::cout<<"disPc:" <<disPC << std::endl;                std::cout<< "disShould:" << disShould << std::endl; #ifdef SHOW_TEMP                //cv::Mat canvasSrc(100,100,CV_8UC3);                cv::circle(canvasSrc,closeEdgeIn[i].first,1,cv::Scalar(255,0,0),1,8,0);                cv::imshow("edgeEvolution",canvasSrc);                cv::waitKey(1); #endif                //调整点到椭圆上                //adjustPoint2Elipse();                //根据距离 往角度方向上拉伸点//角度其实产生了偏离//偏角使用图片偏角                cvWish::PullPoint2Out( closeEdgeIn[i].first, closeEdgeIn[i].second, ( disPC - disShould ) );                   closeEdgeOut[i].first  = closeEdgeIn[i].first;                ////已确认大于0,此时确认不超边界                closeEdgeOut[i].first.x = min(closeEdgeOut[i].first.x,w);                closeEdgeOut[i].first.y = min(closeEdgeOut[i].first.y,h);                closeEdgeOut[i].second = closeEdgeIn[i].second; #ifdef SHOW_TEMP                cv::circle(canvasSrc,closeEdgeOut[i].first,1,cv::Scalar(0,255,0),1,8,0);                cv::imshow("edgeEvolution",canvasSrc);                cv::waitKey(1); #endif            }            return 1.0;        }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/828cf9678cfb70b2199b79d816ba77bc.html