问题
I want my program to input an image (attachment) input and output a string like :
- Question 1: box 2 checked
- Question 2: box 1 checked
- Question 3: box 3 checked
- Question 4: box 2 checked
Etc ... (as many question as I have per image)
I can simply locate empty boxes with this program:
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class test {
public static void main(String[] args) {
// Load the library of openCv
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// Consider the image for processing
Mat image = Imgcodecs.imread("C:/attachement.jpg", Imgproc.COLOR_BGR2GRAY);
Mat imageHSV = new Mat(image.size(), CvType.CV_8UC4);
Mat imageBlurr = new Mat(image.size(),CvType.CV_8UC4);
Mat imageA = new Mat(image.size(), CvType.CV_32F);
Imgproc.cvtColor(image, imageHSV, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur(imageHSV, imageBlurr, new Size(5,5), 0);
Imgproc.adaptiveThreshold(imageBlurr, imageA, 255,Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY,7, 5);
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(imageA, contours, new Mat(), Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE);
for(int i=0; i< contours.size();i++)
{
if (Imgproc.contourArea(contours.get(i)) > 50 )
{
Rect rect = Imgproc.boundingRect(contours.get(i));
if ((rect.height > 35 && rect.height < 60) && (rect.width > 35 && rect.width < 60))
{
Imgproc.rectangle(image, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,0,255));
}
}
}
Imgcodecs.imwrite("C:/Users/Benreghai/Downloads/tof/output.png",image);
}
}
Here is the output of my program: (image attached) output
Thank you for your help !
回答1:
Following the comments, I'm adding the piece of code required.
Vector<Mat> rectangles = new Vector<Mat>();
for(int i=0; i< contours.size();i++)
{
if (Imgproc.contourArea(contours.get(i)) > 50 )
{
Rect rect = Imgproc.boundingRect(contours.get(i));
if ((rect.height > 35 && rect.height < 60) && (rect.width > 35 && rect.width < 60))
{
//Instead of drawing the rectangle, extract it using the Rect data type
Rect rec = new Rect(rect.x, rect.y, rect.width, rect.height);
rectangles.add(new Mat(image, rec));
// Imgproc.rectangle(image, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,0,255));
}
}
}
// Once you have all the rectangles, loop over them to find intersecting lines
// Initialize a vector of points to save the start and end of each line segment found
Vector<Point> start = new Vector<Point>();
Vector<Point> end = new Vector<Point>();
for (Mat rectangle : rectangles){
// Perform edge detection for using Canny, apply threshold suitably
int canny_lower = 100, canny_upper = 200;
Mat canny_img = new Mat(rectangle.size, CvType.8UC1);
Imgproc.Canny(rectangle, canny_img, canny_lower, canny_upper);
// Probably a Morphological Operation here, if required
Mat hough_lines = new Mat();
// Adjust the parameters from (here)[http://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html]
Imgproc.HoughLinesP(canny_img, hough_lines, 1, Math.PI / 720, 80, img.width() * 0.5, 50);
// hough_lines contains all the line segments detected by HoughLinesP
// Find coordinates of the line segment found using the previous step
for(int j = 0; j < hough_lines.cols(); j++){
double[] vec = hough_lines.get(0, j);
double x1 = vec[0], y1 = vec[1], x2 = vec[2], y2 = vec[3];
start.add(new Point(x1, y1));
end.add(new Point(x2, y2));
}
// Now that you have all lines the rectangle, find angle between them to
check if they are intersecting
for (int i = 0; i < start.size(); i++){
// Find the slope between segment i and i+1
// Multiple approaches here
char intersect_flag = get_line_intersection();
if (intersect_flag == 1)
System.out.print("\n Intersecting");
else
System.out.print("\n Not intersecting");
}
}
// Returns 1 if the lines intersect, otherwise 0. In addition, if the lines intersect the intersection point may be stored in the floats i_x and i_y.
// Pass x and y coordinates of each line segment for p0 to p4.i_x and i_y will have the coordinate of intersection, not required here.
char get_line_intersection(float p0_x, float p0_y, float p1_x, float p1_y,
float p2_x, float p2_y, float p3_x, float p3_y, float i_x, float i_y)
{
float s1_x, s1_y, s2_x, s2_y;
s1_x = p1_x - p0_x; s1_y = p1_y - p0_y;
s2_x = p3_x - p2_x; s2_y = p3_y - p2_y;
float s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
// Collision detected
if (i_x != NULL)
*i_x = p0_x + (t * s1_x);
if (i_y != NULL)
*i_y = p0_y + (t * s1_y);
return 1;
}
return 0; // No collision
}
Hope it helps! Follow How do you detect where two line segments intersect? for the intersection of two lines.
来源:https://stackoverflow.com/questions/41349736/find-a-contour-checked-in-java-with-opencv