I'm developing project using java to identify components using opencv package but I'm new to javacv and I just want to know how to identify rectangles in a particular source image please can some experience person give some basic guide line to archive this task. I try to use template matching on here but it can identify exact size rectangle only. But In my case I need to identify variable length rectangle ?
import java.util.Arrays;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
public class TestingTemplate {
public static void main(String[] args) {
//Original Image
IplImage src = cvLoadImage("src\\lena.jpg",0);
//Template Image
IplImage tmp = cvLoadImage("src\\those_eyes.jpg",0);
//The Correlation Image Result
IplImage result = cvCreateImage(cvSize(src.width()-tmp.width()+1, src.height()-tmp.height()+1), IPL_DEPTH_32F, 1);
//Init our new Image
cvZero(result);
cvMatchTemplate(src, tmp, result, CV_TM_CCORR_NORMED);
double[] min_val = new double[2];
double[] max_val = new double[2];
//Where are located our max and min correlation points
CvPoint minLoc = new CvPoint();
CvPoint maxLoc = new CvPoint();
cvMinMaxLoc(result, min_val, max_val, minLoc, maxLoc, null); //the las null it's for
optional mask mat()
System.out.println(Arrays.toString(min_val)); //Min Score
System.out.println(Arrays.toString(max_val)); //Max Score
CvPoint point = new CvPoint();
point.x(maxLoc.x()+tmp.width());
point.y(maxLoc.y()+tmp.height());
cvRectangle(src, maxLoc, point, CvScalar.WHITE, 2, 8, 0); //Draw the rectangule result in original img.
cvShowImage("Lena Image", src);
cvWaitKey(0);
//Release
cvReleaseImage(src);
cvReleaseImage(tmp);
cvReleaseImage(result);
}
}
Please can some one help to accomplish this
(So it is fixed as square.)
For square detection, OpenCV comes with some samples for this. Codes are in C++, C, Python. Hope you can port this to JavaCV.
I will just illustrate how it works:
1 - First you split the image to R,G,B planes.
2 - Then for each plane perform edge detection, and in addition to that, threshold for different values like 50, 100, .... etc.
3 - And in all these binary images, find contours ( remember it is processing a lot of images, so may be a little bit slow, if you don't want, you can remove some threshold values).
4 - After finding contours, remove some small unwanted noises by filtering according to area.
5 - Then, approximate the contour. (More about contour approximation).
6 - For a rectangle, it will give you the four corners. For others, corresponding corners will be given.
So filter these contours with respect to number of elements in approximated contour that should be four, which is same as number of corners. First property of rectangle.
7 - Next, there may be some shapes with four corners but not rectangles. So we take second property of rectangles, ie all inner angles are 90. So we find the angle at all the corners using the relation below :
And if cos (theta) < 0.1, ie theta > 84 degree, that is a rectangle.
8 - Then what about the square? Use its property, that all the sides are equal.
You can find the distance between two points by the relation as shown above. Check if they all are equal, then that rectangle is a square.
This is how the code works.
Below is the output I got applying above mentioned code on an image :
EDIT :
It has been asked how to remove the rectangle detected at the border. It is because, opencv finds white objects in black background, so is border. Just inverting the image using cv2.bitwise_not() function will solve the problem. we get the result as below:
You can find more information about contour here : Contours - 1 : Getting Started