OpenCV convexity defects drawing - c++

I have stored the defects using convexity defects in an 4 element vector integer array using vec4i.
My convex hull array is in hull element and contours in Contours;
What i want to do is draw a line from start point of a convexity defect to the end point of one.
For this i need to access the element start index which is present in the vec4i of a defects vector!
How do i do this??
#include <opencv\cv.h>
#include <opencv2\highgui\highgui.hpp>
#include<opencv\cvaux.h>
#include<opencv\cxcore.h>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream>
#include<conio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
int main(){
Mat img, frame, img2, img3;
VideoCapture cam(0);
while (true){
cam.read(frame);
cvtColor(frame, img, CV_BGR2HSV);
//thresholding
inRange(img, Scalar(0, 143, 86), Scalar(39, 255, 241), img2);
imshow("hi", img2);
//finding contours
vector<vector<Point>> Contours;
vector<Vec4i> hier;
//morphological transformations
erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
//finding the contours required
findContours(img2, Contours, hier, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0));
//finding the contour of largest area and storing its index
int lrgctridx = 0;
int maxarea = 0;
for (int i = 0; i < Contours.size(); i++)
{
double a = contourArea(Contours[i]);
if (a> maxarea)
{
maxarea = a;
lrgctridx = i;
}
}
//convex hulls
vector<vector<Point> >hull(Contours.size());
vector<vector<Vec4i>> defects(Contours.size());
for (int i = 0; i < Contours.size(); i++)
{
convexHull(Contours[i], hull[i], false);
convexityDefects(Contours[i], hull[i], defects[i]);
}
//REQUIRED contour is detected,then convex hell is found and also convexity defects are found and stored in defects
if (maxarea>100){
drawContours(frame, hull, lrgctridx, Scalar(255, 255, 255), 1, 8, vector<Vec4i>(), 0, Point());
\\ drawing the required lines joining defects!im facing problem on how to acheive this since i dont know how to access the elements stored in defects
line(frame, \\startindex, \\endindex, \\color, 1);
}
imshow("output", frame);
char key = waitKey(33);
if (key == 27) break;
}
}
Also my output window shows error when i add the convexityDefects(..) line i think it is in wrong format!
Thanks in advance.

convexityDefects needs a
Convex hull obtained using convexHull() that should contain indices of the contour points that make the hull.
that contains more than 3 indices. So you need this:
vector<vector<Point> >hull(Contours.size());
vector<vector<int> > hullsI(Contours.size()); // Indices to contour points
vector<vector<Vec4i>> defects(Contours.size());
for (int i = 0; i < Contours.size(); i++)
{
convexHull(Contours[i], hull[i], false);
convexHull(Contours[i], hullsI[i], false);
if(hullsI[i].size() > 3 ) // You need more than 3 indices
{
convexityDefects(Contours[i], hullsI[i], defects[i]);
}
}
Then your drawing part is (adapted from here):
/// Draw convexityDefects
for (int i = 0; i < Contours.size(); ++i)
{
for(const Vec4i& v : defects[i])
{
float depth = v[3] / 256;
if (depth > 10) // filter defects by depth, e.g more than 10
{
int startidx = v[0]; Point ptStart(Contours[i][startidx]);
int endidx = v[1]; Point ptEnd(Contours[i][endidx]);
int faridx = v[2]; Point ptFar(Contours[i][faridx]);
line(frame, ptStart, ptEnd, Scalar(0, 255, 0), 1);
line(frame, ptStart, ptFar, Scalar(0, 255, 0), 1);
line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1);
circle(frame, ptFar, 4, Scalar(0, 255, 0), 2);
}
}
}
Complete code
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat img, frame, img2, img3;
VideoCapture cam(0);
while (true){
cam.read(frame);
cvtColor(frame, img, CV_BGR2HSV);
//thresholding
inRange(img, Scalar(0, 143, 86), Scalar(39, 255, 241), img2);
imshow("hi", img2);
//finding contours
vector<vector<Point>> Contours;
vector<Vec4i> hier;
//morphological transformations
erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
//finding the contours required
findContours(img2, Contours, hier, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0));
//finding the contour of largest area and storing its index
int lrgctridx = 0;
int maxarea = 0;
for (int i = 0; i < Contours.size(); i++)
{
double a = contourArea(Contours[i]);
if (a> maxarea)
{
maxarea = a;
lrgctridx = i;
}
}
//convex hulls
vector<vector<Point> >hull(Contours.size());
vector<vector<int> > hullsI(Contours.size());
vector<vector<Vec4i>> defects(Contours.size());
for (int i = 0; i < Contours.size(); i++)
{
convexHull(Contours[i], hull[i], false);
convexHull(Contours[i], hullsI[i], false);
if(hullsI[i].size() > 3 )
{
convexityDefects(Contours[i], hullsI[i], defects[i]);
}
}
//REQUIRED contour is detected,then convex hell is found and also convexity defects are found and stored in defects
if (maxarea>100){
drawContours(frame, hull, lrgctridx, Scalar(2555, 0, 255), 3, 8, vector<Vec4i>(), 0, Point());
/// Draw convexityDefects
for(int j=0; j<defects[lrgctridx].size(); ++j)
{
const Vec4i& v = defects[lrgctridx][j];
float depth = v[3] / 256;
if (depth > 10) // filter defects by depth
{
int startidx = v[0]; Point ptStart(Contours[lrgctridx][startidx]);
int endidx = v[1]; Point ptEnd(Contours[lrgctridx][endidx]);
int faridx = v[2]; Point ptFar(Contours[lrgctridx][faridx]);
line(frame, ptStart, ptEnd, Scalar(0, 255, 0), 1);
line(frame, ptStart, ptFar, Scalar(0, 255, 0), 1);
line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1);
circle(frame, ptFar, 4, Scalar(0, 255, 0), 2);
}
}
}
imshow("output", frame);
char key = waitKey(33);
if (key == 27) break;
}
}

