Program crashes when using cv::findContours with Qt Gui - c++

I have been stuck with this issue for days;
I created a Qt console project, connected it with OpenCV and everything was working just fine;
I created a Qt Gui project, added a button and copied the same code from the previous project in the button's slot, I got a windows segFault and program exited with code -1073741819.
So I used the debugger to detect the problem and it turned out to be at the use of function cv::threshold.
I changed it and instead used cv::Canny but then I got the same problem with cv::findContours !
The strange thing is that when I called the button's 'MainWindow::on_pushButton_clicked()'
in the windows' constructor it worked!!!
here's debugger output:
0 cv::thresh_8u(cv::Mat const&, cv::Mat&, unsigned char, unsigned char, int) C:\OpenCV2.4\OpenMinGw\install\bin\libopencv_imgproc240.dll 0 0x62b2c624
1 cv::_InputArray::getMat(int) const C:\OpenCV2.4\OpenMinGw\install\bin\libopencv_core240.dll 0 0x65c1a838
2 ?? 0 0x00000000
and here's the function where I get the error (which I got from OpenCV tutorials):
void MainWindow::on_pushButton_clicked(){
Mat src; Mat src_gray;
int thresh = 100;
RNG rng(12345);
Mat canny_output;
vector<vector<Point> > contours;
/// Load source image and convert it to gray
src = imread( "hat-10.bmp", 1 );
cvtColor( src, src_gray, CV_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
/// Detect edges using canny
Canny( src_gray, canny_output, thresh, thresh*2, 3 );
qDebug("Ok 1");
/// Find contours
if(cv::sum(src_gray).val[0] > 0.0){
qDebug("Ok 2");
cv::findContours( src_gray, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );
/// Draw contours
Mat drawing = Mat::zeros( src_gray.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, 2);//, 8, hierarchy, 0, Point() );
}
/// Show in a window
imshow( "Contours", drawing);
}
Using:
Windows 7 x64
OpenCV 2.4.0 compiled using mingw 4.1.0
Qt Creator 2.0.0 Based on Qt 4.7.0 (32 bit)
Edit:
here's a shorter version of my code :
void MainWindow::on_toolButton_clicked(){
std::vector<std::vector<cv::Point> > contours;
/// Load source image and convert it to gray
Mat src = imread( "C:/Users/poste/L3 ISIL/PFE Licence/new bmp/hat-10.bmp", 1);
// my image is already a binary one
Mat canny_output(src.size(), src.type());
Canny(src,canny_output,100,200,3);
imshow("Source", canny_output); // here image is displayed before crash
waitKey(500);
/// Find contours
findContours(canny_output, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );
}
in console mode, there's no problem. when called from GUI app constructor there's also no problem.
It only crashes when actually clicking on the button.
edit:
I took a screenshot ![here]http://i.stack.imgur.com/1LyeF.png
canny_output was displayed which means image was loaded.
Uploaded project here

First make sure that the image that you want to threshold is really a gray scaled image. Show it in another window after Thresholding.
Do that before cv::FindContours:
cvThreshold(originalImage,resultingImage,100,100,CV_THRESH_BINARY)
also change that:
vector<vector<Point> > contours;
to:
vector<vector<cv::Point2f> > contours;

Try this:
/// Load source image and convert it to gray
Mat src = imread( "hat-10.bmp", 1 );
Mat src_gray(src.size(), CV_8U);
cvtColor( src, src_gray, CV_BGR2GRAY );
blur( src_gray, src_gray, Size(3,3) );
//Apply threshold
cv::Mat thres_output(src_gray.size(), src_gray.type());
cv::threshold(src_gray, thres_output, 100, 255, cv::THRESH_BINARY);
qDebug("Ok 1");
OpenCV docs have a full demo on Basic Thresholding Operations.
EDIT:
After carefully reviewing your code and comments, I think I know what's going on: these problems might be happening because imread() can't access the specified file. This makes the function return an empty Mat. To check if this is the case, simply do:
Mat src = imread( "hat-10.bmp", 1 );
if (src.empty())
{
std::cout << "!!! imread failed to open image\n";
return;
}
The reason why it happens is because Qt Creator builds the .exe of the project in a separate folder, so when the application runs, it tries to load the image from the directory where the .exe was launched, and it fails because the image isn't there.
When calling imread() remember to pass the FULL PATH to the file. See if that fixes the issue.
EDIT:
Remember to convert the image to binary before feeding it to findContours():
// Convert from 32F to 8U
cv::Mat binary_img;
canny_output.convertTo(binary_img, CV_8U);
std::vector<std::vector<cv::Point> > contours;
cv::findContours(binary_img, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

I used function Qtconcurrent::run() and everything started working.
Even though this isn't a permanent (nor a good) solution; this is all I could come up with.
I'm still open to other answers though.

Related

Opencv Findcontours cause heap error

I am using opencv 2.49.
But I am stuck by find contours function for hours.
When I run the program in debug mode and the error box returns
Debug assertion failed
Program: ...
File f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line: 1322
Exception:_ CrtIsValidHeapPoionter(pUserData)
And here is my function
HRESULT OpenCVHelper::DrawHand(Mat* pImg)
{
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
cvtColor(*pImg, *pImg, CV_RGBA2GRAY);
//Canny(*pImg, *pImg, 30,50);
threshold( *pImg, *pImg, 50, 255,THRESH_BINARY);
if(pImg->type() == CV_8UC1)
{
findContours( *pImg, contours, hierarchy, CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
}
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
Scalar color( rand()&255, rand()&255, rand()&255 );
drawContours( *pImg, contours, i, color, 2, 8, hierarchy, 0, Point() );
}
//contours.clear();
//hierarchy.clear();
cvtColor(*pImg, *pImg, CV_GRAY2RGBA);
return S_OK;
}
When I remove findcontour function there is no error.
When I use findcontour it pops the error box showed above.
When I add "contours.clear(); hierarchy.clear();" these two lines, there is no error message but the program still crashes.
Anyone can help?
EDIT 1. I find out the allocator for causing heap corruption, which is vector > contours; but I still don't know how to fix it.
Finally I found problem...
My Dev Environment
window10 x64, Intel i5 ( X64 ),
MS Visual Studio 2010 SP1
OpenCV 2.4.9 ( Test 2.4.13 get the same error)
Some people solve this problem : up to opencv version. 2.4.9.
, Hear is my code.
Mat Img = imread( src_image );
if (Img.rows == 0 || Img.cols == 0)
return -1;
Mat ImgGray;
cvtColor( Img, ImgGray, CV_BGR2GRAY );
Mat threshold_output;
vector<vector<Point>> contours; // <<
vector<Vec4i> hierarchy;
int blkSize = 5;
int nKernelSz = 3;
double dFactor = 2.0f;
adaptiveThreshold(ImgGray,threshold_output,
100,CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY_INV,blkSize, 5);
findContours(threshold_output, contours, hierarchy, CV_RETR_TREE,
CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
"vector < vector < Point > > "
Causes an error on runtime library /MTd
Solve : runtime library change to /MD
This is the site referenced below.
http://opencv-users.1802565.n2.nabble.com/c-interface-heap-mem-problem-findcontours-td7020857.html
The code you have should work. Most likely point of failure is having an empty image when you get to findContours. I am not talking about uninitialized image but the one that was initialized with Size(0,0). Change your 'if-statement' to be:
if ((pImg->type() == CV_8UC1) && (pImg->rows>0))
If this won't help, than next step is to verify that the function that crushes is indeed findContours and not drawContours. The crash may be in drawContours because it is not used when you remove findContours.
Also it is VERY not recommended to use pointer to Mat. Mat is a smart pointer by itself, and it has reference counter. This will create all kinds of nasty bugs.

opencv findContours() crashes the program

I am new to image processing, and I'm working on a real time tracking
But I am stuck with the findCountours function.
cvtColor(*pImg, *pImg, CV_RGBA2GRAY); //convert to gray image
Mask = pImg->clone(); //clone the source
Mask.convertTo(Mask,CV_8UC1); //convert to 8UC1
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( Mask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
contours.clear();
hierarchy.clear();
and when I run the program it crashes, If I comment the findCountours function it will be fine.
I have checked some documents but there is no clue what happened.
Mask = pImg->clone(); //clone the source
Mask.convertTo(Mask,CV_8UC1); //convert to 8UC1
replace
pImg.convertTo(Mask, CV_8U, arg);
arg may be different for different types of the input image. 255 for float/double.
Try using "Canny edge detector or Threshold operator" before finding contours.
Choose your operator based on the task you need to perform.
`cvtColor(*pImg, *pImg, CV_RGBA2GRAY); //convert to gray image
Mask = pImg->clone(); //clone the source
Mask.convertTo(Mask,CV_8UC1); //convert to 8UC1
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/*based on your need use any of these operator */
threshold( input, output, threshold_value, max_BINARY_value,threshold_type );
Canny( input, canny_output, thresh, thresh*2, 3 );
findContours( output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
contours.clear();
hierarchy.clear();`

ASL hand sign detection opencv

I am a bit new to opencv and could use some help. I want to detect ASL hand signs.
For detecting hands, I can use either detection by skin color or a haar classifier. I already detect hands, but the problem is detecting the hand shape.
I can get the curent hand shape using the algorithm described here, so the problem is how do I compare this shape to my database of shapes?
I tried comparing them using the algorithm described here, which detects similar features images have. The problem is that this will match it with all the hands, since...well it detects them as hands. For instance, check this image, it should point only to V, but it detects features in W and R, too.
I want my final result to be like here, so how can I compare image shapes? Is my approach wrong?
I was thinking that detecting by convexity hull won't work, because most of the signs are closed fists. Check O, for instance, it has no open fingers, so I thought that trying to compare contours would be the best. How to compare them, though? FLANN doesn't seem to work. Or I'm doing it wrong.
Would a Haar cascade classifier work? Or would it detect two hands in different positions as hands as well?
Or is there another way to match shapes? That could solve my problem, but I couldn't find any example that does for custom shapes, only for ones like rectangles, circles and triangles.
Update
Ok, I've been playing a bit with matchShapes as berak told me. Here's my code below(it's a bit messy as I'm testing currently).
#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 = 10;
int max_thresh = 300;
/// 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;
double largest_area=0;
int largest_contour_index=0;
Rect bounding_rect;
/// 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) );
cout<<contours.size()<<endl;
/// Draw contours
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
vector<vector<Point> >hull( contours.size() );
for( int i = 0; i< contours.size(); i++ )
{ Scalar color = Scalar( 255,255,255 );
convexHull( Mat(contours[i]), hull[i], false );
// imshow("conturul"+to_string(i), drawing );
double a=contourArea( hull[i],false); // Find the area of contour
if(a>largest_area){
largest_area=a;
largest_contour_index=i; //Store the index of largest contour
bounding_rect=boundingRect(hull[i]);}
}
cout<<"zaindex "<<largest_contour_index<<endl;
Scalar color = Scalar( 255,255,255 );
drawContours( drawing, hull, largest_contour_index, color, 2, 8, hierarchy, 0, Point() );
namedWindow( "maxim", CV_WINDOW_AUTOSIZE );
imshow( "maxim", drawing );
Mat rects=imread( "scene.png", 1 );
rectangle(rects, bounding_rect, Scalar(0,255,0),1, 8,0);
imshow( "maxim2", rects );
/// Show in a window
}
The problem with it is the definition of a contour. These hand 'contours' are actually made of multiple contours themselves and that image that I showed earlier is actually made of these multiple contours but overlapped with eachother. matchShapes accepts arrays of Points as parameters, but the contours are arrays of arrays of Points.
So my question is, how can I add my contours vector with itself so I can pass it to matchShapes? In other words, how can I make a single contour from multiple overlapped contours?

How to find contours from a webcam frame using opencv and c++?

My goal is to find contours by capturing frame from a webcam. I was able to do it with static images but then I tried to use the same concept in a webcam frame and its giving me this error:
"OpenCV Error: Assertion failed (mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN
(type0) && ((1 << type0) & fixedDepthMask) != 0)) in cv::_OutputArray::create, f
ile C:\builds\2_4_PackSlave-win64-vc11-shared\opencv\modules\core\src\matrix.cpp
, line 1486"
This is the code that I used to find the contours in my program;
Rng rng(12345);
Mat captureframe,con,threshold_output;
vector<vector<Point> > contours; //
vector<Vec4i> hierarchy;
while(true)
{
capturedevice>>captureframe;
con = captureframe.clone();
cvtColor(captureframe,con,CV_BGR2GRAY);
threshold( con, threshold_output, thresh, 255, THRESH_BINARY );
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
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() );
}
imshow("contour drawing",drawing);
}
I think that the problem is in the following two lines:
con = captureframe.clone();
cvtColor(captureframe,con,CV_BGR2GRAY);
In the first line, you are making con as a clone of captureFrame which means that con is a 3 channel image and in the Second line you are trying to make con a grayScale image which is 1 channel therefore you are getting the fault related to the image type.
You should try to do the following (i am not sure whether your code would run after this or not but you should not get the current error after this):
con.create(captureframe.rows , captureframe.cols, CV_8UC1);
cvtColor(captureframe,con,CV_BGR2GRAY);
Guys thank you so much for your help. I finally figured out my mistake and there was a problem in my declaration. I was looking online for some references and then i stumbled upon this code for object detection. The guy actually declared "contour" like this - "std::vector < std::vector < cv::Point > >contours; " and my declaration was "vector contours". My declaration worked for static images but it gave me this error while finding contours from webcam. Can anyone explain me the difference between the above two declarations? Also, as suggested by skm i converted my frame capture to a 1 channel depth image by using the con.create(frame.rows,frame.cols,cv_8uc1) and then converting it to grayscale image. This step is really crucial. So, here is my complete working code!! Thanks
VideoCapture capturedevice;
capturedevice.open(0);
Mat frame,con;
Mat grayframe;
std::vector < std::vector < cv::Point > >contours; //this is very important decalartion
while(true)
{
capturedevice>>frame;
con.create(frame.rows,frame.cols,CV_8UC1);
cvtColor(frame,con,CV_BGR2GRAY);
cv::findContours (con, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
cv::drawContours (frame, contours, -1, cv::Scalar (0, 0, 255), 2);
imshow("frame", frame);
waitKey(33);
}

OpenCV2.4.6 and VS12 error on contour drawing

I am trying to extract and draw contours from an image.
The code I am chosing is mostly taken from the opencv sample code, But When ever I run this code , I got an exception error with message
"First-chance exception at 0x000007FEFDCA9E5D in test1.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000000028EB40.
If there is a handler for this exception, the program may be safely continued."
, I've been looking for a solution but rather I found similar issue .
Is there any solution on following code, because it is most common code if anyone tries to draw contours.
OR I would be very happy with others who are facing same error , if someone put an optimal or common solution for contour extraction
`
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include "opencv2\imgproc\imgproc.hpp"
using namespace cv;
using namespace std;
int main( int argc, const char** argv )
{
Mat img1 = imread("ima1.JPG", CV_LOAD_IMAGE_UNCHANGED);
Mat canny_img1;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
/*Using canny filter for feature extraction in image 1*/
Canny(img1,canny_img1,1,3,3,0);
/* Find contours*/
findContours( canny_img1 , contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/* Draw contours */
// Mat drawing = Mat::zeros( canny_img1.size(), CV_8UC3 );
/// Draw contours
Mat drawing = Mat::zeros( canny_img1.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, 2, 8, hierarchy, 0, Point() );
}
/// Show in a window
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
waitKey(0);
return 0;
}
`
For sample codes to run, you need to have your VS project configured correctly.
You can do this: http://docs.opencv.org/doc/tutorials/introduction/windows_visual_studio_Opencv/windows_visual_studio_Opencv.html?highlight=visual%20studio%20installation
Some of the main points:
You have to go to project properties and set some things:
1) use staticlibrary or dynamic : for that you need to select correctly the appropriate directory in "Additional library directory".
Depending upon the mode in which you are trying to run the project "Debug/Release" if you use staticlib you need to add .lib files with "d" in it before extension.
2) Depending upon the 32 bit or 64 bit project which you are making you need to add appropriate dll directory to System Path.
3) You need to add "Include additional directory to "c\opencv\build\include"
Hope it will help