使用 Sikuli 匹配文件中的图像

Matching images from file with Sikuli

我在寻找一个库以在较大图像(均从文件加载)中查找给定图像的匹配项时,刚刚发现了 Sikuli。 默认情况下,Sikuli 仅支持从文件加载搜索图像,但依赖于专有 class 屏幕截取屏幕截图以用作搜索基础...我希望能够使用图像改为文件。

寻找解决方案导致我this question, but the answer is a bit vague when you consider that I have no prior experience with Sikuli and the available documentation对我的需求没有特别帮助。

有没有人有关于如何自定义实现 Screen、ScreenRegion、ImageScreen 和 ImageScreenLocation 的示例?即使 link 获得关于这些 class 的更详细的文档也会有很大帮助。

我只想获得另一个图像文件中图像匹配的坐标,所以如果有另一个库可以帮助完成这项任务,我会非常乐意了解它!

你可以自己实现,像这样:

class MyImage{
    private BufferedImage img;
    private int imgWidth;
    private int imgHeight;

    public MyImage(String imagePath){       
        try{
            img = ImageIO.read(getClass().getResource(imagePath));
        }catch(IOException ioe){System.out.println("Unable to open file");}
        init();
    }

    public MyImage(BufferedImage img){
        this.img = img;
        init();
    }

    private void init(){
        imgWidth = img.getWidth;
        imgHeight = img.getHeight();
    }

    public boolean equals(BufferedImage img){
        //Your algorithm for image comparison (See below desc for your choices)
    }

    public boolean contains(BufferedImage subImage){
        int subWidth = subImage.getWidth();
        int subHeight = subImage.getHeight();
        if(subWidth > imgWidth || subHeight > imgHeight)
            throw new IllegalArgumentException("SubImage is larger than main image");

        for(int x=0; x<(imgHeight-subHeight); x++)
            for(int y=0; y<(imgWidth-subWidth); y++){
                BufferedImage cmpImage = img.getSumbimage(x, y, subWidth, subHeight);
                if(subImage.equals(cmpImage))
                    return true;
            }
        return false;
    }
}

contains 方法将从主图像抓取子图像并与给定的子图像进行比较。如果不相同,它将移动到下一个像素,直到它遍历整个图像。可能还有其他比逐像素移动更有效的方法,但这应该可行。

比较 2 张图片的相似度

您至少有 2 个选项:

  1. 使用一对嵌套循环逐像素扫描,比较每个像素的RGB值。 (就像比较两个 int 二维数组的相似性一样)

  2. 应该可以为 2 个图像生成一个哈希值,然后只比较哈希值。

最后我放弃了 Sikuli 并使用了纯 OpenCV in my Android project: Imgproc.matchTemplate() 方法成功了,给了我一个包含 "scores" 的所有像素矩阵这很可能是我的子图像的起点。

啊...Sikuli 对此也有答案...您只是看得不够仔细。 :) 答案:查找器 Class

Pattern searchImage = new Pattern("abc.png").similar((float)0.9);
String ScreenImage = "xyz.png"; //In this case, the image you want to search
Finder objFinder = null;
Match objMatch = null;
objFinder = new Finder(ScreenImage);
objFinder.find(searchImage); //searchImage is the image you want to search within ScreenImage
int counter = 0;
while(objFinder.hasNext())
{
    objMatch = objFinder.next(); //objMatch gives you the matching region.
    counter++;
}
if(counter!=0)
System.out.println("Match Found!");

使用 Sikuli,您可以检查一幅图像是否存在于另一幅图像中。 在这个示例代码中,图片是从文件中加载的。 此代码告诉我们第二张图片是否是第一张图片的一部分。

public static void main(String[] argv){
    String img1Path = "/test/img1.png";
    String img2Path = "/test/img2.png";
    if ( findPictureRegion(img1Path, img2Path) == null )
        System.out.println("Picture 2 was not found in picture 1");
    else
        System.out.println("Picture 2 is in picture 1");
}

public static ScreenRegion findPictureRegion(String refPictureName, String targetPictureName2){
    Target target = new ImageTarget(new File(targetPictureName2));
    target.setMinScore(0.5); // Precision of recognization from 0 to 1.
    BufferedImage refPicture = loadPicture(refPictureName);
    ScreenRegion screenRegion = new StaticImageScreenRegion(refPicture);
    return screenRegion.find(target);
}

public static BufferedImage loadPicture(String pictureFullPath){
    try {
        return ImageIO.read(new File(pictureFullPath));
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

为了使用 Sikuli 包,我用 Maven 添加了这个依赖:

    <!-- SIKULI libraries -->
    <dependency>
        <groupId>org.sikuli</groupId>
        <artifactId>sikuli-api</artifactId>
        <version>1.1.0</version>
    </dependency>