opencv中cv2.minAreaRect函數(shù)輸出角度問題詳解
前言
網(wǎng)上很多例子都說cv2.minAreaRect函數(shù)的輸出的角度范圍在[-90,0],但是實測輸出范圍在[0,90]。再進行調(diào)研,確定為opencv4.5版本升級改動引起。
cv2.minAreaRect輸入:四邊形的四個點(不要求順序)。
輸出:最小外接矩形的中心點坐標x,y,寬高w,h,角度anlge,輸出形式為元組((x,y),(w,h),anlge),順序格式不變。
1、4.5版本
4.5版本定義為,x軸順時針旋轉(zhuǎn)最先重合的邊為w,angle為x軸順時針旋轉(zhuǎn)的角度,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)
輸出結(jié)果:((201.25, 92.10), (20.93, 101.94), 67.47)
中心點坐標:(201, 92),寬高: (20, 101),角度: 67。
配合旋轉(zhuǎn)函數(shù),可實現(xiàn)框的拉平。旋轉(zhuǎn)函數(shù)(逆時針旋轉(zhuǎn)):
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
執(zhí)行旋轉(zhuǎn):
rotate(img, -23, center=(201, 92), expand=False)
結(jié)果:
角度說明:
角度為x軸順時針旋轉(zhuǎn),第一次接觸到矩形邊界時的值,范圍:0~90°,第一次接觸的邊界為寬,區(qū)分方向可以使用寬、高的值來確定。
角度按逆時針旋轉(zhuǎn)方式調(diào)整為:
if rect[1][0] > rect[1][1]: # w > h angle = int(rect[2]) else: angle = -(90 - int(rect[2]))
2、4.5之前版本
有網(wǎng)友測試4.1.*,4.2.*,4.3.*,4.4.*下minAreaRect函數(shù)的都一樣,就是網(wǎng)上常見的角度輸出為[-90~0]情況。但是實測python版本4系列的都為上述4.5版情況,可能是c++版本的不同吧。這里補充[-90~0]情況。
rect = cv2.minAreaRect(cnts[0])
rect[0]返回最小外接矩形的中心點,rect[1]為最小外接矩形的寬、高。rect[2]為旋轉(zhuǎn)角度。
寬、高和角度定義如下:角度為x軸沿逆時針旋轉(zhuǎn)遇到的第一個邊時的旋轉(zhuǎn)角度,因為是逆時針旋轉(zhuǎn)所以角度為0~-90度。約定:遇到的第一個邊為寬、另一個邊為高。
補充:opencv ---minAreaRect()計算偏轉(zhuǎn)角度并糾正
- 此次試驗的目的是計算目標圖像偏轉(zhuǎn)的角度,在不改變圖像尺寸下糾正
- 這里主要用到minAreaRect()函數(shù)和getRotationMatrix2D()函數(shù)
- 先簡單的介紹下minAreaRect()函數(shù),本人在這里踩了一些坑,在這里說明一下,如有不妥的地方,大家盡管指正。
函數(shù)為minAreaRect(InputArray points) ,InputArray points是所要求最小外接矩形的點集,這個點集不定個數(shù)。
這個矩形是可以有偏轉(zhuǎn)角度的,可以與圖像的邊界不平行。
調(diào)用形式:RotatedRect minAreaRect(InputArray points)
- 角度計算規(guī)則:以左上角為原點,X軸逆時針旋轉(zhuǎn),所得到的第一個角度即為旋轉(zhuǎn)角度,第一條邊為最小外接矩形的寬。角度范圍[-90,0],當最小外接矩形平行(或垂直)X軸時角度為-90。(跟目標圖像的長寬沒關系)
順時針為正,逆時針為負
- 函數(shù)getRotationMatrix2D(Point2f center, double angle, double scale)
參數(shù)詳解:
Point2f center:表示旋轉(zhuǎn)的中心點
double angle:表示旋轉(zhuǎn)的角度 //這里的角度順時針為負,逆時針為正
double scale:圖像縮放因子
- 踩坑的地方主要在角度分不清,我總結(jié)了一下:
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; //---------------------旋轉(zhuǎn)----------------- //計算偏轉(zhuǎn)角度 GaussianBlur(image, gaussianimage, Size(5, 5), 3, 3);//盡可能多的去除雜質(zhì) 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; //此處目的是為了讓目標圖像旋轉(zhuǎn)到水平位置 if (degree > -90 && degree <= -45) { degree += 90; } else if (degree >-45 && degree < 0) { degree; } else { degree = 0; } cout <<"degree:" << degree << endl; } //旋轉(zhuǎn)糾正 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); }
效果圖:
總結(jié)
到此這篇關于opencv中cv2.minAreaRect函數(shù)輸出角度問題的文章就介紹到這了,更多相關opencv cv2.minAreaRect函數(shù)輸出角度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python實現(xiàn)一個Git日志統(tǒng)計分析的小工具
這篇文章主要給大家介紹了關于利用Python如何實現(xiàn)一個Git日志統(tǒng)計分析小工具的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2017-12-12matplotlib交互式數(shù)據(jù)光標實現(xiàn)(mplcursors)
這篇文章主要介紹了matplotlib交互式數(shù)據(jù)光標實現(xiàn)(mplcursors),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01python神經(jīng)網(wǎng)絡TensorFlow簡介常用基本操作教程
這篇文章主要介紹了python神經(jīng)網(wǎng)絡入門TensorFlow簡介常用基本操作教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-11-11Python實現(xiàn)讀取郵箱中的郵件功能示例【含文本及附件】
這篇文章主要介紹了Python實現(xiàn)讀取郵箱中的郵件功能,可讀取郵件文本及附件的功能,涉及Python針對郵件的獲取、分析、保存等相關操作技巧,需要的朋友可以參考下2017-08-08python輸出100以內(nèi)的質(zhì)數(shù)與合數(shù)實例代碼
本文通過實例代碼給大家介紹了python輸出100以內(nèi)的質(zhì)數(shù)與合數(shù)的方法,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧2018-07-07