2017-08-25 38 views
1

我刚刚找到关于Sikuli的信息,当时我正在寻找一个库来查找较大图像(均从文件加载)中给定图像的匹配。 默认情况下,Sikuli只支持从文件中加载搜索到的图片,但依赖专有类Screen来截取屏幕截图以用作搜索的基础...并且我希望能够使用图片文件。与Sikuli匹配来自文件的图像

寻找解决方案已将我导向this question,但当您考虑到我对Sikuli没有预先的经验并且available documentation对我的需求不是特别有用时,答案有点模糊。

有没有人有任何关于如何制作Screen,ScreenRegion,ImageScreen和ImageScreenLocation的定制实现的例子?即使是关于这些课程的更详细文档的链接也是一个很大的帮助。

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

+1

你要检查是否有另一个图像中存在的图像?您可以自己编写代码,无需使用任何外部软件包。除非两幅图像的图像质量不同,否则会更困难。 – user3437460

+0

是的,我想在更大的图像中找到图像的坐标。最终目标是在不同尺寸/分辨率的匹配上具有灵活性。 –

+0

卡洛请看下面的答案。 – user3437460

回答

1

你可以自己用这样的实现:

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 2D数组的相似性)

  2. 应该有可能为2张图像生成一个散列,然后比较散列值。

0

最后我放弃了Sikuli并用纯OpenCV in my Android project:本Imgproc.matchTemplate()方法的伎俩,让我所有的像素矩阵以“分数”为作为起点的似然点我的subimage。

0

Aah ... Sikuli也有这个答案...你只是没有看起来足够接近。 :) 答: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!"); 
+0

Aji,你能告诉我这个解决方案是否支持不同比例的匹配? 我使用Imgproc.matchTemplate提到的OpenCV解决方案仅在ScreenImage中查找完全相同大小的子图像。我希望通过具有寻找一般模式的能力使其更强大,而不管ScreenImage大小/比例如何。 –

+0

嗨Marcel,Sikuli不允许这样做。 Sikuli实际上只在内部使用openCV的Match模板功能来识别图像。但是,我相信我已经阅读过openCV有一个解决方案,如果您的图像缩放,旋转等。不幸的是,我没有亲自尝试过这一点。抱歉。但是,对于Sikuli来说这是不可能的。 – Aji

0

随着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>