I want to detect the squares of pictures, but I am having problems when calculating the amount of the existing squares. In the picture there are 6 piece of squares, but there are 8 pieces that were detected, 3 of which were detected twice.
This is the result of image detection http://i698.photobucket.com/albums/vv347/holybring18/Screenshot_2013-11-01-07-37-17.png
this is the preprocess http://i698.photobucket.com/albums/vv347/holybring18/Screenshot_2013-11-01-07-37-49.png
this is my code, i got from squares.cpp example code. I code this in my Android with native language, so everything about squares detection is handled by my native code. But i modified a little Because there was an annoying error at mixChannels () that i do not know how to fix it.
// jlong from java convert to references to Mat
// for image source and image result
Mat& matsrc = *(Mat*)alamatMatSrc;
Mat& matres = *(Mat*)alamatMatRes;
// needed matrix
Mat gray;
Mat blur;
Mat bw;
Mat dil;
Mat er;
// tempat menyimpan kontur dan estimasi sudut
vector<vector<Point> > squares;
vector<vector<Point> > contours;
vector<Point> approx;
// convert to grayscale
cvtColor(matsrc, gray, CV_BGR2GRAY);
// blur for reducing noise
medianBlur(gray, blur, 9);
// edge detection with Canny
Canny(blur, bw, 0, 50);
// dilate to ensure there is no cut off lines
dilate(bw, dil, Mat(), Point(-1,-1));
// find all contours
findContours(dil, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
// loop to find the squares
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);
// 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++) {
Point pt1 = approx[j%4];
Point pt2 = approx[j-2];
Point pt3 = approx[j-1];
double cosine = fabs(sudut(pt1, pt2, pt3));
maxCosine = MAX(maxCosine, cosine);
}
if (maxCosine < 0.1) squares.push_back(approx);
}
}
And this is the my java code when invoking the native
// provide Mat for the source and for the result
mymatsrc = new Mat(mybmp.getWidth(), mybmp.getHeight(), CvType.CV_8UC1);
mymatres = new Mat(mybmp.getWidth(), mybmp.getHeight(), CvType.CV_8UC1);
// convert bitmap to Mat, then pass the Mat adress to native, process, and convert it again to bitmap
Utils.bitmapToMat(mybmp, mymatsrc);
Utils.bitmapToMat(mybmp, mymatres);
preProcess(mymatsrc.getNativeObjAddr(), mymatres.getNativeObjAddr());
Utils.matToBitmap(mymatres, mybmp);
// show the processed picture
imageView.setImageBitmap(mybmp);
My point is:
- why my code detected square more than it should be?
- how do I fix this?
- I found a few people experiencing errors on mixChannel () and i can not find the solution, is anyone knows how to fix this, this is the error message.
Invalid arguments ' Candidates are: void mixChannels(const cv::Mat *, ?, cv::Mat *, ?, const int *, ?) void mixChannels(const cv::_InputArray &, const cv::_InputArray &, const std::vector> &) void mixChannels(const std::vector> &, std::vector> &, const int *, ?) '
mixChannels()
call, otherwise it is impossible to know what is wrong – Bull