热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

结构分析与形状识别(外接矩形旋转角度)

classCV_EXPORTSRotatedRect{public:!variousconstructorsRotatedRect();Rotate
class CV_EXPORTS RotatedRect  
{
public:  
    //! various constructors  
    RotatedRect();  
    RotatedRect(const Point2f& center, const Size2f& size, float angle);  
    RotatedRect(const CvBox2D& box);  
  
    //! returns 4 vertices of the rectangle  
    void points(Point2f pts[]) const;  
    //! returns the minimal up-right rectangle containing the rotated rectangle  
    Rect boundingRect() const;  
    //! conversion to the old-style CvBox2D structure  
    operator CvBox2D() const;  
  
    Point2f center; //< the rectangle mass center  
    Size2f size;    //< width and height of the rectangle  
    float angle;    //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.  
};
RotatedRect::points(Point2f pt[]) const  
{  
    double _angle = angle*CV_PI/180.;  
    float b = (float)cos(_angle)*0.5f;  
    float a = (float)sin(_angle)*0.5f;  
  
    pt[0].x = center.x - a*size.height - b*size.width;  
    pt[0].y = center.y + b*size.height - a*size.width;  
    pt[1].x = center.x + a*size.height - b*size.width;  
    pt[1].y = center.y - b*size.height - a*size.width;  
    pt[2].x = 2*center.x - pt[0].x;  
    pt[2].y = 2*center.y - pt[0].y;  
    pt[3].x = 2*center.x - pt[1].x;  
    pt[3].y = 2*center.y - pt[1].y;  
}                      
#include"iostream"  #include"opencv2/opencv.hpp"    using namespace std;  using namespace cv;    int main()  {      Mat image(200, 200, CV_8UC3, Scalar(0));      RotatedRect rRect(Point2f(100, 100), Size2f(100, 50), 30);        Point2f vertices[4];      //定义矩形的4个顶点      rRect.points(vertices);   //计算矩形的4个顶点      for (int i = 0; i < 4; i++)          line(image, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0));        Rect brect = rRect.boundingRect(); //返回包含旋转矩形的最小矩形      rectangle(image, brect, Scalar(255, 0, 0));      imshow("rectangles", image);      waitKey(0);  }  
RotatedRect是一个存储旋转矩形的类,通常用来存储最小外包矩形函数minAreaRect( )和椭圆拟合函数fitEllipse( )返回的结果。存储的值,完全取决在于函数的返回

            

之前用到OpenCV最小外接矩形去表示一个类椭圆形的高度,特此记录备查。
对给定的 2D 点集,寻找最小面积的包围矩形,使用函数:
CvBox2D  cvMinAreaRect2( const CvArr* points, CvMemStorage* storage=NULL );

   points
   点序列或点集数组
   storage
   可选的临时存储仓
  函数 cvMinAreaRect2 通过建立凸外形并且旋转外形以寻找给定 2D 点集的最小面积的包围矩形。
其中返回的2D盒子定义如下:
1 typedef struct CvBox2D
2 {
3     CvPoint2D32f center; /* 盒子的中心 */
4     CvSize2D32f size; /* 盒子的长和宽 */
5     float angle; /* 水平轴与第一个边的夹角,用弧度表示*/
6 }CvBox2D;

注意夹角 angle 是水平轴逆时针旋转,与碰到的第一个边(不管是高还是宽)的夹角。如下图
                                 
  可用函数 cvBoxPoints(box[count], point); 寻找盒子的顶点
1  void cvBoxPoints( CvBox2D box, CvPoint2D32f pt[4] )
2  {
3      double angle = box.angle*CV_PI/180.
4      float a = (float)cos(angle)*0.5f;
5      float b = (float)sin(angle)*0.5f;

7      pt[0].x = box.center.x - a*box.size.height - b*box.size.width;
8      pt[0].y = box.center.y + b*box.size.height - a*box.size.width;
9      pt[1].x = box.center.x + a*box.size.height - b*box.size.width;
10     pt[1].y = box.center.y - b*box.size.height - a*box.size.width;
11     pt[2].x = 2*box.center.x - pt[0].x;
12     pt[2].y = 2*box.center.y - pt[0].y;
13     pt[3].x = 2*box.center.x - pt[1].x;
14     pt[3].y = 2*box.center.y - pt[1].y;
15 }
简单证明此函数的计算公式:
 
   计算x,由图可得到三个方程式: pt[1].x - pt[0].x = width*sin(angle)
                             pt[2].x - pt[1].x = height*cos(angle)
                             pt[2].x - pt[0].x = 2(box.center.x - pt[0].x)
   联立方程可解得函数里的计算式,算 y 略。
写了个函数绘制CvBox2D
1  void DrawBox(CvBox2D box,IplImage* img)
2  {
3      CvPoint2D32f point[4];
4      int i;
5      for ( i=0; i<4; i++)
6      {
7          point[i].x = 0;
8          point[i].y = 0;
9      }
10     cvBoxPoints(box, point); //计算二维盒子顶点
11     CvPoint pt[4];
12     for ( i=0; i<4; i++)
13     {
14         pt[i].x = (int)point[i].x;
15         pt[i].y = (int)point[i].y;
16     }
17     cvLine( img, pt[0], pt[1],CV_RGB(255,0,0), 2, 8, 0 );
18     cvLine( img, pt[1], pt[2],CV_RGB(255,0,0), 2, 8, 0 );
19     cvLine( img, pt[2], pt[3],CV_RGB(255,0,0), 2, 8, 0 );
20     cvLine( img, pt[3], pt[0],CV_RGB(255,0,0), 2, 8, 0 );



                        
                        
                         
推荐阅读
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
author-avatar
林校帅哥美女排行榜_511
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有