我可以获得一个三角形的minRect,它是由opencv独立旋转角度的吗?

时间:2015-04-20 03:14:53

标签: opencv

我试图获得轮廓的minRect(实际上是一个三角形)。 但结果让我感到困惑。!

所有轮廓都是相同的三角形但旋转角度不同。 但他们的minRect与其他人不同。 但我认为结果应该与Angle无关。

棕色矩形是0°
粉红色& Green Rect是45°
其他Rect是随机的。
(我没有足够的声誉发布图片,抱歉。)

我的问题是我可以通过opencv得到一个独立于Angle的minRect吗?

3 个答案:

答案 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;
    }
}