opencv中cv2.minAreaRect函数输出角度问题详解

 更新时间:2022年11月18日 11:46:32   作者:alex1801  
minAreaRect返回的数据包括了矩形的中心点,宽、高,和旋转角度,下面这篇文章主要给大家介绍了关于opencv中cv2.minAreaRect函数输出角度问题的相关资料,需要的朋友可以参考下

前言

网上很多例子都说cv2.minAreaRect函数的输出的角度范围在[-90,0],但是实测输出范围在[0,90]。再进行调研,确定为opencv4.5版本升级改动引起。

cv2.minAreaRect输入:四边形的四个点(不要求顺序)。

输出:最小外接矩形的中心点坐标x,y,宽高w,h,角度anlge,输出形式为元组((x,y),(w,h),anlge),顺序格式不变。

1、4.5版本

4.5版本定义为,x轴顺时针旋转最先重合的边为w,angle为x轴顺时针旋转的角度,angle取值为(0,90]。

cnts, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
rect = cv2.minAreaRect(cnts[0])
box = np.int0(cv2.boxPoints(rect))
print(rect)

输出结果:((201.25, 92.10), (20.93, 101.94), 67.47)

中心点坐标:(201, 92),宽高: (20, 101),角度: 67。

配合旋转函数,可实现框的拉平。旋转函数(逆时针旋转):

import cv2
import numpy as np
 
def rotate(img, angle, center=None, scale=1.0, fill=0, interpolation=cv2.INTER_LINEAR, expand=True):
    if center is not None and expand:
        raise ValueError('`auto_bound` conflicts with `center`')
 
    h, w = img.shape[:2]
    if center is None:
        center = ((w - 1) * 0.5, (h - 1) * 0.5)
    assert isinstance(center, tuple)
 
    matrix = cv2.getRotationMatrix2D(center, angle, scale)
    if expand:
        cos = np.abs(matrix[0, 0])
        sin = np.abs(matrix[0, 1])
        new_w = h * sin + w * cos
        new_h = h * cos + w * sin
        matrix[0, 2] += (new_w - w) * 0.5
        matrix[1, 2] += (new_h - h) * 0.5
        w = int(np.round(new_w))
        h = int(np.round(new_h))
    rotated = cv2.warpAffine(
        img,
        matrix, (w, h),
        flags=interpolation,
        borderValue=fill)
    return rotated

执行旋转:

rotate(img, -23, center=(201, 92), expand=False)

结果:

 角度说明:

角度为x轴顺时针旋转,第一次接触到矩形边界时的值,范围:0~90°,第一次接触的边界为宽,区分方向可以使用宽、高的值来确定。

 角度按逆时针旋转方式调整为:

if rect[1][0] > rect[1][1]: # w > h 
    angle = int(rect[2]) 
else: 
    angle = -(90 - int(rect[2]))

2、4.5之前版本

有网友测试4.1.*,4.2.*,4.3.*,4.4.*下minAreaRect函数的都一样,就是网上常见的角度输出为[-90~0]情况。但是实测python版本4系列的都为上述4.5版情况,可能是c++版本的不同吧。这里补充[-90~0]情况。

rect = cv2.minAreaRect(cnts[0])

rect[0]返回最小外接矩形的中心点,rect[1]为最小外接矩形的宽、高。rect[2]为旋转角度。

宽、高和角度定义如下:角度为x轴沿逆时针旋转遇到的第一个边时的旋转角度,因为是逆时针旋转所以角度为0~-90度。约定:遇到的第一个边为宽、另一个边为高。

补充:opencv ---minAreaRect()计算偏转角度并纠正

  • 此次试验的目的是计算目标图像偏转的角度,在不改变图像尺寸下纠正
  • 这里主要用到minAreaRect()函数和getRotationMatrix2D()函数
  • 先简单的介绍下minAreaRect()函数,本人在这里踩了一些坑,在这里说明一下,如有不妥的地方,大家尽管指正。

函数为minAreaRect(InputArray points) ,InputArray points是所要求最小外接矩形的点集,这个点集不定个数。

这个矩形是可以有偏转角度的,可以与图像的边界不平行。

调用形式:RotatedRect minAreaRect(InputArray points)

  • 角度计算规则:以左上角为原点,X轴逆时针旋转,所得到的第一个角度即为旋转角度,第一条边为最小外接矩形的宽。角度范围[-90,0],当最小外接矩形平行(或垂直)X轴时角度为-90。(跟目标图像的长宽没关系)

顺时针为正,逆时针为负

  • 函数getRotationMatrix2D(Point2f center, double angle, double scale)

参数详解:

Point2f center:表示旋转的中心点

double angle:表示旋转的角度  //这里的角度顺时针为负,逆时针为正

double scale:图像缩放因子

  • 踩坑的地方主要在角度分不清,我总结了一下:

minAreaRect():以X轴正方向为起点,顺时针为正,逆时针为负

getRotationMatrix2D():以X轴正方向为起点,顺时针为负,逆时针为正

下面是一个例子:

#include <iostream>
#include <string>
#include <math.h>
#include <vector>
#include <io.h>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
 
using namespace cv;
using namespace std;
 
int main()
{  
	Mat image = imread("a11.jpg");  
	Mat gaussianimage,grayimage, cannyimage, thresholdimage;
 
//---------------------旋转-----------------
	//计算偏转角度
	GaussianBlur(image, gaussianimage, Size(5, 5), 3, 3);//尽可能多的去除杂质
	Canny(gaussianimage, cannyimage, 50, 150, 3);
	cvtColor(cannyimage, grayimage, CV_GRAY2BGR);
	vector<vector<Point>>vec_point;
	vector<Vec4i>hireachy;
	findContours(cannyimage, vec_point, hireachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
 
	double degree = 0;
	for (size_t i = 0; i < vec_point.size(); i++)
	{
		RotatedRect minrect = minAreaRect(vec_point[i]);//minAreaRect():以X轴正方形为起点,顺时针为正,逆时针为负
		degree = minrect.angle;
		
        //此处目的是为了让目标图像旋转到水平位置
		if (degree > -90 && degree <= -45)
		{
			degree += 90;
		}
		else if (degree >-45 && degree < 0)
		{
			degree;
		}
		else
		{
			degree = 0;
		}		
		cout <<"degree:" << degree << endl;
	}	
 
	//旋转纠正
	Point center = Point(image.cols / 2, image.rows / 2);
	double angle = degree;
	double scale = 1;
	Mat rot(2, 3, CV_32FC1);
	rot = getRotationMatrix2D(center, angle, scale);//getRotationMatrix2D():以X轴正方形为起点,顺时针为负,逆时针为正
	Mat rotimage;
	warpAffine(image, rotimage, rot, image.size());
	namedWindow("rotation", 0);
	resizeWindow("rotation", 800, 600);
	imshow("rotation", rotimage);
}

效果图:

总结

到此这篇关于opencv中cv2.minAreaRect函数输出角度问题的文章就介绍到这了,更多相关opencv cv2.minAreaRect函数输出角度内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • PyCharm中的库Flask安装以及如何使用详解

    PyCharm中的库Flask安装以及如何使用详解

    在学习flask的过程中关于flask安装的过程中遇到了很多的问题,通过自己的摸索和搜寻最终终于能够成功运行,下面这篇文章主要给大家介绍了关于PyCharm中库Flask安装以及如何使用的相关资料,需要的朋友可以参考下
    2023-12-12
  • Python基于socket模块实现UDP通信功能示例

    Python基于socket模块实现UDP通信功能示例

    这篇文章主要介绍了Python基于socket模块实现UDP通信功能,结合实例形式分析了Python使用socket模块实现IPV4协议下的UDP通信客户端与服务器端相关操作技巧,需要的朋友可以参考下
    2018-04-04
  • python识别图标并点击功能实现

    python识别图标并点击功能实现

    这篇文章主要介绍了python识别图标并点击功能实现,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-07-07
  • python自动重试第三方包retrying模块的方法

    python自动重试第三方包retrying模块的方法

    retrying是一个python的重试包,可以用来自动重试一些可能运行失败的程序段。这篇文章主要介绍了python自动重试第三方包retrying的方法,需要的朋友参考下吧
    2018-04-04
  • python实现广度优先搜索过程解析

    python实现广度优先搜索过程解析

    这篇文章主要介绍了python实现广度优先搜索过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • ansible作为python模块库使用的方法实例

    ansible作为python模块库使用的方法实例

    ansible是一个python package,是个完全的unpack and play软件,对客户端唯一的要求是有ssh有python,并且装了python-simplejson包,部署上简单到发指。下面这篇文章就给大家主要介绍了ansible作为python模块库使用的方法实例,需要的朋友可以参考借鉴。
    2017-01-01
  • Python如何将LabelMe生成的JSON格式转换成YOLOv8支持的TXT格式

    Python如何将LabelMe生成的JSON格式转换成YOLOv8支持的TXT格式

    标注工具 LabelMe 生成的标注文件为JSON格式,而YOLOv8中支持的为TXT文件格式,下面给大家分享Python如何将LabelMe生成的JSON格式转换成YOLOv8支持的TXT格式,感兴趣的朋友跟随小编一起看看吧
    2024-05-05
  • flask框架json数据的拿取和返回操作示例

    flask框架json数据的拿取和返回操作示例

    这篇文章主要介绍了flask框架json数据的拿取和返回操作,结合实例形式分析了flask框架针对json格式数据的解析、数据库操作与输出等相关操作技巧,需要的朋友可以参考下
    2019-11-11
  • python编程使用selenium模拟登陆淘宝实例代码

    python编程使用selenium模拟登陆淘宝实例代码

    这篇文章主要介绍了python编程使用selenium模拟登陆淘宝实例代码,涉及selenium的简介及Windows下的安装,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Python+OpenCV实现定位二维码

    Python+OpenCV实现定位二维码

    这篇文章主要为大家详细介绍了如何利用Python和OpenCV实现定位二维码功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12

最新评论