Everyone, please help me. I have a problem.
I make a Convex Hull detection from image.
Then, i have a problem to fill a color on area within the boundary of ConvexHull.
Is there someone who can help me to fill a color on area within the boundary of ConvexHull?
Please help me with implementation on source code.
I use OpenCV 2.3.
This is a source code:
#include "stdafx.h"
#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 = 240;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void thresh_callback(int, void* );
/** #function main */
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( "kubis1.jpg", 1 );
/// 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 );
imshow( source_window, src );
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
waitKey(0);
return(0);
}
/** #function thresh_callback */
void thresh_callback(int, void* )
{
Mat src_copy = src.clone();
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 convex hull object for each contour
vector<vector<Point> >hull( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ convexHull( Mat(contours[i]), hull[i], false );
}
/// Draw contours + hull results
Mat drawing = 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) );
drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
}
/// Show in a window
namedWindow( "Hull demo", CV_WINDOW_AUTOSIZE );
imshow( "Hull demo", drawing );
}
You should use drawContours function with negative ’thickness’ parameter:
The function draws contour outlines in the image if thickness >= 0 or
fills the area bounded by the contours if thickness <= 0
Related
[original image][1]
[1]: https://i.stack.imgur.com/j7brr.jpg
I am trying to detect the clusters of connected boundaries in this image. I need to find the length of these edges and also the radius of gyration of the individual clusters.
I am using opencv 2.4.13.
I used the following code to detect the mass clusters using contours.
#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 thresh_callback(int, void* );
/** #function main */
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], 1 );
/// 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 );
imshow( source_window, src );
createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
waitKey(0);
return(0);
}
/** #function thresh_callback */
void thresh_callback(int, void* )
{
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using canny
Canny( src_gray, canny_output, thresh, thresh*2, 3 );
/// Find contours
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Get the moments
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false ); }
/// Get the mass centers:
vector<Point2f> mc( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
/// Draw contours
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
Mat drawing2 = Mat::zeros( canny_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{if(arcLength( contours[i], true )>900)
{Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
circle( drawing, mc[i], 4, color, -1, 8, 0 );}
}
int length=0;
int j=0;
for( int i = 0; i< contours.size(); i++ )
{
if(arcLength( contours[i], true )>length)
{
length=arcLength( contours[i], true );
j=i;
}
}
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing2, contours, j, color, 2, 8, hierarchy, 0, Point() );
circle( drawing2, mc[j], 4, color, -1, 8, 0 );
/// Show in a window
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
namedWindow( "Contours2", CV_WINDOW_AUTOSIZE );
imshow( "Contours_max", drawing2 );
/// Calculate the area with the moments 00 and compare with the result of the OpenCV function
printf("\t Info: Area and Contour Length \n");
for( int i = 0; i< contours.size(); i++ )
{
if(arcLength( contours[i], true )>900)
{printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
circle( drawing, mc[i], 4, color, -1, 8, 0 );}
}
}
The problem is the contours are getting different for common sharing edges and logically they should be of the same cluster. The following contour image I am giving.
We can see that many contours having same sharing edges are taken separately as different contours. I want them as a part of the same boundary clusters. Also suggest me how to detect the length of the boundaries and the radius of gyration.
Please help.
I am incredibly confused by your question (would ask for clarification in a comment, but I am too noob to comment)
My only advice based on what I see and understand is that you may not want to be using a canny filter. To be clear, your original image already has edges... running a canny filter on that gives you "double edges" which i do not think you want, but again, I am not even sure what you are trying to achieve.
I am using this link to get bound rectangle for contour
I want to know how can I get the same rectangle on source window, which is detected in the contour window.
Thank you very much in advance.
Create your polygons and circles in main( int argc, char** argv ) function.
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, drawing );
3.Comment
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
Answered here. Code by sturkmen:
/**
* #function generalContours_demo1.cpp
* #brief Demo code to find contours in an image
* #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 thresh_callback(int, void* );
/**
* #function main
*/
int main( int, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], 1 );
/// Convert image to gray and blur it
cvtColor( src, src_gray, COLOR_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
/// Create Window
const char* source_window = "Source";
namedWindow( source_window, WINDOW_AUTOSIZE );
imshow( source_window, src );
createTrackbar( " Threshold:", "Source", &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
waitKey(0);
return(0);
}
/**
* #function thresh_callback
*/
void thresh_callback(int, void* )
{
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) );
/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly( contours.size() );
vector<Rect> boundRect( contours.size() );
vector<Point2f>center( contours.size() );
vector<float>radius( contours.size() );
for( size_t i = 0; i < contours.size(); i++ )
{ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
minEnclosingCircle( contours_poly[i], center[i], radius[i] );
}
/// Draw polygonal contour + bonding rects + circles
Mat src2 = src.clone(); //add this line
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
for( size_t i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours_poly, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );
rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );
circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );
drawContours( src2, contours_poly, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point() );//add this line
rectangle( src2, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );//add this line
circle( src2, center[i], (int)radius[i], color, 2, 8, 0 );//add this line
}
/// Show in a window
namedWindow( "Contours", WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
imshow( "Source", src2 );//add this line
}
I have this image and my goal is to extract text from the image and save those texts as a string.My program has been able to detect text from the image but now i want to extract the characters and save it as a string. Is there a way to do it? Following is my code which i used to detect the texts in an image. I followed the tutorial as mentioned in this thread:- Extracting text OpenCV.
When i ran the program, i could see that the texts were bounded by rectangles but now how can i extract the characters from the rectangles and save it as a string? Is there a way to do it?
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
vector<cv::Rect> detectLetters(cv::Mat img)
{
std::vector<cv::Rect> boundRect;
cv::Mat img_gray, img_sobel, img_threshold, element;
cvtColor(img, img_gray, CV_BGR2GRAY);
cv::Sobel(img_gray, img_sobel, CV_8U, 1, 0, 3, 1, 0, cv::BORDER_DEFAULT);
cv::threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
element = getStructuringElement(cv::MORPH_RECT, cv::Size(17, 3) );
cv::morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element); //Does the trick
std::vector< std::vector< cv::Point> > contours;
cv::findContours(img_threshold, contours, 0, 1);
std::vector<std::vector<cv::Point> > contours_poly( contours.size() );
for( int i = 0; i < contours.size(); i++ )
if (contours[i].size()>100)
{
cv::approxPolyDP( cv::Mat(contours[i]), contours_poly[i], 3, true );
cv::Rect appRect( boundingRect( cv::Mat(contours_poly[i]) ));
if (appRect.width>appRect.height)
boundRect.push_back(appRect);
}
return boundRect;
}
int main()
{
Mat img;
img = imread("3d.JPG");
std::vector<cv::Rect> letterBBoxes1=detectLetters(img);
for(int i=0; i< letterBBoxes1.size(); i++)
cv::rectangle(img,letterBBoxes1[i],cv::Scalar(0,255,0),3,8,0);
imshow("image",img);
cvWaitKey(0);
}
Link of my output image is as follows:- http://s26.photobucket.com/user/rebecca1995/media/image_zps3f31a352.jpg.html.
Thanks.
I am using this code to *extract the finger*s when users show their hands to the camera.
The following error is being thrown after inserting these lines to find the convexity.
if (contours[i].size() >3 )
{
cout<<"inside"<<endl;
convexityDefects(contours[i], hull[i], defects[i]);
}
And the error is :
inside
OpenCV Error: Assertion failed (hull.checkVector(1, CV_32S) > 2) in convexityDefects, file C:/slave/builds/WinInstallerMegaPack/src/opencv/modules/imgproc/src/contours.cpp, line 1971
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
terminate called after throwing an instance of 'cv::Exception'
what(): C:/slave/builds/WinInstallerMegaPack/src/opencv/modules/imgproc/src/contours.cpp:1971: error: (-215) hull.checkVector(1, CV_32S) > 2 in function convexityDefects
Can anybody help me to resolve this issue?
Code:
#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 = 147;
int max_thresh = 255;
RNG rng(12345);
/// Function header
void thresh_callback(int, void* );
/** #function main */
int main( int argc, char** argv )
{
src = imread( "D:\\a.jpg", 1 );
/// Convert image to gray and blur it
resize(src,src,Size(640,480),0,0,INTER_LINEAR);
cvtColor( src, src_gray, CV_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
/// Create Window
char* source_window = "Knuckle Extractor";
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );
// createTrackbar( " Threshold:", source_window, &thresh, max_thresh, thresh_callback );
thresh_callback( 0, 0 );
waitKey(0);
return(0);
}
/** #function thresh_callback */
void thresh_callback(int, void* )
{
Mat src_copy = src.clone();
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold( src_gray, threshold_output, thresh, 255, THRESH_BINARY||CV_THRESH_OTSU );
// imshow("Grey",src_gray);
imshow("Threshold",threshold_output);
/// Find contours
// findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
//findContours( threshold_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0, 0) );
findContours( threshold_output, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Find the convex hull object for each contour
vector<vector<Point> >hull( contours.size() );
vector<vector<Vec4i> >defects( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{
convexHull( Mat(contours[i]), hull[i], false );
if (contours[i].size() >3 )
{
cout<<"inside"<<endl;
convexityDefects(contours[i], hull[i], defects[i]);
}
}
/// Draw contours + hull results
Mat drawing = 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) );
drawContours( drawing, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
}
/// Show in a window
namedWindow( "Result", CV_WINDOW_AUTOSIZE );
imshow( "Result", drawing );
}
The problem (or at least the main one I can see), is the way you construct your contours. You should use:
vector<vector<int> >hull( contours.size() );
Instead of:
vector<vector<Point> >hull( contours.size() );
This is because the convexityDefects function only works on convex hulls represented by a series of indices rather than a series of points.
Does anyone know how to use the cvFindDominantPoints API of openCV? I basically have a 1 channel, binary image from which I get a set of contours. Judging from the image, I seem to be getting the correct contours. Now, I am selecting one of these contours to get dominant points of. This contour has about 60 vertices. However, the API call to cvFindDominantPoints is giving me a sequence of points (about 15) that does not even lie on the contour. It is quite far from it. Any insight?
my usage:
CvSeq *dominantpoints = cvFindDominantPoints(targetSeq, tristorage, CV_DOMINANT_IPAN, 7, 9, 9, 150);
#include "cv.h"
#include "highgui.h"
CvSeq* contours = 0;
CvSeq* dps = 0;
int main( int argc, char** argv )
{
int i, idx;
CvPoint p;
CvMemStorage* storage_ct = cvCreateMemStorage(0);
CvMemStorage* storage_dp = cvCreateMemStorage(0);
IplImage* img = cvLoadImage("contour.bmp", CV_LOAD_IMAGE_GRAYSCALE);
cvNamedWindow( "image" );
cvShowImage( "image", img );
cvFindContours( img, storage_ct, &contours, sizeof(CvContour),
CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE );
dps = cvFindDominantPoints( contours, storage_dp, CV_DOMINANT_IPAN, 7, 20, 9, 150 );
contours = cvApproxPoly( contours, sizeof(CvContour), storage_ct, CV_POLY_APPROX_DP, 3, 1 );
printf("found %d DPs and %d Contours \n", dps->total, contours->total );
for ( i = 0; i < dps->total; i++)
{
idx = *(int *) cvGetSeqElem(dps, i);
p = *(CvPoint *) cvGetSeqElem(contours, idx);
cvDrawCircle( img, p , 1, cvScalarAll(255) );
printf("%d %d %d\n", idx, p.x, p.y);
}
cvDrawContours(img, contours, cvScalarAll(100), cvScalarAll(200), 100 );
cvNamedWindow( "contours" );
cvShowImage( "contours", img );
cvWaitKey(0);
cvReleaseMemStorage( &storage_ct );
cvReleaseMemStorage( &storage_dp );
cvReleaseImage( &img );
return 0;
}