简体   繁体   English

在Java OpenCV中填写并检测轮廓矩形

[英]Fill in and detect contour rectangles in Java OpenCV

I have an initial starting image through some processing that looks like this 我有一个初始起始图像通过一些看起来像这样的处理

在此输入图像描述

What I want to do it is to fill in the contours so it looks somewhat like this 我想要做的是填写轮廓,使它看起来像这样

在此输入图像描述

and find the best fit parallelograms of the two (or more) squares which would let me get each one of the four bounding lines like this 并找到两个(或多个)正方形的最佳拟合平行四边形,这样我就可以得到四个边界线中的每一个

在此输入图像描述

If anyone could point me to the right functions that would help, but I can't find anything helpful. 如果有人能指出我能提供帮助的正确功能,但我找不到任何有用的东西。 I've tried many distorted rectangle correctors but couldn't get them to work. 我尝试了许多扭曲的矩形校正器但无法使它们工作。

Heres current source code 继承人目前的源代码

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javacvtesting;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfInt;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.highgui.Highgui;
/**
 *
 * @author Arhowk
 */
public class JavaCVTesting {

    /**
     * @param args the command line arguments
     *//*
  */



    public static BufferedImage convert(Mat m){
        Mat image_tmp = m;

        MatOfByte matOfByte = new MatOfByte();

        Highgui.imencode(".png", image_tmp, matOfByte); 

        byte[] byteArray = matOfByte.toArray();
        BufferedImage bufImage = null;

        try {

            InputStream in = new ByteArrayInputStream(byteArray);
            bufImage = ImageIO.read(in);

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            return bufImage;
        }
    }
    public static Mat convert(BufferedImage i){
        BufferedImage image = i;
        byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        Mat mat = new Mat(image.getHeight(),image.getWidth(), CvType.CV_8UC3);
        mat.put(0, 0, data);
        return mat;
    }
    public static void show(BufferedImage i){
        JFrame frame = new JFrame();
        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(new JLabel(new ImageIcon(i)));
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        Mat src = Highgui.imread("D:\\0_image.png");
        Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2HSV);
        Mat dest = new Mat();
      // Mat dest = new Mat(src.width(), src.height(), src.type());
        Core.inRange(src, new Scalar(58,125,0), new Scalar(256,256,256), dest);

        Mat erode = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3));
        Mat dilate = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5));
        Imgproc.erode(dest, dest, erode);
        Imgproc.erode(dest, dest, erode);

        Imgproc.dilate(dest, dest, dilate);
        Imgproc.dilate(dest, dest, dilate);

        List<MatOfPoint> contours = new ArrayList<>();

        Imgproc.findContours(dest, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
        Imgproc.drawContours(dest, contours, -1, new Scalar(255,255,0));

        Panel p = new Panel();
        p.setImage(convert(dest));
        p.show();
    }
}
  • To determine the outer contours you may use findContours with mode RETR_EXTERNAL: 要确定外部轮廓,可以使用模式RETR_EXTERNAL的findContours:

     List<MatOfPoint> contours = new ArrayList<>(); Mat dest = Mat.zeros(mat.size(), CvType.CV_8UC3); Scalar white = new Scalar(255, 255, 255)); // Find contours Imgproc.findContours(image, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); // Draw contours in dest Mat Imgproc.drawContours(dest, contours, -1, white); 

    Saving the obtained Mat you will get: 保存获得的垫子你会得到: 在此输入图像描述

  • To fill in the obtained contours: 填写获得的轮廓:

     for (MatOfPoint contour: contours) Imgproc.fillPoly(dest, Arrays.asList(contour), white); 

    Saving the new resulting Mat you will get this: 保存新生成的Mat,您将获得以下信息: 在此输入图像描述

  • And to find the best fit rectangle for each contour: 并为每个轮廓找到最合适的矩形:

     Scalar green = new Scalar(81, 190, 0); for (MatOfPoint contour: contours) { RotatedRect rotatedRect = Imgproc.minAreaRect(new MatOfPoint2f(contour.toArray())); drawRotatedRect(dest, rotatedRect, green, 4); } public static void drawRotatedRect(Mat image, RotatedRect rotatedRect, Scalar color, int thickness) { Point[] vertices = new Point[4]; rotatedRect.points(vertices); MatOfPoint points = new MatOfPoint(vertices); Imgproc.drawContours(image, Arrays.asList(points), -1, color, thickness); } 

Finally you get this resulting image: 最后,您得到以下结果图像: 在此输入图像描述

听起来像你想要floodfill()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM