【问题标题】:Detecting similar objects in a picture检测图片中的相似对象
【发布时间】:2017-10-09 05:58:19
【问题描述】:

我正在尝试检测图片中的相似对象。代码的目的是检测黄金并点击它。

我尝试逐像素扫描,但效率不高,结果也不令人满意。 我要补充一点,游戏在 Windows 模式下运行,并且像机器人这样的类运行良好。此外,黄金可能每次都在不同的地方。

【问题讨论】:

  • 根据大小,您可以每步跳过 5 个像素。如果你想写一个机器人,java 可能不是最好的解决方案
  • 太宽泛了。您的问题归结为:如何检测图片中的对象。问题是:整本书都是关于这个主题的。
  • 这是 OpenCV 的一项任务,可以与这里提到的 java 一起使用:stackoverflow.com/questions/29182521/… 您可以创建一个二进制图像,检测斑点,消除太大的东西(即您的机器人)并成为留下金色斑点
  • 特别是你可以检查这个:opencv-java-tutorials.readthedocs.io/en/latest/…

标签: java


【解决方案1】:

作为一个非常简单的例子,我用你的图片写了这个:

public class OpenCVTest {

    public static void main(String[] args) {
        OpenCV.loadLibrary();

        Mat m = Highgui.imread("/home/artur/Pictures/test.png", Highgui.CV_LOAD_IMAGE_GRAYSCALE);
        LoadImage( m);
        Mat res = Mat.zeros(m.size(), m.type());
        Imgproc.adaptiveThreshold(m, res, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 15, 20);
        LoadImage(res);
        Mat cannyRes = Mat.zeros(m.size(), m.type());
        Imgproc.Canny(res, cannyRes, 55, 5.2);
        LoadImage(cannyRes);

        Imgproc.dilate(cannyRes, cannyRes, new Mat(), new Point(-1, -1), 2);
        Imgproc.erode(cannyRes, cannyRes, new Mat(), new Point(-1, -1), 2);

        LoadImage(cannyRes);

        List<MatOfPoint> contours = new ArrayList<>();
        Imgproc.findContours(cannyRes, contours, new Mat(), Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE);

        System.err.println(contours.size());

        contours = contours.stream().filter(s -> s.size().area() > 50 && s.size().area() <= 100).collect(Collectors.toList());

        for(MatOfPoint p : contours) {
            Size size = p.size();
            System.err.println("-- -- --");
            System.err.println(size.area());
        }

        Imgproc.drawContours(cannyRes, contours, 20, new Scalar(233, 223,212));
        LoadImage(cannyRes);
    }

    public static void LoadImage( Mat m) {
        Path path = Paths.get("/tmp/", UUID.randomUUID().toString() + ".png");
        Highgui.imwrite(path.toString(), m);
        JFrame frame = new JFrame("My GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setResizable(true);
        frame.setLocationRelativeTo(null);

        // Inserts the image icon
        ImageIcon image = new ImageIcon(path.toString());
        frame.setSize(image.getIconWidth() + 10, image.getIconHeight() + 35);
        // Draw the Image data into the BufferedImage
        JLabel label1 = new JLabel(" ", image, JLabel.CENTER);
        frame.getContentPane().add(label1);

        frame.validate();
        frame.setVisible(true);
    }

}
  1. 我看了图片

  2. 我使用自适应阈值创建二值图像

  3. 我使用 canny 检测图像中的边缘

  4. 我使用扩张/腐蚀来消除背景噪音

  5. 我使用轮廓查找器在图像中查找对象

  6. 我忽略任何具有任意大小的轮廓

生成的轮廓大致是您的黄色斑点。这不是很准确,因为我没有花时间玩不同的参数,但你可以微调它。

希望对你有帮助,

玩得开心。您可以在此处查看如何设置 OpenCV:Java OpenCV from Maven

【讨论】:

  • 谢谢,但是您认为每秒创建一个图像并分析它是否有效?因为每次单击对象(金)时,您都必须再次扫描屏幕/生成图像,因为玩家将在不同的位置。
  • 把物品放到画布上的不是你吗?您不必检测它们,因为您应该已经知道对象在哪里。此外,这不是每秒一次,而是每秒至少 30 次(这将为您提供相对流畅的画面),甚至可能每秒 6​​0 帧。但是,在 CV 中,一旦您有了对象,并且知道它们会随着图片移动,您就可以使用不同的技术来跟踪它们,而不是每次都重新发现它们。但同样,如果游戏在您的控制之下,您应该知道对象的放置位置
猜你喜欢
  • 2019-06-22
  • 2015-03-20
  • 2016-08-10
  • 2018-12-06
  • 2020-05-04
  • 2016-10-31
  • 2016-01-25
  • 2014-10-03
  • 2011-04-16
相关资源
最近更新 更多