opencv学习笔记之十五——最小外接矩形(RotatedRect返回角度angle问题)

2023-10-30

最近在看一个车牌识别开源项目时,对其中RotatedRect的角度属性理解得不清楚,也查找了大量博客,得出了基本结论,最后通过实验进一步进行了验证。

RotatedRect该类表示平面上的旋转矩形,有三个属性:

  1. 矩形中心点(质心)
  2. 边长(长和宽)
  3. 旋转角度

旋转角度angle的范围为[-90,0),当矩形水平或竖直时均返回-90,请看下图:

来源:https://blog.csdn.net/qq_24237837/article/details/77850496

看了这幅图,我明白了一些,但还是有疑虑,这个角度如何产生?究竟是那条边(宽?高?)与哪条坐标系的角度呢?矩形的宽和高究竟如何确定?

带着这个疑问,继续查找,下面的博客给出了解释(图均来自该博客):

也就是说,opencv的原点在左上角,横向为x轴,纵向为y轴,将x轴逆时针转动,碰到的第一条边(延长线)就为宽(Winth),而与之所成角度就为angle。那么问题又来了,矩形宽不等于高,若宽>高,当x轴逆时针转动碰到的第一条边是短边,将这个短边作为宽Winth,那不是和 宽>高 这个实际情况矛盾么?且看下图:

角度确实已经确定了,但是width“有问题”,当我们算宽高比时,若不加判断,有些情况下(宽>高的实际情况)就会出错(结果相反),那如何解决呢?

当然,opencv这样不区分短长边就是为了照顾正方形。所以计算时我们首先要判断:width/height <1?,若是,则需要交换width和height 的值,这样在后续操作(车牌矫正,数学运算)才不会出错。

为了验证是否是这样我做个小实验,结果如下:

width>height

 

width<height

 

顺便做了个仿射变换:

 

综合上面的内容,角度和边长的确定已经弄清楚了。

我发现学习openCV,仅仅会用函数,只知道参数和属性还不行啊,太容易忘了,两年后真不一定记得呢,何况真正的开发都是要挖源码的,所以我决定以后在调用函数的同时,要看opencv的源码,理解它的实现过程,看这些大牛是如何写代码的,同时会记录在博客上,方便以后查看,嗯,就这样吧。

实验源码:

