我试图获得轮廓的minRect(实际上是一个三角形)。 但结果让我感到困惑。!
所有轮廓都是相同的三角形但旋转角度不同。 但他们的minRect与其他人不同。 但我认为结果应该与Angle无关。
棕色矩形是0°
粉红色& Green Rect是45°
其他Rect是随机的。
(我没有足够的声誉发布图片,抱歉。)
我的问题是我可以通过opencv
得到一个独立于Angle的minRect吗?
答案 0 :(得分:0)
我认为你的意思是minAreaRect,根据定义,它找到一个旋转的矩形。从文档
该函数计算并返回指定点集的最小区域边界矩形(可能已旋转)。
您正在寻找适合未旋转的矩形的功能吗?
有boundingRect函数可以完成
该函数计算并返回指定点集的最小右上边界矩形。
在Python中,一个例子是加载图像,找到轮廓并将轮廓传递给函数。
img =cv2.imread(fileName,0)
#convert the image to B&W with the given threshold. 'thresh' is the
# the B&W image
ret, thresh = cv2.threshold(img,threshold,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh, cv2.cv.CV_RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[ID] #ID is the index of the contour you want
#find bounding rectangle of countour
x,y,w,h = cv2.boundingRect(cnt)
答案 1 :(得分:0)
实际上,我想获得countour的旋转角度(三角形)。 您可以使用Excel绘制三角形(两边相等),旋转它。复制该三角形并以另一个角度旋转它。 现在我们得到了2个相同但不同的旋转角度的三角形。 复制这2个三角形并复制到MSpaint,将其保存为图像。 使用opencv函数minAreaRect来查找countour(2个三角形)的旋转。你会发现:如果三角形旋转0deg或45deg你会得到一种类型的rect,但如果三角形旋转20deg或60度,你会得到另一种类型的矩形。 一种类型使用短边构造矩形,另一种类型使用长边构造矩形。
答案 2 :(得分:0)
#include "stdafx.h"
/**
* @function generalContours_demo2.cpp
* @brief Demo code to obtain ellipses and rotated rectangles that contain detected contours
* @author OpenCV team
*/
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void GetImPath();
void thresh_callback(int, void* );
void ReflashContours();
float trueAngle(Point2f centerP,Point2f midP,float a);
string mypath;
string impath;
/**
* @function main
*/
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
mypath=argv[0];
int pos0=mypath.rfind("\\");
mypath=mypath.substr(0,pos0+1);
if(1==argc)
{
char c='0';
impath=mypath+"t"+ c +".jpg";
}
else
{
impath=argv[1];
}
cout<<impath<<endl;
const char* source_window = "Source";
char k;
while(1){
src = imread (impath, 1 );
/// Convert image to gray and blur it
cvtColor( src, src_gray, COLOR_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
/// Create Window
namedWindow( source_window, WINDOW_AUTOSIZE );
imshow( source_window, src );
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
k=waitKey(0);
if (27==k) break;
GetImPath();
cout<<impath<<endl;
}
return(0);
}
void GetImPath()
{
static char c='0';
impath=mypath+"t"+ c +".jpg";
c++;
if( '3'<c) c='0';
return ;
}
void ReflashContours()
{
Mat proc_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
//threshold( src_gray, proc_output, thresh, 255, THRESH_BINARY );
// detect edges using canny
Canny(src_gray,proc_output,thresh,thresh*2,3);
//namedWindow( "Proc", WINDOW_AUTOSIZE );
//imshow( "Proc", proc_output );
/// Find contours
findContours( proc_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
cout<< contours.size() <<" Lens found."<<endl;
/// Find the rotated rectangles and ellipses for each contour
vector<RotatedRect> minRect( contours.size() );
vector<RotatedRect> minEllipse( contours.size() );
/// Get the moments
vector<Moments> mu(contours.size() );
for( size_t i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false ); }
/// Get the mass centers:
vector<Point2f> mc( contours.size() );
for( size_t i = 0; i < contours.size(); i++ )
{ mc[i] = Point2f( static_cast<float>(mu[i].m10/mu[i].m00) , static_cast<float>(mu[i].m01/mu[i].m00) ); }
for( size_t i = 0; i < contours.size(); i++ )
{
minRect[i] = minAreaRect( Mat(contours[i]) );
minEllipse[i] = fitEllipse( Mat(contours[i]) );
cout<<"Angle: " << trueAngle(mc[i],minRect[i].center, minRect[i].angle)<<"\t [X , Y] = " <<minRect[i].center <<endl;
//cout<<"Angle: " << trueAngle(mc[i],minEllipse[i].center, minEllipse[i].angle)<<"\t [X , Y] = " <<minEllipse[i].center <<endl;
cout<<endl;
}
cout<<endl;
cout<<endl;
/// Draw contours + rotated rects + ellipses
Mat drawing = Mat::zeros( proc_output.size(), CV_8UC3 );
//cout<< "drawing type :"<< drawing.type() <<endl;
drawing=src.clone();
for( size_t i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
// contour
drawContours( drawing, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );
//drawContours( src, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );
/**/
// rotated rectangle
Point2f rect_points[4]; minRect[i].points( rect_points );
for( int j = 0; j < 4; j++ )
{
line( drawing, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
//line( src, rect_points[j], rect_points[(j+1)%4], color,1 , 8 );
circle(drawing,rect_points[j],j*2,color,-1,8,0);
}
//center point
circle( drawing, mc[i], 1, color, -1, 8, 0 );
circle(drawing,minRect[i].center,1,color,-1,8,0);
//circle(drawing,minEllipse[i].center,1,color,-1,8,0);
//ellipse( drawing, minEllipse[i], color, 1, 8 );
}
/// Show in a window
namedWindow( "Contours", WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
}
/**
* @function thresh_callback
*/
void thresh_callback(int, void* )
{
ReflashContours();
}
float trueAngle(Point2f centerP,Point2f midP,float a)
{
cout<<"centerp: "<<centerP<<"\tmidp: "<<midP<<"\tangle: "<<a<<endl;
//1
if ((midP.x>centerP.x) && (midP.y<centerP.y ))
{
cout<<"1"<<endl;
return -a;
}
//2
else if((midP.x<centerP.x) && (midP.y<centerP.y ))
{
cout<<"2"<<endl;
return 90-a;
}
//3
else if((midP.x<centerP.x) && (midP.y>centerP.y ))
{
cout<<"3"<<endl;
return -180-a;
}
//4
else
{
cout<<"4"<<endl;
return -90-a;
}
}