简体   繁体   English

使用Sikuli匹配文件中的图像

[英]Matching images from file with Sikuli

I just found about Sikuli when I was looking for a library to find matches of a given image within a larger image (both loaded from files). 当我在寻找一个库以在较大图像(均从文件加载)中查找给定图像的匹配项时,才发现有关Sikuli的信息。 By default, Sikuli only supports loading the searched image from file, but relies on a proprietary class Screen to take screenshots to use as base for the search... And I'd like to have the ability to use a image file instead. 默认情况下,Sikuli仅支持从文件加载搜索到的图像,但是依赖于专有类Screen来获取屏幕截图以用作搜索的基础...而且我希望能够使用图像文件。

Looking for a solution has led me to this question , but the answer is a bit vague when you consider that I have no prior experience with Sikuli and the available documentation is not particularly helpful for my needs. 寻找解决方案已经使我想到了这个问题 ,但是当您认为我没有Sikuli的经验并且可用的文档对我的需求不是特别有用时,答案就有些模糊。

Does anyone have any examples on how to make a customized implementation of Screen, ScreenRegion, ImageScreen and ImageScreenLocation? 有没有人有关于如何自定义实现Screen,ScreenRegion,ImageScreen和ImageScreenLocation的示例? Even a link to a more detailed documentation on these classes would be a big help. 即使是有关这些类的更详细文档的链接也将有很大帮助。

All I want is to obtain the coordinates of an image match within another image file, so if there's another library that could help with this task I'd more than happy to learn about it! 我想要的只是在另一个图像文件中获取图像匹配的坐标,因此,如果有另一个可以帮助完成此任务的库,我将非常乐意学习!

You can implement it by yourself with something like this: 您可以自己通过以下方式实现它:

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

The contains method will grab a subimage from the main image and compare with the given subimage. contains方法将从主图像中获取一个子图像,并将其与给定的子图像进行比较。 If it is not the same, it will move on to the next pixel until it went through the entire image. 如果不相同,它将继续移动到下一个像素,直到遍历整个图像为止。 There might be other more efficient ways than moving pixel by pixel, but this should work. 除了逐像素移动之外,可能还有其他更有效的方法,但这应该可行。

To compare 2 images for similarity 比较2张图片的相似度

You have at least 2 options: 您至少有2个选择:

  1. Scan pixel by pixel using a pair of nested loop to compare the RGB value of each pixel. 使用一对嵌套循环逐像素扫描以比较每个像素的RGB值。 (Just like how you compare two int 2D array for similarity) (就像您如何比较两个int 2D数组的相似性一样)

  2. It should be possible to generate a hash for the 2 images and just compare the hash value. 应该可以为这两个图像生成一个哈希值,然后只比较哈希值即可。

Aah... Sikuli has an answer for this too... You just didnt look close enough. 啊,西库里(Sikuli)也有答案。 :) Answer : The FINDER Class :)答:FINDER类

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,并在我的Android项目中使用了纯OpenCV :Imgproc.matchTemplate()方法成功了,给了我一个所有像素为“ scores”的矩阵,这是我的起点。子图像。

With Sikuli, you can check for the presence of an image inside another one. 使用Sikuli,您可以检查另一张图像中是否有图像。 In this example code, the pictures are loaded from files. 在此示例代码中,图片是从文件加载的。 This code tell us if the second picture is a part of the first picture. 此代码告诉我们第二张图片是否是第一张图片的一部分。

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

To use Sikuli package, I added this dependency with Maven : 要使用Sikuli包,我在Maven中添加了此依赖项:

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

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

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