2

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

在此处输入图像描述

我想做的是填充轮廓,所以看起来有点像这样

在此处输入图像描述

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

在此处输入图像描述

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

继承人当前的源代码

/*
 * 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();
    }
}
4

2 回答 2

8
  • 要确定外部轮廓,您可以使用带有 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);
    

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

  • 填充获得的轮廓:

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

最后你得到这个结果图像: 在此处输入图像描述

于 2017-03-10T20:38:37.060 回答
-1

听起来你想要floodfill()

于 2013-09-03T09:51:39.050 回答