java - 使用 OpenCV 在 Java 中查找轮廓

标签 java opencv contour

我想让我的程序输入一张图片(附件)

input

并输出如下字符串:

  • 问题 1:选中框 2
  • 问题 2:选中框 1
  • 问题 3:选中框 3
  • 问题 4:选中框 2

等等......(每张图片我有多少问题)

我可以用这个程序简单地找到空盒子:

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);
    }
}

这是我的程序的输出:(附图片) output

感谢您的帮助!

最佳答案

根据评论,我添加了所需的代码。

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
}

希望对您有所帮助!关注How do you detect where two line segments intersect?对于两条线的交点。

关于java - 使用 OpenCV 在 Java 中查找轮廓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41349736/

相关文章:

c++ - 从 cvFindContour 中提取对象

java - 无法使用 android studio 3.3 在 Mac 上解析 com.android.tools.build :gradle:3. 2.1

java - 使用增量时间使运动平滑的简单方法

java - 想要通过 Java 中的 Web 应用程序发送 OTP,而不使用 gsm 调制解调器

java - 自从更改 SpringBoot 依赖性以来,在空字段上加入时出现 Freemarker 错误

android - 具有Android Studio的OpenCV

java - 重叠形状识别 (OpenCV)

.net - OpenCV - 缺少 dll

OpenCV的partition()底层算法

matlab - Matlab 中的等高线图 - 需要永远