I need to draw rectangle with 2 largest object from webcam. I already got to draw contours with 2 largest object from webcam but now i confuse in how to draw 2 largest Rectangle.
Someone can show me the code Please~
//find and draw contours
void showconvex(Mat &thresh,Mat &frame) {
int largestIndex = 0;
int largestContour = 0;
int secondLargestIndex = 0;
int secondLargestContour = 0;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
//find contours
findContours(thresh, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
/// Find the convex hull object for each contour
vector<vector<Point> >hull(contours.size());
vector<vector<int> >inthull(contours.size());
vector<vector<Vec4i> >defects(contours.size());
for (int i = 0; i < contours.size(); i++)
{
convexHull(Mat(contours[i]), hull[i], false);
convexHull(Mat(contours[i]),inthull[i], false);
if (inthull[i].size()>3)
convexityDefects(contours[i], inthull[i], defects[i]);
}
//find 2 largest contour
for( int i = 0; i< contours.size(); i++ )
{
if(contours[i].size() > largestContour)
{
secondLargestContour = largestContour;
secondLargestIndex = largestIndex;
largestContour = contours[i].size();
largestIndex = i;
}
else if(contours[i].size() > secondLargestContour)
{
secondLargestContour = contours[i].size();
secondLargestIndex = i;
}
}
//show contours of 2 biggest and hull as well
if(contours.size()>0)
{
//check for contouraea function if error occur
//draw the 2 largest contour using previously stored index.
drawContours(frame, contours, largestIndex, CV_RGB(0,255,0), 2, 8, hierarchy);
drawContours(frame, contours, secondLargestIndex, CV_RGB(0,255,0), 2, 8, hierarchy);
}
}
take a look at the code below
based on sorting contours by bounding boxes or by areas.
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
using namespace std;
struct contour_sorter_dsc // sorts contours by their bounding boxes descending
{
bool operator ()( const vector<Point>& a, const vector<Point> & b )
{
Rect ra( boundingRect(a) );
Rect rb( boundingRect(b) );
return ( ( rb.width * rb.height ) < ( ra.width * ra.height ) );
}
};
struct contour_sorter_dsc_area // sorts contours by their areas descending
{
bool operator ()( const vector<Point>& a, const vector<Point> & b )
{
double area_a = contourArea( a );
double area_b = contourArea( b );
return ( area_b < area_a );
}
};
int main( int argc, char** argv )
{
Mat src = imread( argv[1] );
if( src.empty() )
{
return -1;
}
Mat canvas1 = src.clone();
Mat canvas2 = src.clone();
Mat gray;
cvtColor( src, gray, COLOR_BGR2GRAY );
gray = gray > 127; // binarize image
vector<vector<Point> > contours;
findContours( gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE );
sort(contours.begin(), contours.end(), contour_sorter_dsc());
for( size_t i = 0; i< 2; i++ )
{ // checks if the first contour is image boundary
if( contours[0][0] == Point( 1, 1 ) & contours[0][1] == Point( 1, gray.rows -2 )
& contours[0][2] == Point( gray.cols - 2, gray.rows -2 ) & contours[0][3] == Point( gray.cols - 2, 1 ) )
{
contours[0] = contours[1];
contours[1] = contours[2];
}
if( i < contours.size())
{
drawContours( canvas1, contours, i, Scalar( 255,255,0 ) );
Rect minRect = boundingRect( Mat(contours[i]) );
rectangle( canvas1, minRect, Scalar( 0, 0, 255 ) );
}
}
imshow( "result of sorting contours by bounding boxes ", canvas1 );
sort(contours.begin(), contours.end(), contour_sorter_dsc_area());
for( size_t i = 0; i< 2; i++ )
{ // checks if the first contour is image boundary
if( contours[0][0] == Point( 1, 1 ) & contours[0][1] == Point( 1, gray.rows -2 )
& contours[0][2] == Point( gray.cols - 2, gray.rows -2 ) & contours[0][3] == Point( gray.cols - 2, 1 ) )
{
contours[0] = contours[1];
contours[1] = contours[2];
}
if( i < contours.size())
{
drawContours( canvas2, contours, i, Scalar( 255,255,0 ) );
Rect minRect = boundingRect( Mat(contours[i]) );
rectangle( canvas2, minRect, Scalar( 0, 0, 255 ) );
}
}
imshow( "result of sorting contours by areas ", canvas2 );
waitKey();
return 0;
}
Input image
Result Images according sort type
Related
I have a problem with the execution of my code.
I am trying to make this work:
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
using namespace cv;
using namespace std;
int main( )
{
Mat src1,src2;
namedWindow( "corner", CV_WINDOW_AUTOSIZE );
namedWindow( "result", CV_WINDOW_AUTOSIZE );
src1 = imread("RGB_32.png", CV_LOAD_IMAGE_COLOR);
src2 = imread("RGB_33.png", CV_LOAD_IMAGE_COLOR);
//*********************************************************************************
Mat im1,im2;
cvtColor(src1, im1, CV_RGB2GRAY);
cvtColor(src2, im2, CV_RGB2GRAY);
//******************ReduceImageSizeAndDetectCorner**********************************
Mat im2c,
tmp = im2;
pyrDown(tmp,im2c,Size( tmp.cols/2, tmp.rows/2));
Mat dst = Mat::zeros( im2c.size(), CV_32FC1 );
int blockSize = 3;
int apertureSize = 3;
double c = 0.09;
cornerHarris(im2c,dst,blockSize, apertureSize, c, BORDER_DEFAULT);
Mat dst_norm, dst_norm_scaled;
normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
convertScaleAbs( dst_norm, dst_norm_scaled );
int w=23,nb_pt=0,l=0, alpha=143;
/// Drawing a circle around corners
for( int j = 0+w; j < dst_norm.rows-w ; j++ ){
for( int i = 0+w; i < dst_norm.cols-w; i++ ){
if( (int) dst_norm.at<float>(j,i) > alpha )
{
circle( im2c, Point( i, j ), 0.5, Scalar(0,0,255), 4, 8, 0 );
nb_pt ++ ;
}
}
}
Mat C= Mat:: zeros(nb_pt,2,CV_32FC1) ;
for( int j = 0+w; j < dst_norm.rows-w ; j++ ){
for( int i = 0+w; i < dst_norm.cols-w; i++ ){
if( (int) dst_norm.at<float>(j,i) > alpha ){
C.at <float> (l,0)=j;
C.at <float> (l,1)=i;
l++;
}
}
}
C=2*C;
//******************ImplementLucas&KanadeMethod**************************************
Mat1f Cx,Cy;
Mat Ix_m,Iy_m,It_m,It1,It2;
Cx = (Mat_<float>(2,2) << -1,1,-1,1);
Cy= (Mat_<float>(2,2) << -1,-1,1,1);
Mat Ct1 = (Mat_<float>(2,2) << -1,-1,-1,-1);
Mat Ct2 = Mat::ones( 2, 2, CV_8U );
filter2D(im1,Ix_m,-1,Cx,Point(-1,-1),0,BORDER_DEFAULT);
filter2D(im1,Iy_m,-1,Cy,Point(-1,-1),0,BORDER_DEFAULT);
filter2D(im1,It1,-1,Ct1,Point(-1,-1),0,BORDER_DEFAULT);
filter2D(im1,It2,-1,Ct2,Point(-1,-1),0,BORDER_DEFAULT);
add(It1,It2,It_m);
//initialiser le flot
//Mat u = Mat::zeros( 1, nb_pt, CV_32FC1 );
//Mat v = Mat::zeros( 1, nb_pt, CV_32FC1 );
Mat Ix,Ixd,Iy,Iyd,It,Itd,b,nu,A;
int u,v ;
cv::Scalar color(0,0,255);
int size = 10 ;
int thickness = 10 ;
for (int k=0 ; k < nb_pt ; ++k) {
int j= C.at <float> (k,0);
int i= C.at <float> (k,1);
Ix= Ix_m(Range(j-w,j+w),Range(i-w,i+w));
Iy= Iy_m(Range(j-w,j+w),Range(i-w,i+w));
It= It_m(Range(j-w,j+w),Range(i-w,i+w));
redim(Ix,Ixd);
redim(Iy,Iyd);
redim(It,Itd);
multi(Itd,b);
funct(Ixd,Iyd,A);
Mat inv = A.inv(DECOMP_SVD);
nu = inv * b ;
u= nu.at<float> (0,0);
v= nu.at<float> (0,1);
//cout << "u = "<< u << endl ;
//cout << "v = "<< v << endl ;
cvQuiver(src2,i,j,u,v,color, size, thickness);
}
imshow( "result", src2 );*/
waitKey();
}
I have a problem with the for loop. When k = 2, I get the error "core dumped". But, when I run the code case by case, that is to say I take the case k=0 then k=1,2,..., it works.
Any help please? when k=2
I am currently working on extracting Contours path attributes from a particular image file. I am able to extract Contours using Open CV function findContours() the output look like this
[98, 81][97, 80][95, 80][94, 79][93, 79][92, 78][91, 78][88, 75][87, 75][85, 73][84, 73][83, 72][82, 72]
But my desired output is look like this
M 398.7,106.8 c -5.5,-2.7 -20.7,-4.7 -36.1,-4.6 -15.4,0.1
How can I get it
This is my code:
using namespace cv;
using namespace std;
Mat src_grays;
int threshs = 100;
int max_threshs = 255;
RNG rng(12345);
void thresh_callbacks(int, void* );
void main( )
{
Mat src = imread( "F:/academic/pro4/t/download.jpg" );
imshow("real Image", src);
Mat gray,edge,edges, draw,draws;
Mat samples(src.rows * src.cols, 3, CV_32F);
for( int y = 0; y < src.rows; y++ )
for( int x = 0; x < src.cols; x++ )
for( int z = 0; z < 3; z++)
samples.at<float>(y + x*src.rows, z) = src.at<Vec3b>(y,x)[z];
int clusterCount = 5;
Mat labels;
int attempts = 10;
Mat centers;
kmeans(samples, clusterCount, labels, TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10000, 0.0001), attempts, KMEANS_PP_CENTERS, centers );
Mat new_image( src.size(), src.type() );
for( int y = 0; y < src.rows; y++ )
for( int x = 0; x < src.cols; x++ )
{
int cluster_idx = labels.at<int>(y + x*src.rows,0);
new_image.at<Vec3b>(y,x)[0] = centers.at<float>(cluster_idx, 0);
new_image.at<Vec3b>(y,x)[1] = centers.at<float>(cluster_idx, 1);
new_image.at<Vec3b>(y,x)[2] = centers.at<float>(cluster_idx, 2);
}
imshow( "clustered image", new_image );
char filename[80];
sprintf(filename,"F:/academic/pro4/t/seg.png");
imwrite(filename, new_image);
cvtColor(src, gray, CV_BGR2GRAY);
Canny( new_image, edges, 50, 150, 3);
edges.convertTo(draws, CV_8U);
namedWindow("imageAfterSegmnetation", CV_WINDOW_AUTOSIZE);
imshow("imagesAfterCluster", draws);
cvtColor( new_image, src_grays, CV_BGR2GRAY );
blur( src_grays, src_grays, Size(3,3) );
char* source_window = "Source";
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
createTrackbar( " Canny thresh:", "Source", &threshs, max_threshs, thresh_callbacks );
thresh_callbacks( 0, 0 );
waitKey( 0 );
}
void thresh_callbacks(int, void* )
{
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using canny
Canny( src_grays, canny_output, threshs, threshs*2, 3 );
/// Find contours
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
for(int i= 0; i < contours.size(); i++)
{
for(int j= 0; j < contours[i].size();j++) // run until j < contours[i].size();
{
int a= contours[i][j].x ;
int b =contours[i][j].y ;
// printf("Point(x,y)=" + a, b);
std::cout << contours[i][j] << std::endl;
}
printf ("%i", i + "\n");
}
/// Draw contours
int a=contours.size();
for( int i = 0; i<contours.size(); i++ )
{
Mat drawing_i = Mat::zeros( canny_output.size(), CV_8UC3 );
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing_i, contours, i, color, 2, 8, hierarchy, 0, Point() );
namedWindow( "Contours_i", CV_WINDOW_AUTOSIZE );
imshow( "Contours_i", drawing_i );
}
}
Note:
I need Contours path, that mean how to contours connected for example it can be M = moveto L = lineto H = horizontal lineto V = vertical lineto C = curveto S = smooth curveto Q = quadratic Bézier curve T = smooth quadratic Bézier curveto A = elliptical Arc Z = closepath just like SVG path
How can i convert cvSeq* to vector< vector< Point > > ?
this is my code:
first_contour = NULL;
cvFindContours(
src_copy_gray,
storage,
&first_contour,
sizeof(CvContour),
CV_RETR_TREE );
// Finding convex Hull
CvMemStorage* hull_storage = cvCreateMemStorage();
CvSeq* retHulls = NULL;
CvMat* tmp;
cv::Mat tmp22;
// drawing contours
ff = cv::Mat::zeros( tmp4.size(), CV_8UC3 );
draw = new IplImage(ff);
for(CvSeq* i = first_contour; i != 0; i = i->h_next){
cvDrawContours(draw,i,cv::Scalar(255,255,0,0),cv::Scalar(255,0,0,0),0,1,8);
retHulls = cvConvexHull2(i,hull_storage,CV_CLOCKWISE,1);
cvDrawContours(draw,retHulls,cv::Scalar(255,0,0,0),cv::Scalar(255,0,0,0),0,1,8);
for (int k = 0; k < vertices_number; k++)
{
if(pointPolygonTest( ??????, cv::Point2f(verticesB[k].x,verticesB[k].y), false )>0){
cv::line( ff,cv::Point2f(verticesB[k].x,verticesB[k].y), cv::Point2f(verticesB[k].x,verticesB[k].y), cv::Scalar(255,0,255 ), 2, 8 );
}
}
}
what should i put instead of ?????
I neea a cv::_InputArray, but I don't know how to convert the cvseq* retHulls to a cv::_InputArray like vector of vectors.
I have tried to port Square detection with OpenCV 2.4.1-2.4.4 but results seem very slow. I was keen to move to newer versions of OpenCV because of new functionality given, but am having very slow results.
My OpenCV code for versions 2.4.X is:
// The "Square Detector" program.
// It loads several images sequentially and tries to find squares in
// each image
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <math.h>
#include <string.h>
using namespace cv;
using namespace std;
int thresh = 50, N = 11;
const char* wndname = "Square Detection Demo";
// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle( Point pt1, Point pt2, Point pt0 )
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
static void findSquares( const Mat& image, vector<vector<Point> >& squares )
{
squares.clear();
Mat pyr, timg, gray0(image.size(), CV_8U), gray;
// down-scale and upscale the image to filter out the noise
pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
pyrUp(pyr, timg, image.size());
vector<vector<Point> > contours;
// find squares in every color plane of the image
for( int c = 0; c < 3; c++ )
{
int ch[] = {c, 0};
mixChannels(&timg, 1, &gray0, 1, ch, 1);
// try several threshold levels
for( int l = 0; l < N; l++ )
{
// hack: use Canny instead of zero threshold level.
// Canny helps to catch squares with gradient shading
if( l == 0 )
{
// apply Canny. Take the upper threshold from slider
// and set the lower to 0 (which forces edges merging)
Canny(gray0, gray, 0, thresh, 5);
// dilate canny output to remove potential
// holes between edge segments
dilate(gray, gray, Mat(), Point(-1,-1));
}
else
{
// apply threshold if l!=0:
// tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
gray = gray0 >= (l+1)*255/N;
}
// find contours and store them all as a list
findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
vector<Point> approx;
// test each contour
for( size_t i = 0; i < contours.size(); i++ )
{
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
// square contours should have 4 vertices after approximation
// relatively large area (to filter out noisy contours)
// and be convex.
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if( approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx)) )
{
double maxCosine = 0;
for( int j = 2; j < 5; j++ )
{
// find the maximum cosine of the angle between joint edges
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange
// vertices to resultant sequence
if( maxCosine < 0.3 )
squares.push_back(approx);
}
}
}
}
}
// the function draws all the squares in the image
static void drawSquares( Mat& image, const vector<vector<Point> >& squares )
{
for( size_t i = 0; i < squares.size(); i++ )
{
const Point* p = &squares[i][0];
int n = (int)squares[i].size();
polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);
}
imshow(wndname, image);
}
int main()
{
VideoCapture cap;
cap.open(0);
Mat frame,image;
namedWindow( "Square Detection Demo", 1 );
vector<vector<Point> > squares;
for(;;)
{
cap >> frame;
if( frame.empty() ){
break;
}
frame.copyTo(image);
if( image.empty() )
{
cout << "Couldn't load image" << endl;
continue;
}
findSquares(image, squares);
drawSquares(image, squares);
//imshow("Window", image);
int c = waitKey(1);
if( (char)c == 27 )
break;
}
return 0;
}
You can notice that the code is a simple mix of Webcam visualization and the squares code provided both by OpenCV 2.4.X.
However, the equivalent code for version 2.1 of OpenCV which i will put now is a lot faster:
#include <cv.h>
#include <highgui.h>
int thresh = 50;
IplImage* img = 0;
IplImage* img0 = 0;
CvMemStorage* storage = 0;
// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
{
double dx1 = pt1->x - pt0->x;
double dy1 = pt1->y - pt0->y;
double dx2 = pt2->x - pt0->x;
double dy2 = pt2->y - pt0->y;
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )
{
CvSeq* contours;
int i, c, l, N = 11;
CvSize sz = cvSize( img->width & -2, img->height & -2 );
IplImage* timg = cvCloneImage( img ); // make a copy of input image
IplImage* gray = cvCreateImage( sz, 8, 1 );
IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
IplImage* tgray;
CvSeq* result;
double s, t;
// create empty sequence that will contain points -
// 4 points per square (the square's vertices)
CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
// select the maximum ROI in the image
// with the width and height divisible by 2
cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));
//cvSetImageROI( timg, cvRect( 0,0,50, 50 ));
// down-scale and upscale the image to filter out the noise
cvPyrDown( timg, pyr, 7 );
cvPyrUp( pyr, timg, 7 );
tgray = cvCreateImage( sz, 8, 1 );
// find squares in every color plane of the image
for( c = 0; c < 3; c++ )
{
// extract the c-th color plane
cvSetImageCOI( timg, c+1 );
cvCopy( timg, tgray, 0 );
// try several threshold levels
for( l = 0; l < N; l++ )
{
// hack: use Canny instead of zero threshold level.
// Canny helps to catch squares with gradient shading
if( l == 0 )
{
// apply Canny. Take the upper threshold from slider
// and set the lower to 0 (which forces edges merging)
cvCanny( tgray, gray, 0, thresh, 5 );
// dilate canny output to remove potential
// holes between edge segments
cvDilate( gray, gray, 0, 1 );
}
else
{
// apply threshold if l!=0:
// tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
}
// find contours and store them all as a list
cvFindContours( gray, storage, &contours, sizeof(CvContour),
CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
// test each contour
while( contours )
{
// approximate contour with accuracy proportional
// to the contour perimeter
result = cvApproxPoly( contours, sizeof(CvContour), storage,
CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
// square contours should have 4 vertices after approximation
// relatively large area (to filter out noisy contours)
// and be convex.
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if( result->total == 4 &&
cvContourArea(result,CV_WHOLE_SEQ,0) > 1000 &&
cvCheckContourConvexity(result) )
{
s = 0;
for( i = 0; i < 5; i++ )
{
// find minimum angle between joint
// edges (maximum of cosine)
if( i >= 2 )
{
t = fabs(angle(
(CvPoint*)cvGetSeqElem( result, i ),
(CvPoint*)cvGetSeqElem( result, i-2 ),
(CvPoint*)cvGetSeqElem( result, i-1 )));
s = s > t ? s : t;
}
}
// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange
// vertices to resultant sequence
if( s < 0.3 )
for( i = 0; i < 4; i++ )
cvSeqPush( squares,
(CvPoint*)cvGetSeqElem( result, i ));
}
// take the next contour
contours = contours->h_next;
}
}
}
// release all the temporary images
cvReleaseImage( &gray );
cvReleaseImage( &pyr );
cvReleaseImage( &tgray );
cvReleaseImage( &timg );
return squares;
}
// the function draws all the squares in the image
void drawSquares( IplImage* img, CvSeq* squares )
{
CvSeqReader reader;
IplImage* cpy = cvCloneImage( img );
int i;
// initialize reader of the sequence
cvStartReadSeq( squares, &reader, 0 );
// read 4 sequence elements at a time (all vertices of a square)
for( i = 0; i < squares->total; i += 4 )
{
CvPoint pt[4], *rect = pt;
int count = 4;
// read 4 vertices
CV_READ_SEQ_ELEM( pt[0], reader );
CV_READ_SEQ_ELEM( pt[1], reader );
CV_READ_SEQ_ELEM( pt[2], reader );
CV_READ_SEQ_ELEM( pt[3], reader );
// draw the square as a closed polyline
cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
}
// show the resultant image
cvShowImage( "Squares", cpy );
cvReleaseImage( &cpy );
}
int main(int argc, char** argv){
// Crea una ventana llamada Original Image con un tamaño predeterminado.
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Squares", CV_WINDOW_AUTOSIZE);
// Crea la conexion con la Webcam.
CvCapture* capture = cvCreateCameraCapture(0);
if( !capture ){
throw "Error when reading steam_avi";
}
storage = cvCreateMemStorage(0);
while(true)
{
// Pongo el frame capturado dentro de la imagen originalImg.
img0 = cvQueryFrame(capture);
if(!img0){
break;
}
img = cvCloneImage( img0 );
// find and draw the squares
drawSquares( img, findSquares4( img, storage ) );
cvShowImage("Original Image", img0);
cvReleaseImage(&img);
// clear memory storage - reset free space position
cvClearMemStorage( storage );
// Espero a que me pulsen el ESC para salir del bucle infinito.
char c = cvWaitKey(10);
if( c == 27 ) break;
}
//cvReleaseImage(&img);
cvReleaseImage(&img0);
// clear memory storage - reset free space position
cvClearMemStorage( storage );
// Destruye la ventana “Original Image”.
cvDestroyWindow("Original Image");
cvDestroyWindow("Squares");
// Libera la memoria utilizada por la variable capture.
cvReleaseCapture(&capture);
}
I am aware that I can use one colour channel to speed up x3, and change other params to speed up, but wonder why equivalent codes give such different execution times.
Is there anything basic which I am missing out on?
I have tried to put working code up for everyone to try, so as to not waste anybody's time with vague questions such as: Opencv 2.4.X is slow.
Finaly left out Canny and checked for Area of square being below certain values (less 20% of image area) so that unwanted squares were not detected. As for getting multiple results for same square, am not too bothered with it at the moment, as i can input given squares as possible template images for comparisson. Now off to recognition of image in square. Thanks Chris for at least reading this comment (I cant give you points as answer as it was only a comment, but either way, thank you).
I have the following code to draw the largest contour. But It seems there is something that I am doing wrong. Please advice
if(inputImage.data == NULL)
return HandInfo2();
Mat outputImage = Mat::zeros( inputImage.size(), CV_8UC1);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
vector<Point> largestContour;
int largestArea = -1;
findContours( inputImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Approximate contours to polygons
vector<vector<Point> > polyContours( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{
approxPolyDP( Mat(contours[i]), polyContours[i], 3, true );
}
for( int i = 0; i < contours.size(); i++ )
{
int area = fabs(contourArea(polyContours[i],false));
if(area > largestArea && area > size)
{
largestArea = area;
largestContour = polyContours[i];
}
}
Scalar color = Scalar( 255 );
if(largestContour.size()>0)
drawContours( outputImage, largestContour, 0, color, 1, 8, vector<Vec4i>(), 0, Point() );
When drawContours() is being called, I get the following error
OpenCV Error: Assertion failed (i < 0) in unknown function, file ..\..\..\src\opencv\modules\core\src\matrix.cpp, line 957
What am I doing wrong here?
Ok, just for someone who makes the same mistake.
I needed the a vector<vector<Point>> largestContour; instead of vector largestContour;
And changed the code from largestContour = polyContours[i]; to largestContour.push_back(polyContours[i]);
That was it. Now I can extract the largest contour.