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

作者:alex1801 时间:2023-09-08 06:38:47 

前言

网上很多例子都说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]。

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

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)

结果:

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

 角度说明:

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

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

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

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中cv2.minAreaRect函数输出角度问题详解

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

  • 此次试验的目的是计算目标图像偏转的角度,在不改变图像尺寸下纠正

  • 这里主要用到minAreaRect()函数和getRotationMatrix2D()函数

  • 先简单的介绍下minAreaRect()函数,本人在这里踩了一些坑,在这里说明一下,如有不妥的地方,大家尽管指正。

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

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

调用形式:RotatedRect minAreaRect(InputArray points)

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

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

顺时针为正,逆时针为负

  • 函数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函数输出角度问题详解

来源:https://blog.csdn.net/weixin_34910922/article/details/120239687

标签:cv2.minAreaRect,角度,opencv
0
投稿

猜你喜欢

  • 微信小程序实现留言板(Storage)

    2024-04-16 09:31:16
  • Python requests库用法实例详解

    2021-03-31 19:36:30
  • JSON.parse处理非标准Json数据出错的解决

    2024-04-18 09:49:12
  • Python 实现敏感目录扫描的示例代码

    2021-08-21 05:47:14
  • 详解python日期时间处理

    2021-08-20 17:07:53
  • python使用BeautifulSoup分析网页信息的方法

    2022-02-07 11:33:40
  • 带你了解python装饰器

    2023-08-26 23:10:57
  • 如何设置SQL Server数据库全文索引服务

    2009-01-13 13:46:00
  • python 2.6.6升级到python 2.7.x版本的方法

    2022-09-25 15:07:45
  • Vue表单之v-model绑定下拉列表功能

    2024-05-13 09:07:07
  • javascript封装的下拉导航菜单渐显效果

    2007-08-04 20:11:00
  • asp如何取回已忘记的密码?

    2010-05-13 16:33:00
  • Python 编码Basic Auth使用方法简单实例

    2023-06-13 22:29:50
  • Python实现导出数据生成excel报表的方法示例

    2021-05-17 16:43:57
  • 浅谈python3打包与拆包在函数的应用详解

    2022-03-05 00:33:15
  • 通过js获取上传的图片信息(临时保存路径,名称,大小)然后通过ajax传递给后端的方法

    2024-04-17 10:06:38
  • javascript中if和switch,==和===详解

    2024-04-22 13:23:28
  • Python json解析库jsonpath原理及使用示例

    2022-05-18 09:43:00
  • python条件变量之生产者与消费者操作实例分析

    2023-05-06 02:06:42
  • CSS nuggets CSS金矿

    2009-10-28 18:59:00
  • asp之家 网络编程 m.aspxhome.com