为了账号安全,请及时绑定邮箱和手机立即绑定

如何通过图像查找元素

如何通过图像查找元素

浮云间 2021-06-28 12:56:28
我们知道selenium支持多个定位器策略来查找网页上的元素。但我的要求不同,我有一些网站,其中 selenium 支持的任何定位器都不足以唯一地找到一个元素。由于 selenium 提供了创建自己的自定义定位器策略来查找元素的便利,我正在尝试创建图像定位器,它可以像appium一样使用子图像的base64 来查找元素。String图像定位器的要点:使用 URL 启动浏览器截取页面截图从屏幕截图中检测子图像的x , y位置使用页面中的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以使用坐标查找元素之外,我能够实现所有功能。谁能建议我更好的方法来完成这项任务?
查看完整描述

2 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

您可以选择不同的选项,例如:

  1. 您可以使用Java Bindings for OpenCV来查找主屏幕截图中的子图像,查看模板匹配文章以获得全面的解释和代码片段。

  2. Sikuli 项目提供了一些用于图像识别/交互的简单 API

  3. SeeTest Automation为图像模板提供图像识别和对象存储库模式实现


查看完整回答
反对 回复 2021-07-08
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

我将使用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 method

Imgproc.matchTemplate(source, template, outputImage, Imgproc.TM_SQDIFF_NORMED);


MinMaxLocResult mmr = Core.minMaxLoc(outputImage);

// Now get the point

Point 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);

希望对大家有帮助。


查看完整回答
反对 回复 2021-07-08
  • 2 回答
  • 0 关注
  • 200 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信