Related

Can't run c++ project with webcam, but it's actually work with image

I create c++ project named "Document Scanner". With images, he works perfectly but with my webcam, he gives me an error "vector subscript out of range".
Code for images:
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//////////////// Project 2 – Document Scanner ////////////
Mat imgOriginal, imgGray, imgCanny, imgThre, imgBlur, imgDil, imgErode, imgCrop, imgWarp;
vector<Point> initialPoints, docPoints;
float w = 420, h = 596; //dimensions of a4 paper multiplied by 2
Mat preProcessing(Mat img) {
cvtColor(img, imgGray, COLOR_BGR2GRAY);
GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
Canny(imgBlur, imgCanny, 25, 75);
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(imgCanny, imgDil, kernel);
//erode(imgDil, imgErode, kernel);
return imgDil;
}
vector<Point> getContours(Mat image) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(imgDil, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//drawContours(img, contours, -1, Scalar(255, 0, 255), 2);
vector<vector<Point>> conPoly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point> biggest;
int maxArea = 0;
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]);
cout << area << endl;
string objectType;
if (area > 1000) {
float peri = arcLength(contours[i], true);
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);
if (area > maxArea && conPoly[i].size() == 4) {
//drawContours(imgOriginal, conPoly, i, Scalar(255, 0, 255), 5);
biggest = { conPoly[i][0],conPoly[i][1], conPoly[i][2], conPoly[i][3] };
maxArea = area;
}
//drawContours(imgOriginal, conPoly, i, Scalar(255, 0, 255), 2);
//rectangle(imgOriginal, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
}
}
return biggest;
}
void drawPoints(vector<Point> points, Scalar color) {
for (int i = 0; i < points.size(); i++) {
circle(imgOriginal, points[i], 10, color, FILLED);
putText(imgOriginal, to_string(i), points[i], FONT_HERSHEY_PLAIN, 4, color, 4);
}
}
vector<Point> reorder(vector<Point> points) {
vector<Point> newPoints;
vector<int> sumPoints, subPoints;
for (int i = 0; i < 4; i++) {
sumPoints.push_back(points[i].x + points[i].y);
subPoints.push_back(points[i].x - points[i].y);
}
newPoints.push_back(points[min_element(sumPoints.begin(), sumPoints.end()) - sumPoints.begin()]); //0
newPoints.push_back(points[max_element(subPoints.begin(), subPoints.end()) - subPoints.begin()]); //1
newPoints.push_back(points[min_element(subPoints.begin(), subPoints.end()) - subPoints.begin()]); //2
newPoints.push_back(points[max_element(sumPoints.begin(), sumPoints.end()) - sumPoints.begin()]); //3
return newPoints;
}
Mat getWarp(Mat img, vector<Point> points, float w, float h) {
Point2f src[4] = { points[0], points[1], points[2], points[3] };
Point2f dst[4] = { {0.0f,0.0f}, {w,0.0f}, {0.0f,h}, {w, h} };
Mat matrix = getPerspectiveTransform(src, dst);
warpPerspective(img, imgWarp, matrix, Point(w, h));
return imgWarp;
}
void main() {
string path = "Resources/paper.jpg";
imgOriginal = imread(path);
//resize(imgOriginal, imgOriginal, Size(), 0.5, 0.4);
// Preprocessing
imgThre = preProcessing(imgOriginal);
// Get Contours - Biggest
initialPoints = getContours(imgThre);
///drawPoints(initialPoints, Scalar(0,0,255));
docPoints = reorder(initialPoints);
//drawPoints(docPoints, Scalar(0, 255, 0));
// Warp
imgWarp = getWarp(imgOriginal, docPoints, w, h);
//Crop
int cropVal = 5;
Rect roi(cropVal, cropVal, w - (2 * cropVal), h - (2 * cropVal));
imgCrop = imgWarp(roi);
imshow("Image", imgOriginal);
imshow("Image Dilation", imgThre);
imshow("Image Warp", imgWarp);
imshow("Image Crop", imgCrop);
waitKey(0);
}
Code for webcam:
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//////////////// Project 2 – Document Scanner ////////////
Mat img, imgGray, imgCanny, imgThre, imgBlur, imgDil, imgErode, imgCrop, imgWarp;
vector<Point> initialPoints, docPoints;
float w = 420, h = 596; //dimensions of a4 paper multiplied by 2
Mat preProcessing(Mat img) {
cvtColor(img, imgGray, COLOR_BGR2GRAY);
GaussianBlur(imgGray, imgBlur, Size(3, 3), 3, 0);
Canny(imgBlur, imgCanny, 25, 75);
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(imgCanny, imgDil, kernel);
//erode(imgDil, imgErode, kernel);
return imgDil;
}
vector<Point> getContours(Mat image) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//drawContours(img, contours, -1, Scalar(255, 0, 255), 2);
vector<vector<Point>> conPoly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point> biggest;
int maxArea = 0;
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]);
cout << area << endl;
if (area > 1000) {
float peri = arcLength(contours[i], true);
approxPolyDP(contours[i], conPoly[i], 0.02 * peri, true);
if (area > maxArea && conPoly[i].size() == 4) {
//drawContours(imgOriginal, conPoly, i, Scalar(255, 0, 255), 5);
biggest = { conPoly[i][0],conPoly[i][1], conPoly[i][2], conPoly[i][3] };
maxArea = area;
}
//drawContours(imgOriginal, conPoly, i, Scalar(255, 0, 255), 2);
//rectangle(imgOriginal, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 255, 0), 5);
}
}
return biggest;
}
void drawPoints(vector<Point> points, Scalar color) {
for (int i = 0; i < points.size(); i++) {
circle(img, points[i], 10, color, FILLED);
putText(img, to_string(i), points[i], FONT_HERSHEY_PLAIN, 4, color, 4);
}
}
vector<Point> reorder(vector<Point> points) {
vector<Point> newPoints;
vector<int> sumPoints, subPoints;
for (int i = 0; i < 4; i++) {
sumPoints.push_back(points[i].x + points[i].y);
subPoints.push_back(points[i].x - points[i].y);
}
newPoints.push_back(points[min_element(sumPoints.begin(), sumPoints.end()) - sumPoints.begin()]); //0
newPoints.push_back(points[max_element(subPoints.begin(), subPoints.end()) - subPoints.begin()]); //1
newPoints.push_back(points[min_element(subPoints.begin(), subPoints.end()) - subPoints.begin()]); //2
newPoints.push_back(points[max_element(sumPoints.begin(), sumPoints.end()) - sumPoints.begin()]); //3
return newPoints;
}
Mat getWarp(Mat img, vector<Point> points, float w, float h) {
Point2f src[4] = { points[0], points[1], points[2], points[3] };
Point2f dst[4] = { {0.0f,0.0f}, {w,0.0f}, {0.0f,h}, {w, h} };
Mat matrix = getPerspectiveTransform(src, dst);
warpPerspective(img, imgWarp, matrix, Point(w, h));
return imgWarp;
}
void main() {
VideoCapture cap(0);
//string path = "Resources/paper.jpg";
//imgOriginal = imread(path);
//resize(imgOriginal, imgOriginal, Size(), 0.5, 0.4);
while (true) {
cap.read(img);
// Preprocessing
imgThre = preProcessing(img);
// Get Contours - Biggest
initialPoints = getContours(imgThre);
///drawPoints(initialPoints, Scalar(0,0,255));
docPoints = reorder(initialPoints);
//drawPoints(docPoints, Scalar(0, 255, 0));
// Warp
imgWarp = getWarp(img, docPoints, w, h);
//Crop
int cropVal = 5;
Rect roi(cropVal, cropVal, w - (2 * cropVal), h - (2 * cropVal));
imgCrop = imgWarp(roi);
//imshow("Image", imgOriginal);
//imshow("Image Dilation", imgThre);
//imshow("Image Warp", imgWarp);
imshow("Image Crop", imgCrop);
waitKey(1);
}
}
After debugging my program I find an error in function "reorder", when I push_back(). How can I resolve that problem?

