Вы можете использовать функцию minArearect . Эта функция dr aws устанавливает прямоугольники для каждого контура. Вы можете фильтровать, устанавливая эти длины прямоугольника.
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
int main()
{
Mat src; Mat src_gray;
int thresh = 100;
RNG rng(12345);
/// Load source image and convert it to gray
src = imread( "/ur/src/image_directory/image.png", 1 );
Mat original = src.clone();
/// Convert image to gray and blur it
cvtColor( src, src_gray, CV_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
/// Create Window
char* source_window = "Source";
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY );
/// Find contours
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Find the rotated rectangles for each contour
vector<RotatedRect> minRect( contours.size() );
for( int i = 0; i < contours.size(); i++ )
minRect[i] = minAreaRect( Mat(contours[i]) );
int x1,x2,y1,y2;
/// Draw contours + rotated rects
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
Mat result_zero = Mat::zeros( threshold_output.size(), CV_8UC3 );
for( int 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, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
// rotated rectangle
Point2f rect_points[4]; minRect[i].points( rect_points );
double length_1 = cv::norm(cv::Mat(rect_points[0]),cv::Mat(rect_points[1]));
double length_2 = cv::norm(cv::Mat(rect_points[1]),cv::Mat(rect_points[2]));
//This if scope for your desired rectangle size.You can set your size according to your rectangle(if it changes)
if(length_1>30 && length_1<100 && length_2>30 && length_2<100)
{
int min_x1 = INT_MAX, max_x2 = 0, min_y1 = INT_MAX, max_y2 = 0;
for( int j = 0; j < 4; j++ )
{
if(rect_points[j].x>max_x2 && rect_points[j].y>max_y2)
{
max_x2 = rect_points[j].x;
max_y2 = rect_points[j].y;
}
if(rect_points[j].x<min_x1 && rect_points[j].y<min_y1)
{
min_x1 = rect_points[j].x;
min_y1 = rect_points[j].y;
}
line( result_zero, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
}
x1 = min_x1;
x2 = max_x2;
y1 = min_y1;
y2 = max_y2;
}
}
circle(result_zero,Point(x1,y1),3,Scalar(0,255,255),2);
circle(result_zero,Point(x2,y2),3,Scalar(0,255,255),2);
// Here in source image we make the rectangle black according to found points
for(int i=y1-2;i<y2+2;i++)
{
for(int j=x1-2;j<x2+2;j++)
{
src.at<cv::Vec3b>(i,j)[0]=0;
src.at<cv::Vec3b>(i,j)[1]=0;
src.at<cv::Vec3b>(i,j)[2]=0;
}
}
/// Show in windows
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow("First",original);
imshow( source_window, result_zero );
imshow("Last",src);
imshow( "Contours", drawing );
waitKey(0);
return(0);
}
Исходное изображение:
Очки:
Результат: