繁体   English   中英

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

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

我有一个初始起始图像通过一些看起来像这样的处理

在此输入图像描述

我想要做的是填写轮廓,使它看起来像这样

在此输入图像描述

并找到两个(或多个)正方形的最佳拟合平行四边形,这样我就可以得到四个边界线中的每一个

在此输入图像描述

如果有人能指出我能提供帮助的正确功能,但我找不到任何有用的东西。 我尝试了许多扭曲的矩形校正器但无法使它们工作。

继承人目前的源代码

/*
 * 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();
    }
}
  • 要确定外部轮廓,可以使用模式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); 

    保存获得的垫子你会得到: 在此输入图像描述

  • 填写获得的轮廓:

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

    保存新生成的Mat,您将获得以下信息: 在此输入图像描述

  • 并为每个轮廓找到最合适的矩形:

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

最后,您得到以下结果图像: 在此输入图像描述

听起来像你想要floodfill()

暂无
暂无

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

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