I am trying to implement some image processing using OpenCV and Java to extract a card out of an image.
Following is my approach:
- Convert to BGR image
- Convert to GRAY image
- Apply GaussianBlur
- Apply Canny Edge detection
- Dilate
- Find contours
- Find the largest contour
- Find corners of the largest contour using approxPolyDP
- Getting a top-down view of the cropped image along the largest contour
At step no 8, I am facing some issues, as I am not getting the appropriate corners/vertices. Following sample images shows the scenario :
After edge detection and dilation. (What is to be done to get appropriate edges?? Here I've got broken edges. Could not get Hough transform working)
After finding vertices. (shown in green)
Following is the code :
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
//load Image
File input = new File("card4.png");
BufferedImage image = ImageIO.read(input);
byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
//put read image to Mat
mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); //original Mat
mat.put(0, 0, data);
mat_f = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); //for storing manipulated Mat
//conversion to grayscale, blurring and edge detection
Imgproc.cvtColor(mat, mat_f, Imgproc.COLOR_RGB2BGR);
Imgproc.cvtColor(mat_f, mat_f, Imgproc.COLOR_RGB2GRAY);
Imgproc.GaussianBlur(mat_f, mat_f, new Size(13,13), 0);
Imgproc.Canny(mat_f, mat_f, 300, 600, 5, true);
Imgproc.dilate(mat_f, mat_f, new Mat(), new Point(-1, -1), 2);
Imgcodecs.imwrite("D:\\JAVA\\Image_Proc\\CVTest1.jpg",mat_f);
//finding contours
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat hierarchy = new Mat();
Imgproc.findContours(mat_f, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
double maxArea=0;
int maxAreaIdx=0;
//finding largest contour
for (int idx = 0; idx != contours.size(); ++idx)
{
Mat contour = contours.get(idx);
double contourarea = Imgproc.contourArea(contour);
if (contourarea > maxArea)
{
maxArea = contourarea;
maxAreaIdx = idx;
}
}
//Rect rect = Imgproc.boundingRect(contours.get(maxAreaIdx));
//Imgproc.rectangle(mat, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,0,255),7);
// mat = mat.submat(rect.y, rect.y + rect.height, rect.x, rect.x + rect.width);
//Polygon approximation
MatOfPoint2f approxCurve = new MatOfPoint2f();
MatOfPoint2f oriCurve = new MatOfPoint2f(contours.get(maxAreaIdx).toArray());
Imgproc.approxPolyDP(oriCurve, approxCurve, 6.0, true);
//drawing red markers at vertices
Point [] array = approxCurve.toArray();
for(int i=0; i < array.length;i++) {
Imgproc.circle(mat, array[i], 2, new Scalar(0, 255, 0), 5);
}
Imgcodecs.imwrite("D:\\JAVA\\Image_Proc\\CVTest.jpg",mat);
Seeking help in getting the appropriate corner vertices... Thanks in advance..