boundingrect not working for a contour in opencv c++ - opencv

{
#include<opencv2\opencv.hpp>
#include<iostream>
#include<conio.h>
using namespace std;
using namespace cv;
int main()
{
int a = 0;
Mat frame, diffimage,back,frame_gray;
VideoCapture cap("D:\\elance\\check\\Sent3.avi");
vector<vector<Point>> contours;
BackgroundSubtractorMOG2 bg;
vector<int> params;
params.push_back(CV_IMWRITE_PNG_COMPRESSION);
params.push_back(9);
for (int i = 0; i < 200;i++)
{
cap >> frame;
if (frame.empty())
break;
bg(frame,back);
}
bg.getBackgroundImage(back);
cap.set(CV_CAP_PROP_POS_FRAMES,0);
cvtColor(back, back, CV_BGR2GRAY);
//for (int f = 0; f < 20;f++)
while (1)
{
a = a + 1;
cout << "Frame no : " << a<<endl;
cap >> frame;
if (frame.empty())
break;
cvtColor(frame, frame_gray, CV_BGR2GRAY);
absdiff(frame_gray, back, diffimage);
threshold(diffimage, diffimage, 10, 255, CV_THRESH_BINARY);
for (int i = 0; i < 2; i++)
{
cv::erode(diffimage, diffimage, cv::Mat());
cv::dilate(diffimage, diffimage, cv::Mat());
}
findContours(diffimage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
cout << "Contour Size : " << contours.size()<<endl;
vector<Rect> boundRect(contours.size());
for (int i = 0; i < contours.size(); i++)
{
drawContours(frame, contours, i, cv::Scalar(0, 255, 255), 1);
Mat smoothCont;
smoothCont = cv::Mat(contours[i]);
cout << smoothCont.rows << "\t" << smoothCont.cols <<"\t"<<smoothCont.depth()<< endl << endl;
if (smoothCont.rows > 0 && smoothCont.rows < 10000)
boundRect[i] = boundingRect(Mat(contours[i]));
}
for (int i = 0; i < contours.size(); i++)
rectangle(frame, boundRect[i], Scalar(0, 255, 255), 1, 8, 0);
imshow("Diff", diffimage);
imshow("frame", frame);
imwrite("D:\\test.jpg", frame, params);
waitKey(30);
break;
}
}
This code basically takes the contours and results are the rectangles on the contours. But only one is bounded by the box and other contour is is still not bounded box.
Can anyone help in this matter ?

Maybe "if (smoothCont.rows > 0 && smoothCont.rows < 10000)" filtered them out?

Related

Implementing Lucas Kanade Method

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

Application error(0xc000007b) when runnning Opencv example in Visual Studio 2015

I am running canny edge example in Visual Studio 2015 and i got this error.
The application was unable to start correctly (0xc000007b).
And then visual studio show to this error.
Unhandled exception at 0x77A2D5B2 (ntdll.dll) in Canny Edge.exe: 0xC000007B: %hs is either not designed to run on Windows or it contains an error. Try installing the program again using the original installation media or contact your system administrator or the software vendor for support. Error status 0x.
I quite sure this coding is working as i ran this coding before in Visual Studio 2013. Here is my coding.
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <algorithm>
using namespace cv;
using namespace std;
void help()
{
cout << "\nThis program demonstrates line finding with the Hough transform.\n"
"Usage:\n"
"./houghlines <image_name>, Default is pic1.jpg\n" << endl;
}
bool less_by_y(const cv::Point& lhs, const cv::Point& rhs)
{
return lhs.y < rhs.y;
}
int main(int argc, char** argv)
{
const char* filename = argc >= 2 ? argv[1] : "pic1.jpg";
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
Rect roi;
Mat src = imread("test_4_1.png");
if (src.empty())
{
help();
cout << "can not open " << filename << endl;
return -1;
}
Mat dst, cdst;
Canny(src, dst, 50, 200, 3);
cvtColor(dst, cdst, CV_GRAY2BGR);
findContours(dst, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//vector<Vec2f> lines;
//HoughLines(dst, lines, 1, CV_PI / 180, 50, 0, 0);
//for (size_t i = 0; i < lines.size(); i++)
//{
// float rho = lines[i][0], theta = lines[i][1];
// Point pt1, pt2;
// double a = cos(theta), b = sin(theta);
// double x0 = a*rho, y0 = b*rho;
// pt1.x = cvRound(x0 + 1000 * (-b));
// pt1.y = cvRound(y0 + 1000 * (a));
// pt2.x = cvRound(x0 - 1000 * (-b));
// pt2.y = cvRound(y0 - 1000 * (a));
// line(cdst, pt1, pt2, Scalar(0, 0, 255), 1, CV_AA);
// cout << pt1 << " " << pt2 << endl;
//}
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI / 180, 30, 50, 10);
for (size_t i = 0; i < lines.size(); i++)
{
Vec4i l = lines[i];
line(cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, CV_AA);
cout << l << endl;
}
cout << endl << lines.size() << endl;
cout << arcLength(contours[0], true) << endl;
cout << dst.size() << endl << endl;
for (int a = 0; a < contours[0].size(); a++){
cout << contours[0][a] << " ";
}
vector<Point> test = contours[0];
auto mmx = std::minmax_element(test.begin(), test.end(), less_by_y);
cout << endl << *mmx.first._Ptr << endl << *mmx.second._Ptr;
vector<Point> test2 = contours[1];
auto mmx_1 = std::minmax_element(test2.begin(), test2.end(), less_by_y);
cout << endl << *mmx_1.first._Ptr << endl << *mmx_1.second._Ptr;
imshow("source", src);
imshow("detected lines", cdst);
/* ROI by creating mask for the parallelogram */
Mat mask = cvCreateMat(dst.size().height, dst.size().width, CV_8UC1);
// Create black image with the same size as the original
for (int i = 0; i < mask.cols; i++)
for (int j = 0; j < mask.rows; j++)
mask.at<uchar>(Point(i, j)) = 0;
cout <<endl<<endl<< *mmx.first._Ptr << *mmx.second._Ptr << *mmx_1.first._Ptr << *mmx_1.second._Ptr << endl;
// Create Polygon from vertices
vector<Point> ROI_Vertices = { *mmx.first._Ptr, *mmx.second._Ptr, *mmx_1.first._Ptr, *mmx_1.second._Ptr};
vector<Point> ROI_Poly;
approxPolyDP(ROI_Vertices, ROI_Poly, 1.0, false);
// Fill polygon white
fillConvexPoly(mask, &ROI_Poly[0], ROI_Poly.size(), 255, 8, 0);
cout << ROI_Poly.size() << endl;
// Create new image for result storage
Mat imageDest = cvCreateMat(dst.size().height, dst.size().width, CV_8UC3);
// Cut out ROI and store it in imageDest
src.copyTo(imageDest, mask);
imshow("mask", mask);
imshow("image", imageDest);
waitKey();
return 0;
}
Actually my comment is the answer, with some additions
What OpenCV Libs are you linking to? Are you linking to vs12? Because
you need to upgrade your linker to vs13 for MSVS 2015
OpenCV Doesn't come with Visual Studio 15 pre-builds, so you need to build OpenCV yourself for VS2015
This person seems to have had a similar problem and talks you through how to compile for VS2015

Extract Contours path attributes

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 to detect squares in a video using openCV for iOS?

I'm trying to detect squares shape in a video, application crashes and showing following error.
OpenCV Error: Assertion failed (j < nsrcs && src[j].depth() == depth) in mixChannels, file /Users/alexandershishkov/opencv2.4.3rc/opencv/modules/core/src/convert.cpp, line 472
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /Users/alexandershishkov/opencv2.4.3rc/opencv/modules/core/src/convert.cpp:472: error: (-215) j < nsrcs && src[j].depth() == depth in function mixChannels
here is the code.
vector<vector<cv::Point> > squares;
cvtColor(image,image,CV_BGR2GRAY);
GaussianBlur(image,image,cv::Size(9,11),0,0);
find_squares(image, contours);
void find_squares(Mat& image, vector<vector<cv::Point> >& squares)
{
Mat blurred(image);
medianBlur(image, blurred, 9);
Mat gray0(blurred.size(), CV_8U), gray;
vector<vector<cv::Point> > contours;
for (int c = 0; c < 3; c++)
{
int ch[] = {c, 0};
mixChannels(&blurred, 1, &gray0, 1, ch, 1);
const int threshold_level = 2;
for (int l = 0; l < threshold_level; l++)
{
if (l == 0)
{
Canny(gray0, gray, 10, 20, 3);
dilate(gray, gray, Mat(), cv::Point(-1,-1));
}
else
{
gray = gray0 >= (l+1) * 255 / threshold_level;
}
findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
vector<cv::Point> approx;
for (size_t i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
if (approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx)))
{
double maxCosine = 0;
for (int j = 2; j < 5; j++)
{
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
if (maxCosine < 0.3)
squares.push_back(approx);
}
}
}
}
}
blurred and gray0 are 1-channel images. So, you try to copy second and third channels of blurred image which does not exit! The error should be because of this.
I hope it helps. I do not have any idea about rest of the code and what do you want to do.

OpenCV find sub images

I have a scanner which is big enough to scan multiple pictures at once.
Unfortunatelly, all the pictures are stored in one jpg file, separated only by
white borders. Is there any way to automatically find the sub images and store them
in separate files? I was thinking about using OpenCV to get the job done, but
I can't find the right functions. Does anybody know which OpenCV function would work, or if there is any other approach (using linux)?
Thanks,
Konstantin
My quick and dirty solution that worked with my images looks like this. I hope people with similar problem can use this as a starting point on how to use OpenCV.
// g++ `pkg-config --cflags --libs opencv` parse.cp
// include standard OpenCV headers, same as before
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
// all the new API is put into "cv" namespace. Export its content
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
string imagename = argc > 1 ? argv[1] : "lena.jpg";
// the newer cvLoadImage alternative with MATLAB-style name
Mat imgf = imread("original/"+imagename);
if( !imgf.data ) // check if the image has been loaded properly
return -1;
int border = 1000;
Mat img(imgf.rows+2*border,imgf.cols+2*border,CV_8UC3,Scalar(255,255,255));
for (int i=0; i<imgf.cols; ++i) {
for (int j=0; j<imgf.rows; ++j) {
img.at<Vec3b>(j+border,i+border) = imgf.at<Vec3b>(j,i);
}
}
cout << "created border\n";
Mat mask;
img.copyTo(mask);
Scalar diff(2,2,2);
floodFill(mask, Point(0,0), Scalar(0,0,255), NULL, diff, diff);
cout << "flood filled\n";
imwrite("flood.png",mask);
for (int i=0; i<mask.cols; ++i) {
for (int j=0; j<mask.rows; ++j) {
if(mask.at<Vec3b>(j,i) != Vec3b(0,0,255)) {
mask.at<Vec3b>(j,i) = Vec3b(0,0,0);
} else {
mask.at<Vec3b>(j,i) = Vec3b(255,255,255);
}
}
}
cvtColor( mask, mask, CV_RGB2GRAY );
cout << "mask created\n";
imwrite("binary.png",mask);
Mat sobelX;
Mat sobelY;
Mat sobel;
Sobel(mask,sobelX,CV_16S,1,0);
Sobel(mask,sobelY,CV_16S,0,1);
sobel = abs(sobelX)+abs(sobelY);
for (int i=0; i<mask.cols; ++i) {
for (int j=0; j<mask.rows; ++j) {
mask.at<char>(j,i) = abs(sobelX.at<short>(j,i))+abs(sobelY.at<short>(j,i));
}
}
threshold(mask, mask, 127, 255, THRESH_BINARY);
cout << "sobel done\n";
imwrite("sobel.png",mask);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(mask, contours, hierarchy,
CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
imwrite("contours.png",mask);
cout << "contours done\n";
// iterate through all the top-level contours
int idx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0] )
{
RotatedRect box = minAreaRect(contours[idx]);
if(box.size.width > 100 && box.size.height > 100) {
Mat rot = getRotationMatrix2D(box.center,box.angle,1.0);
Mat rotimg;
warpAffine(img,rotimg,rot,Size(img.cols,img.rows));
imwrite("rotimg.png",rotimg);
Mat subimg(box.size.width,box.size.height,CV_8UC3);
getRectSubPix(rotimg,box.size,box.center,subimg);
stringstream name;
name << "subimg_"<< imagename << "_" << idx << ".png";
cout << name.str() << "\n";
imwrite(name.str(),subimg);
}
}
imwrite("img.png",img);
imwrite("mask.png",mask);
cout << "Done\n";
return 0;
}

Resources