#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
 void main()
 {
	    //轮廓最小外接矩形的绘制
		Mat srcImg = imread("pen4.jpg");
		//srcImg = srcImg(Rect(10,10,1000,690));
		namedWindow("scr", 0);
		imshow("scr", srcImg);
		Mat dstImg = srcImg.clone();
	    cvtColor(srcImg, srcImg, CV_BGR2GRAY);
	    threshold(srcImg, srcImg, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV); //二值化
	    //medianBlur(srcImg, srcImg, 9);
	    imshow("threshold", srcImg);
	
	    vector<vector<Point>> contours;
		findContours(srcImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
	     Rect boundRect;  //定义外接矩形
	     RotatedRect box; //定义最小外接矩形

		 vector<vector<Point>>::iterator itc = contours.begin();
	     Point2f rect_point[4];
		 int i = 0;
     for (; itc!=contours.end(); itc++)
		    {  
		 
		         box = minAreaRect(Mat(*itc));  //计算每个轮廓最小外接矩形(旋转)
				 boundRect = box.boundingRect();
				 //boundRect = boundingRect(Mat(*itc));
		         circle(dstImg, Point(box.center.x, box.center.y), 5, Scalar(255,0, 0), -1, 8);  //绘制最小外接矩形的中心点
				// rectangle(dstImg, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar(0, 255, 0), 2, 8);
				 rectangle(dstImg, boundRect.tl(), boundRect.br() , Scalar(0, 255, 0), 3, 8);
				 box.points(rect_point);  //把最小外接矩形四个端点复制给rect数组
		        for (int j = 0; j<4; j++)
			         {
					line(dstImg, rect_point[j], rect_point[(j + 1) % 4], Scalar(0, 0, 255), 3, 8);  //绘制最小外接矩形每条边
		             }
				cout << "angle " << i << " :" << box.angle << endl;
				cout << "width " << i << " :" << box.size.width << endl;
				cout << "height " << i << " :" << box.size.height << endl<<endl;
				char width[20], height[20];
				sprintf(width, "width=%0.2f", box.size.width);//
				sprintf(height, "height=%0.2f", box.size.height);//
				putText(dstImg, width, box.center, CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 0, 255));
				putText(dstImg, height, box.center + Point2f(0, 20), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 0, 255));
	     }
	 namedWindow("rec_dst", 0);
	 imshow("rec_dst", dstImg);

		
		//旋转校正
		float angle_rotation;
		if ((box.size.width / box.size.height) < 1)
			angle_rotation = 90 + box.angle;//正数,逆时针旋转
		else
			angle_rotation = box.angle; //负数,顺时针旋转

		double scale = 0.78;//缩放比例
		Mat rot_m = getRotationMatrix2D(box.center,angle_rotation,scale);//获得旋转矩阵
		warpAffine(dstImg, dstImg, rot_m, dstImg.size());//仿射变换

	    namedWindow("dst", 0);
		imshow("dst", dstImg);
		
	     waitKey(0);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv学习笔记之十五——最小外接矩形(RotatedRect返回角度angle问题) 的相关文章

  • 使用相位相关和对数极坐标变换获得旋转位移

    我一直在编写一个脚本 它使用 cv2 计算两个图像之间的旋转位移phaseCorrelate method 我有两张图像 第二张是第一张图像的 90 度旋转版本 加载图像后 我将它们转换为对数极坐标 然后将它们传递到phaseCorrela
  • 在 Python 3.5 64 位上通过 pip 安装 OpenCV

    我尝试安装 OpenCV 但找不到任何合适的 pip 软件包 我决定上网查找有关如何安装它的官方文档 并发现this https opencv python tutroals readthedocs io en latest py tuto
  • 如何使用 OpenCV 检测图像帧中的对象?

    我正在使用 Raspberry Pi 开发一个漫游器 它将清扫房间并捡起掉落在地上的物体 为了检测物体 我使用了在流动站操作开始时拍摄的参考图像 以及每 10 秒单击一次的图像 新图像 为了确定图像帧是否发生变化 我在参考图像和新图像之间进
  • 计算两个描述符之间的距离

    我正在尝试计算已计算的两个描述符之间的距离 欧几里得或汉明 问题是我不想使用匹配器 我只想计算两个描述符之间的距离 我正在使用 OpenCV 2 4 9 并且我的描述符存储在 Mat 类型中 Mat descriptors1 Mat des
  • 相机标定(OpenCV 2.3)-如何使用畸变参数?

    我有一组带有一些附加标记的刚体图像 我在这些标记之一中定义了一个原点坐标系 我想获得该坐标系与在相机原点定义的坐标系之间的旋转和平移 我尝试了一段时间 POSIT 以下this http goo gl cUYYt 但从未获得可接受的结果 直
  • Opencv matchTemplate 和 np.where():仅保留唯一值

    继带有马里奥硬币的 opencv 教程 https opencv python tutroals readthedocs io en latest py tutorials py imgproc py template matching p
  • Opencv未找到所有轮廓

    我试图找到该图像的轮廓 但是该方法查找轮廓只返回1轮廓 轮廓突出显示image 2 我正在努力寻找all外部轮廓就像这些圆圈 里面有数字 我究竟做错了什么 我可以做什么来实现它 image 1 image 2 以下是我的代码的相关部分 th
  • 使用 opencv warpPerspective() 生成道路的自上而下视图

    我正在尝试实施逆透视映射计算与道路上另一辆车的距离 我知道在应用该函数之前我需要生成一个包含源点和目标点的变换矩阵warpPerspective 但我不知道如何计算目的地点 我在这个论坛和其他网站中搜索 但无法将第一张图片转换为第二张图片
  • 如何在opencv python中为图像添加边框

    如果我有如下图所示的图像 如何在图像周围添加边框 以便最终图像的整体高度和宽度增加 但原始图像的高度和宽度保持在中间 下面的代码添加了一个大小恒定的边框10像素到原始图像的所有四个边 对于颜色 我假设您想要使用背景的平均灰度值 这是我根据图
  • 如何设置K-means openCV c++的初始中心

    我正在尝试使用 OpenCv 和 Kmeans 对图像进行分割 我刚刚实现的代码如下 include opencv2 objdetect objdetect hpp include opencv2 highgui highgui hpp i
  • 如何计算图像中的 RGB 或 HSV 通道组合?

    我使用 python opencv 加载形状为 30 100 3 的图像 现在想要按颜色计算所有颜色的频率 我不是指单个通道 而是指通道组合 含义 3 个频道列表 例如 255 0 0 表示红色 255 255 0 表示黄色 100 100
  • 如何将 mat 转换为 array2d

    我为dlib http dlib net face landmark detection ex cpp html那里的面部地标代码使用 array2d 来获取图像 但我喜欢使用 Mat 读取图像并转换为 array2d 因为 dlib 仅支
  • 如何在 OpenCV 中从 YUV 文件读取帧?

    如何在 OpenCV 中从 YUV 文件读取帧 我编写了一个非常简单的 python 代码来从二进制文件读取 YUV NV21 流 import cv2 import numpy as np class VideoCaptureYUV de
  • 创建 OpenCV 的 mouseCallback 函数的基于类的实现时遇到问题

    正如标题所示 我在基于类的 C 结构中实现 OpenCV 的 mouseCallback 函数时遇到了一些麻烦 请允许我解释一下 我定义了一个名为 BriskMatching 的类 在其中创建了一个名为 mouseCallback 的成员函
  • minAreaRect OpenCV 返回的裁剪矩形 [Python]

    minAreaRectOpenCV 中返回一个旋转的矩形 如何裁剪矩形内图像的这部分 boxPoints返回旋转矩形的角点的坐标 以便可以通过循环框内的点来访问像素 但是在 Python 中是否有更快的裁剪方法 EDIT See code在
  • 如何使用 python、openCV 计算图像中的行数

    我想数纸张 所以我正在考虑使用线条检测 我尝试过一些方法 例如Canny HoughLines and FLD 但我只得到处理过的照片 我不知道如何计算 有一些小线段就是我们想要的线 我用过len lines or len contours
  • OpenCV 错误:connectedComponents_sub1 中断言失败 (L.channels() == 1 && I.channels() == 1) [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我在 OpenCV python 中遇到以下错误 并用 google 搜索了很多 但无法解决 如果有人能为我提供一些线索
  • OpenCV 跟踪器:模型未在函数 init 中初始化

    在视频的第一帧 我运行一个对象检测器 它返回对象的边界框 如下所示
  • iOS 上的 OpenCV - VideoCapture 属性始终返回 1

    我一直在尝试构建一个简单的 OpenCV iOS 应用程序 该应用程序从捆绑包中加载视频并查询其帧数 持续时间等 然后它将尝试从中获取各个帧 不幸的是 当我使用VideoCapture类中 所有属性返回值 1 然后我尝试导航到frame 1
  • 同时从多个流中捕获、最佳方法以及如何减少 CPU 使用率

    我目前正在编写一个应用程序 该应用程序将捕获大量 RTSP 流 在我的例子中为 12 个 并将其显示在 QT 小部件上 当我超过大约 6 7 个流时 问题就会出现 CPU 使用率激增并且出现明显的卡顿 我认为它不是 QT 绘制函数的原因是因

随机推荐

  • R语言介绍

    1 R的统计计算和绘图功能十分强大 2 R是一种区分大小写的解释型语言 R的赋值符号是 lt 而不是传统的 号 3 x lt rnorm 5 表示了一个名为x的向量对象 它包含5个来自标准正态分布的随机偏差 4 注释是有 开头 再 之后的任
  • 使用canvas进行图片压缩(前端图片压缩核心处理)

    一 原理 实际上就是利用canvas进行重新绘制 1 先将图片的file文件转成baseURL 2 创建一个image标签去接收文件获取图片的宽高和比例 3 创建canvas画布设置画布的大小 4 将图片绘制到canvas上面 5 对can
  • vue-json-viewer展示JSON内容

    文章目录 01 前言 02 接口内容预处理 03 json viewer使用 01 前言 最近写的一个小案例 需要将接口返回的JSON内容显示在页面上 要求是要和控制台返回的JSON内容一样能点击展开显示或者关闭 当时只知道处理内容格式 后
  • [AHK]输入法状态提示,中文状态提示“中”,英文状态提示“EN”

    输入法状态提示 中文状态提示 中 英文状态提示 EN 切换中英文状态的时候 或者用鼠标切换到另一个编辑窗口的时候再次提示 循环如此 功能 输入法状态提示 环境 win10 搜狗输入法 输入法状态切换用默认的shift键 作者 sunwind
  • 【100天精通Python】Day52:Python 数据分析_Numpy入门基础与数组操作

    目录 1 NumPy 基础概述 1 1 NumPy的主要特点和功能 1 2 NumPy 安装和导入 2 Numpy 数组 2 1 创建NumPy数组 2 2 数组的形状和维度 2 3 数组的数据类型 2 4 访问和修改数组元素 3 数组操作
  • s7300的db块详细说明_s7-300与s7-200的mpi通信中db块的详细使用

    哪位有s7 300与s7 200的mpi通信中db块与v区对应详细资料 另外我想问一下想用组态软件与s7 300做mpi通信 然后用e277模块与s7 300做dp通信同时组态软件也能访问s 200不知道可不可以 硬 软件组态方面应该怎样连
  • vim的超详细使用方法

    文章目录 vim的四种模式 命令模式详解 移动光标 快速定位光标 复制 粘贴 剪切和删除 撤销和恢复 编辑模式详解 底行模式详解 保存和退出 文件内容的替换 显示行号 paste 查找和搜索 可视化模式 批量注释 批量去注释 vim是史上最
  • VC6.0无法安装,老是未响应

    今天我安装VC6 0 然后发现老是安装的进候 刚进去就程序未响应 特别的郁闷 弄了好多次 开始是怀疑是安装程序的问题 后来我换了一个版本 还是不可以 最后想想可能是因为我的WINDOWS分区的原因 因为我的系统本身是VISTA的 后来装双系
  • 利用傅立叶变换进行图像处理的代码演示

    前面有篇文件介绍过使用DCT 离散余弦 变换进行图像处理的例子 Matlab一探DCT IDCT变换在图像压缩中的应用 tugouxp的专栏 CSDN博客绝大多数图像都有一个共同特征 平坦区域和内容缓慢变化的区域占据一幅图像的大部分 而细节
  • Win11蓝屏代码IRQL NOT LESS OR EQUAL的处理方法

    蓝屏错误IRQL NOT LESS OR EQUAL是用户常见的系统故障了 升级到Win11新系统也遇到了同样的问题 那么Win11蓝屏问题IRQL NOT LESS OR EQUAL要如何解决 下面就来看看小编整理的解决办法 什么是 IR
  • Java 8: 元空间(Metaspace)

    前言 很多开发者都在其系统中见过 java lang OutOfMemoryError PermGen space 这一问题 这往往是由类加载器相关的内存泄漏以及新类加载器的创建导致的 通常出现于代码热部署时 相对于正式产品 该问题在开发机
  • 解决报错:错误1130- Host xxx is not allowed to connect to this MariaDb server

    在云服务器上面搭建了MariaDb MariaDB是MySQL源代码的一个分支 但是远程链接不上 首先 你要确保服务器安全组3306端口已经开放 在确保端口开放的情况下 如果出现错误代码1130 Host xxx is not allowe
  • SuperPoint 论文详解

    SuperPoint 该论文是 magic leap 公司在18年的一篇工作 而且提供了代码 基于 pytorch 的 不过遗憾的是训练代码和相应的渲染的训练数据没提供 主要思路 本文提出了一个自监督的方式去训练网络来提取特征点以及计算描述
  • 【LoadRunner】解决LR11无法录制Chrome浏览器脚本问题

    LoadRunner 解决LR11无法录制Chrome浏览器脚本问题 LoadRunner录制脚本时 遇到高版本的IE FireFox 或者Chrome浏览器 会出现无法录制脚本的问题 下面就来讲一下如何利用LR自带的wplus init
  • tflearn anaconda 安装过程记录

    准备工作 gcc升级为4 8 2glibc升级为2 18 opt xxx xxx components ficlient bigdata env 里加入 export LD LIBRARY PATH usr local lib usr lo
  • SpringBoot调取OpenAi接口实现ChatGpt功能

    很高兴和大家分享我实现的一个小项目 利用 Spring Boot 实现了一个 ChatGpt 对话系统 在本文中 我将详细介绍这个项目的实现步骤 以及代码实现 什么是 ChatGpt ChatGpt 是一种基于 GPT 技术的对话系统 能够
  • 剑指offer45 把数组排成最小的数

    目录 题目链接 解法1 调用sort 解法2 冒泡排序的扩展 题目链接 链接 其实这道题 大概看完就知道是一个排序的问题 无非就是数组中的元素以一个合适的位置排好序 这样从头加到尾 组成的整体数字最小 题目中也暗示你排序问题了 个人捉摸了一
  • linux系统启动过程(方便记忆步骤&详细步骤)

    linux系统的启动过程 大致可以分为五个阶段 内核的引导 运行init 系统初始化 建立终端 用户登录系统 大致步骤 1 内核的引导 操作系统 gt boot 2 运行init 操作系统 gt boot gt init进程 配置文件 et
  • Wix toolset打包工具介绍

    Wix Toolset工具目前是windows平台应用打包比较好用的工具 最大的两个优点是功能全面和免费软件 下面来介绍一下这个软件 Wix Toolset官网 1 Wix的核心是一组build工具 Wix来生成windows安装包的理念跟
  • opencv学习笔记之十五——最小外接矩形(RotatedRect返回角度angle问题)

    最近在看一个车牌识别开源项目时 对其中RotatedRect的角度属性理解得不清楚 也查找了大量博客 得出了基本结论 最后通过实验进一步进行了验证 RotatedRect该类表示平面上的旋转矩形 有三个属性 矩形中心点 质心 边长 长和宽