Crop Triangle with opencv c++

User,
I want to crop that Triangle on the image and show it in another window with opencv c++. I know all three Coordinates.
Can anyone help me? I did not find any answer on the Internet about "triangle cropping". Thanks!
EDIT: The Problem here is that i cannot use ROI for cropping the Triangle. I have to copy just the triangle without any background or something around. Is it possible to create my own ROI by knowing the Coordinates of the triangle [p1(302,179), p2(329,178), p3(315,205)]?
cv::Mat inputImage = cv::imread("input.png");
if (inputImage.channels() > 1)
{
cv::cvtColor(inputImage, inputImage, CV_RGB2GRAY);
}
// replace these values with your actual coordinates
// I found these by first saving your provided image, then
// using Microsoft Paint
int x0 = 242;
int y0 = 164;
int x1 = 314;
int y1 = 38;
int x2 = 387;
int y2 = 164;
// then create a line masking using these three points
cv::Mat lineMask = cv::Mat::zeros(inputImage.size(), inputImage.type());
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x1, y1), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
// perform contour detection on your line mask
cv::vector<cv::vector<cv::Point>> contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(lineMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
// calculate the distance to the contour
cv::Mat raw_dist(lineMask.size(), CV_32FC1);
for (int i = 0; i < lineMask.rows; i++)
{
for (int j = 0; j < lineMask.cols; j++)
{
raw_dist.at<float>(i, j) = cv::pointPolygonTest(contours[0], cv::Point2f(j, i), true);
}
}
double minVal; double maxVal;
cv::minMaxLoc(raw_dist, &minVal, &maxVal, 0, 0, cv::Mat());
minVal = std::abs(minVal);
maxVal = std::abs(maxVal);
// depicting the distances graphically
cv::Mat mask = cv::Mat::zeros(inputImage.size(), CV_8UC1);
for (int i = 0; i < mask.rows; i++)
{
for (int j = 0; j < mask.cols; j++)
{
if (raw_dist.at<float>(i, j) < 0)
{
mask.at<uchar>(i, j) = static_cast<uchar>(0);
continue;
}
mask.at<uchar>(i, j) = static_cast<uchar>(255);
}
}
// inverse the input image
cv::Mat invInput;
cv::bitwise_not(inputImage, invInput);
// then get only the region of your triangle
cv::Mat outputImage;
invInput.copyTo(outputImage, mask);
cv::bitwise_not(outputImage, outputImage);
// display for debugging purpose
cv::imshow("inputImage", inputImage);
cv::imshow("lineMask", lineMask);
cv::imshow("mask", mask);
cv::imshow("outputImage", outputImage);
cv::waitKey();
This is your inputImage:
This is your lineMask:
This is your created binary mask:
And this is your final outputImage:
References:
OpenCV draw line
OpenCV findContours
Point Polygon Test
you can do it by using mask as shown with the code below
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread( argv[1] );
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY );
gray = gray < 127;
vector<vector<Point> > contours;
findContours(gray, contours,
RETR_EXTERNAL,
CHAIN_APPROX_SIMPLE);
for( size_t i = 0; i< contours.size(); i++ )
{
Rect rect = boundingRect(contours[i]);
Mat mask = gray(rect);
Mat srcROI = src(rect);
srcROI.setTo(Scalar(0,0,255),mask);
imshow("srcROI",srcROI);
waitKey();
}
imshow( "result", src );
waitKey(0);
return(0);
}
EDIT: according the change on the question i suggest the test code below
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread("lena.jpg");
vector<Point> points;
points.push_back( Point(200,200));
points.push_back( Point(370,370));
points.push_back( Point(220,410));
Mat mask = Mat::zeros( src.size(), CV_8UC1 );
fillConvexPoly( mask, points, Scalar( 255 ));
Rect rect = boundingRect( points );
Mat roi = src( rect ).clone();
mask = mask( rect ).clone();
rect.x = rect.x - 180;
rect.y = rect.y - 180;
Mat srcROI = src( rect );
roi.copyTo( srcROI, mask );
imshow( "result", src );
waitKey(0);
return(0);
}
As you told that you know co-ordinates of the triangle, using below code you can find triangle.
Mat image = imread("imagePath");
bitwise_not(image, image);
Mat grayImage;
cv::cvtColor(image, grayImage, CV_RGB2GRAY);
cv::vector<cv::vector<cv::Point> > contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(grayImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
Mat contourMat(grayImage.size(), grayImage.type(), Scalar(255));
for(int i = 0; i < contours.size(); i++)
{
if(contours[i].data()->x == 314 && contours[i].data()->y == 37)
drawContours(contourMat, contours, i, Scalar(0), CV_FILLED, 8, hierarchy);
}
imshow("WindowName", contourMat);
Hope this will help.

Open cv finding convex hull

The following code in OpenCV is for me to detect a yellow color ball and draw its convex hull.The code although doesnt give any compilation errors,gives the following error in the output window.
I used the largest area function to avoid smaller unwanted contours.
The error is
Assertion failed <0 <= contourIdx && contourIdx< last> in cv::drawContours ,file C:Buildsmasters..(some path),line 2299****
#include <opencv\cv.h>
#include <opencv2\highgui\highgui.hpp>
#include<opencv\cvaux.h>
#include<opencv\cxcore.h>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream>
#include<conio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
int main(){
Mat img, frame, img2, img3;
double maxarea = 0;
int lrgctridx; //largest contour index
VideoCapture cam(0);
while (true){
cam.read(frame);
cvtColor(frame, img, CV_BGR2HSV);
//thresholding
inRange(img, Scalar(0, 143, 86), Scalar(39, 255, 241), img2);
//finding contours
vector<vector<Point>> Contours;
vector<Vec4i> hier;
//morphological transformations
erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
erode(img2, img2, getStructuringElement(MORPH_RECT, Size(3, 3)));
dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
dilate(img2, img2, getStructuringElement(MORPH_RECT, Size(8, 8)));
//finding the contours required
findContours(img2, Contours, hier, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0));
//finding the contour of largest area and storing its index
for (int i = 0; i < Contours.size(); i++)
{
double a=contourArea(Contours[i]);
if (a> maxarea)
{
maxarea = a;
lrgctridx=i;
}
}
//convex hulls
vector<vector<Point> >hull(Contours.size());
for (int i = 0; i < Contours.size(); i++)
{
convexHull(Contours[i], hull[i], false);
}
//REQUIRED contour is detected,then draw a convex hull
if (maxarea!=0)
drawContours(frame, hull, lrgctridx, Scalar(255, 255, 255), 1, 8, vector<Vec4i>(), 0, Point());
imshow("output", frame);
char key = waitKey(33);
if (key == 27) break;
}
}
Any help would be much appreciated.Thaanks in advance!
You should reset lrgctridx at every iteration.
Say you find a countour at time "t", and you set lrgctridx = 1;. At time "t+1" you don't find any contours, so Contours and hull size will be 0, but you're trying to access position 1.
Just put lrgctridx = 0 before the for loop. Same for maxarea.
lrgctridx = 0;
maxarea = 0;
for (int i = 0; i < Contours.size(); i++)
{
....
Now your condition to draw contours is ok, but you'd better replace it with
if(!Contours.empty()) {
drawContours(...);
....

OpenCV c++ assertion failed <i < 0> in cv::_InputArray::getMat

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/background_segm.hpp>
#include <iostream>
#include <windows.h>
using namespace cv;
using namespace std;
//initial min and max HSV filter values.
//these will be changed using trackbars
Mat src; Mat HSV; Mat roi; Mat range; Mat eroded; Mat gray;
int thresh = 100;
int max_thresh = 255;
/** #function main */
int main(int argc, char** argv)
{
createTrackbars();
VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
namedWindow("background", 1);
int waitTime = 50;
int counter = 101;
int roiLeft = 20;
int roiTop = 50;
int roiRight = 200;
int roiBottom = 200;
Rect rRoi = Rect(roiLeft, roiTop, roiRight, roiBottom);
Mat background;
cap >> background;
background = background(rRoi);
//cvtColor(background, background, CV_BGR2HSV);
//imshow("background", background);
vector<vector<Point> > contours;
vector<vector < cv::Point >> hull(1);
vector<Vec4i> hierarchy;
vector<CvConvexityDefect> defects;
while (true)
{
cap >> src;
//Create the region of interest.
Mat iRoi = src.clone()(rRoi);
Mat iRoiSRC = src(rRoi);
//Draw a rectangle there.
rectangle(src, rRoi, Scalar(255, 128, 0), 1, 8, 0);
//imshow("roi", iRoi);
//Subtract the static background.
absdiff(iRoi, background, iRoi);
//imshow("diff", iRoi);
//Convert it to a GrayScale and threshold it.
cvtColor(iRoi, iRoi, CV_BGR2GRAY);
threshold(iRoi, gray, 15, 255, CV_THRESH_BINARY);
//Perform a closing.
Mat erodeElement = getStructuringElement(MORPH_ELLIPSE, Size(erodeSize, erodeSize));
Mat dilateElement = getStructuringElement(MORPH_ELLIPSE, Size(dilateSize, dilateSize));
for (int index = 0; index < loopAmount; index++)
{
erode(gray, gray, erodeElement);
dilate(gray, gray, dilateElement);
}
//imshow("range", gray);
//Find the contours.
findContours(gray, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//Pick the biggest contour.
int biggestContourIndex = 0;
int largestArea = 0;
for (int i = 0; i < contours.size(); i++)
{
if (contours[i].size() > largestArea)
{
largestArea = contours[i].size();
biggestContourIndex = i;
}
}
vector<int> hullsI;
vector<Point> hullsP;
vector<Vec4i> defects;
//Find the convex hull.
if (contours.size() > 0)
{
convexHull(contours[biggestContourIndex], hullsI, true, true);
convexHull(contours[biggestContourIndex], hullsP, true, true);
}
//Find the convexity defects.
if (contours.size() > 0)
{
if (contours[biggestContourIndex].size() > 3)
{
convexityDefects(contours[biggestContourIndex], hullsI, defects);
}
}
//Draw the biggest contour and its convex hull.
Scalar colorOne = Scalar(255, 128, 0);
Scalar colorTwo = Scalar(0, 0, 255);
if (contours.size() > 0)
{
drawContours(iRoiSRC, contours, biggestContourIndex, colorOne, 2, 8, hierarchy, 0, Point());
drawContours(iRoiSRC, hullsP, 0, colorTwo, 1, 8, vector<Vec4i>(), 0, Point());
rectangle(iRoiSRC, boundingRect(contours[biggestContourIndex]), Scalar(0, 255, 0), 1, 8, 0);
}
imshow("src", src);
if (waitKey(waitTime) >= 0) break;
}
return(0);
}
There is a rectangle in the upper left of the screen, where my hand will be recognized once I hold it there.
The error that i get appears at the first drawContours. The full error which is given to me by the console is: OpenCV Error: Assertion failed <i <0> in cv::_InputArray::getMat, file C:\buildslave64\win64_amdoc1\2_4_PackSlave-win64-vc11-shared\opencv\modules\core\src\matrix.cpp, line 963
I've been extensively searching for a solution on multiple sites, including stackoverflow but none of the solution seem to be working.
Any help would be appreciated.
I use Visual studio 2013 with OpenCV-2.4.10
converting vector<CvConvexityDefect> defects; to a point seemed to do the trick

OPENCV: PCA application error in image_proc

Base from this here.
I got this error and this is the only one left for almost 3 days of my trial and error in debugging:
Unhandled exception at 0x000007FEEC6315A4 (opencv_imgproc242.dll) in PCA.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
Please can someone here who can help me with this. Im currently using VS2012 and my os is win7 64-bit. I configure my opencv 2.4.2 following this blog.
Please help!
I've corrected some minor bugs (and now it works perfect for me):
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
double getOrientation(vector<Point> &pts, Mat &img)
{
if (pts.size() == 0) return false;
//Construct a buffer used by the pca analysis
Mat data_pts = Mat(pts.size(), 2, CV_64FC1);
for (int i = 0; i < data_pts.rows; ++i)
{
data_pts.at<double>(i, 0) = pts[i].x;
data_pts.at<double>(i, 1) = pts[i].y;
}
//Perform PCA analysis
PCA pca_analysis(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
//Store the position of the object
Point pos = Point(pca_analysis.mean.at<double>(0, 0),
pca_analysis.mean.at<double>(0, 1));
//Store the eigenvalues and eigenvectors
vector<Point2d> eigen_vecs(2);
vector<double> eigen_val(2);
for (int i = 0; i < 2; ++i)
{
eigen_vecs[i] = Point2d(pca_analysis.eigenvectors.at<double>(i, 0),
pca_analysis.eigenvectors.at<double>(i, 1));
eigen_val[i] = pca_analysis.eigenvalues.at<double>(i);
}
// Draw the principal components
circle(img, pos, 3, CV_RGB(255, 0, 255), 2);
line(img, pos, pos + 0.02 * Point(eigen_vecs[0].x * eigen_val[0], eigen_vecs[0].y * eigen_val[0]) , CV_RGB(255, 255, 0));
line(img, pos, pos + 0.02 * Point(eigen_vecs[1].x * eigen_val[1], eigen_vecs[1].y * eigen_val[1]) , CV_RGB(0, 255, 255));
return atan2(eigen_vecs[0].y, eigen_vecs[0].x);
}
int main()
{
// Read the image
Mat bw, img = imread("pca_test1.jpg",1); // "pca_test2.jpg"
// Convert it to greyscale
cvtColor(img, bw, COLOR_BGR2GRAY);
// Apply thresholding
threshold(bw, bw, 150, 255, cv::THRESH_BINARY);
// Find all objects of interest
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(bw, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);
// For each object
for (size_t i = 0; i < contours.size(); ++i)
{
// Calculate its area
double area = contourArea(contours[i]);
// Ignore if too small or too large
if (area < 1e2 || 1e5 < area) continue;
// Draw the contour
drawContours(img, contours, i, CV_RGB(255, 0, 0), 2, 8, hierarchy, 0);
// Get the object orientation
getOrientation(contours[i], img);
}
imshow("Image", img);
char key;
while (true)
{
key = waitKey(1);
if (key == 'q') break;
}
cv::destroyAllWindows();
return 0;
}