猿问

如何通过图像查找元素

我们知道selenium支持多个定位器策略来查找网页上的元素。

但我的要求不同,我有一些网站,其中 selenium 支持的任何定位器都不足以唯一地找到一个元素。

由于 selenium 提供了创建自己的自定义定位器策略来查找元素的便利,我正在尝试创建图像定位器,它可以像appium一样使用子图像的base64 来查找元素。String

图像定位器的要点:

  1. 使用 URL 启动浏览器

  2. 截取页面截图

  3. 从屏幕截图中检测子图像的x , y位置

  4. 使用页面中的x , y位置查找元素

为了完成这项任务,我正在创建自定义Image定位器,如下所示:

public class ByImage extends By {


    String imageBase64String


    /**

     * @param imageBase64String

     */

    public ByImage(String imageBase64String) {

        this.imageBase64String = imageBase64String

    }


    @Override

    public List<WebElement> findElement(SearchContext context) {

        List<WebElement> els = findElements(context)

        if (els) {

            return els.get(0)

        }

        throw new NoSuchElementException("Element not found")

    }


    @Override

    public List<WebElement> findElements(SearchContext context) {

       //Get current screenshot

        byte[] screenshotByte = ((TakesScreenshot)context).getScreenshotAs(OutputType.BYTES))

        byte[] subImgToFindByte = DatatypeConverter.parseBase64Binary(imageBase64String)

        //Convert buffred image to get height and width of subimage

        BufferedImage bufferedSubImgToFind = ImageIO.read(new ByteArrayInputStream(subImgToFindByte ));


        //Here I need a mechanism to get coordinates of sub image from screenshot

        //Suppose I able to find x, y

        double x

        double y


        //Now find element using coordinates

        //Now calculate center point

        int centerX = int(x + (bufferedSubImgToFind.getWidth() / 2))

        int centerY = int(y + (bufferedSubImgToFind.getHeight() / 2))


        JavascriptExecutor js = ((JavascriptExecutor)context)


        return js.executeScript("return document.elementsFromPoint(arguments[0], arguments[1]);", centerX, centerY)

      }   

  }

现在测试用例如下:


WebDriver driver = new ChromeDriver()

driver.get("<URL>")

WebElement elementByImage = driver.findElement(new ByImage("<Base64 String of the subimage>"))

除了一个更好的库来检测subimage来自 an 的精确坐标image以使用坐标查找元素之外,我能够实现所有功能。


谁能建议我更好的方法来完成这项任务?


浮云间
浏览 201回答 2
2回答

慕娘9325324

您可以选择不同的选项,例如:您可以使用Java Bindings for OpenCV来查找主屏幕截图中的子图像,查看模板匹配文章以获得全面的解释和代码片段。Sikuli 项目提供了一些用于图像识别/交互的简单 APISeeTest Automation为图像模板提供图像识别和对象存储库模式实现

慕虎7371278

我将使用Java Bindings for OpenCV。下载适当的 OpenCV并将其解压缩到classpath并尝试获取坐标为:import org.opencv.core.Core;import org.opencv.core.Core.MinMaxLocResult;import org.opencv.core.CvType;import org.opencv.core.Mat;import org.opencv.core.MatOfByte;import org.opencv.core.Point;import org.opencv.imgcodecs.Imgcodecs;import org.opencv.imgproc.Imgproc;byte[] screenshotByte = ((TakesScreenshot)context).getScreenshotAs(OutputType.BYTES))byte[] subImgToFindByte = DatatypeConverter.parseBase64Binary(imageBase64String)System.loadLibrary(Core.NATIVE_LIBRARY_NAME);Mat source = Imgcodecs.imdecode(new MatOfByte(screenshotByte), Imgcodecs.IMREAD_UNCHANGED);Mat template = Imgcodecs.imdecode(new MatOfByte(subImgToFindByte), Imgcodecs.IMREAD_UNCHANGED);int result_cols = source.cols() - template.cols() + 1;int result_rows = source.rows() - template.rows() + 1;Mat outputImage = new Mat(result_rows, result_cols, CvType.CV_32FC1);// Template matching methodImgproc.matchTemplate(source, template, outputImage, Imgproc.TM_SQDIFF_NORMED);MinMaxLocResult mmr = Core.minMaxLoc(outputImage);// Now get the pointPoint point = mmr.minLoc;double x = point.x;double y = point.y;//Now get the find the element using x, y after calculating center point.int centerX = int(x + (bufferedSubImgToFind.getWidth() / 2));int centerY = int(y + (bufferedSubImgToFind.getHeight() / 2));WebElement el = js.executeScript("return document.elementFromPoint(arguments[0], arguments[1]);", centerX, centerY);希望对大家有帮助。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答