Appium 使用 appnium 做自动化,我是基于 java 的,一个控件,使用名字的方式找不见,该如何解决

testerhaha · 2018年07月19日 · 最后由 testerhaha 回复于 2018年07月23日 · 2125 次阅读

我是使用的 java,那个控件的话,里面只有 text 和 class 有值,这两个都找不到,该如何处理呢?
各位大牛,请问有啥解决办法?

最佳回复

如果控件是一个图标的话,可以试一下基于图像识别的方法。
简单讲就是先把需要识别的图片截图,然后在需要寻找该图像的时候,调用封装好的方法

贴一个以前写的代码,楼主参考一下,是基于 opencv 的。
OpencvRecognition.match 方法接收 2 个参数,分别是需要寻找的图标文件路径,完整的屏幕截图文件路径,返回识别到的中心坐标。
并且会创建一个新的图片,标识出识别到的具体位置,用来 debug。

import org.opencv.calib3d.Calib3d;
import org.opencv.core.*;
import org.opencv.features2d.*;
import org.opencv.highgui.Highgui;

import java.io.File;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;

/**
 * @author weijianrao
 */
public class OpencvRecognition {

    public static double[] match(String template, String source) {
        double[] ret = new double[2];
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        System.out.println("开始匹配");
        System.out.println("加载图片");
        Mat templateImage = Highgui.imread(template, Highgui.CV_LOAD_IMAGE_COLOR);
        Mat sourceImage = Highgui.imread(source, Highgui.CV_LOAD_IMAGE_COLOR);

        MatOfKeyPoint templateKeyPoints = new MatOfKeyPoint();
        FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);
        System.out.println("检测关键点");
        detector.detect(templateImage, templateKeyPoints);

        DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.SURF);

        MatOfKeyPoint templateDescriptors = new MatOfKeyPoint();
        System.out.println("计算描述符");
        extractor.compute(templateImage, templateKeyPoints, templateDescriptors);

        // Create the matrix for output image.
        Mat outputImage = new Mat(templateImage.rows(), templateImage.cols(), Highgui.CV_LOAD_IMAGE_COLOR);
        Scalar newKeypointColor = new Scalar(255, 0, 0);

        System.out.println("Drawing key points on object image...");
        Features2d.drawKeypoints(templateImage, templateKeyPoints, outputImage, newKeypointColor, 0);

        // Match object image with the scene image
        MatOfKeyPoint sourceKeyPoints = new MatOfKeyPoint();
        MatOfKeyPoint sourceDescriptors = new MatOfKeyPoint();
        System.out.println("Detecting key points in background image...");
        detector.detect(sourceImage, sourceKeyPoints);
        System.out.println("Computing descriptors in background image...");
        extractor.compute(sourceImage, sourceKeyPoints, sourceDescriptors);

        Mat matchoutput = new Mat(sourceImage.rows() * 2, sourceImage.cols() * 2, Highgui.CV_LOAD_IMAGE_COLOR);
        Scalar matchestColor = new Scalar(0, 255, 0);

        List<MatOfDMatch> matches = new LinkedList<MatOfDMatch>();
        DescriptorMatcher descriptorMatcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
        System.out.println("Matching object and scene images...");
        descriptorMatcher.knnMatch(templateDescriptors, sourceDescriptors, matches, 2);

        System.out.println("Calculating good match list...");
        LinkedList<DMatch> goodMatchesList = new LinkedList<DMatch>();

        float nndrRatio = 0.7f;

        for (int i = 0; i < matches.size(); i++) {
            MatOfDMatch matofDMatch = matches.get(i);
            DMatch[] dmatcharray = matofDMatch.toArray();
            DMatch m1 = dmatcharray[0];
            DMatch m2 = dmatcharray[1];

            if (m1.distance <= m2.distance * nndrRatio) {
                goodMatchesList.addLast(m1);
            }
        }

        if (goodMatchesList.size() >= 7) {
            System.out.println("找到了!!!");

            List<KeyPoint> templateKeypointlist = templateKeyPoints.toList();
            List<KeyPoint> sourceKeypointlist = sourceKeyPoints.toList();

            LinkedList<Point> templatePoints = new LinkedList<Point>();
            LinkedList<Point> sourcePoints = new LinkedList<Point>();

            for (int i = 0; i < goodMatchesList.size(); i++) {
                templatePoints.addLast(templateKeypointlist.get(goodMatchesList.get(i).queryIdx).pt);
                sourcePoints.addLast(sourceKeypointlist.get(goodMatchesList.get(i).trainIdx).pt);
            }

            MatOfPoint2f templateMatOfPoint2f = new MatOfPoint2f();
            templateMatOfPoint2f.fromList(templatePoints);
            MatOfPoint2f scnMatOfPoint2f = new MatOfPoint2f();
            scnMatOfPoint2f.fromList(sourcePoints);

            Mat homography = Calib3d.findHomography(templateMatOfPoint2f, scnMatOfPoint2f, Calib3d.RANSAC, 3);

            Mat templateCorners = new Mat(4, 1, CvType.CV_32FC2);
            Mat sourceCorners = new Mat(4, 1, CvType.CV_32FC2);

            templateCorners.put(0, 0, new double[]{0, 0});
            templateCorners.put(1, 0, new double[]{templateImage.cols(), 0});
            templateCorners.put(2, 0, new double[]{templateImage.cols(), templateImage.rows()});
            templateCorners.put(3, 0, new double[]{0, templateImage.rows()});

            System.out.println("Transforming object corners to scene corners...");
            Core.perspectiveTransform(templateCorners, sourceCorners, homography);

            Mat img = Highgui.imread(source, Highgui.CV_LOAD_IMAGE_COLOR);

            Core.line(img, new Point(sourceCorners.get(0, 0)), new Point(sourceCorners.get(1, 0)), new Scalar(0, 255, 0), 4);
            Core.line(img, new Point(sourceCorners.get(1, 0)), new Point(sourceCorners.get(2, 0)), new Scalar(0, 255, 0), 4);
            Core.line(img, new Point(sourceCorners.get(2, 0)), new Point(sourceCorners.get(3, 0)), new Scalar(0, 255, 0), 4);
            Core.line(img, new Point(sourceCorners.get(3, 0)), new Point(sourceCorners.get(0, 0)), new Scalar(0, 255, 0), 4);

            ret[0] = (sourceCorners.get(0, 0)[0] + sourceCorners.get(1, 0)[0] + sourceCorners.get(2, 0)[0] + sourceCorners.get(3, 0)[0]) / 4;
            ret[1] = (sourceCorners.get(0, 0)[1] + sourceCorners.get(1, 0)[1] + sourceCorners.get(2, 0)[1] + sourceCorners.get(3, 0)[1]) / 4;
            Core.circle(img, new Point(ret), 10, new Scalar(0, 0, 255), 3);

            System.out.println("Drawing matches image...");
            MatOfDMatch goodMatches = new MatOfDMatch();
            goodMatches.fromList(goodMatchesList);

            Features2d.drawMatches(templateImage, templateKeyPoints, sourceImage, sourceKeyPoints, goodMatches, matchoutput, matchestColor, newKeypointColor, new MatOfByte(), 2);

            //Highgui.imwrite("C:\\Users\\weijianrao.LEXINFINTECH\\Desktop\\outputImage.jpg", outputImage);
            //Highgui.imwrite("C:\\Users\\weijianrao.LEXINFINTECH\\Desktop\\matchoutput.jpg", matchoutput);
            String dirName = new File(source).getParent();
            String baseName = new File(source).getName().replace(".png", "") + "_debug" + ".png";
            String debugPic = Paths.get(dirName).resolve(baseName).toString();
            Highgui.imwrite(debugPic, img);
        } else {
            System.out.println("Object Not Found");
        }
        return ret;
    }
}
共收到 5 条回复 时间 点赞

把代码,和 log 贴出来 大兄弟

如果控件是一个图标的话,可以试一下基于图像识别的方法。
简单讲就是先把需要识别的图片截图,然后在需要寻找该图像的时候,调用封装好的方法

贴一个以前写的代码,楼主参考一下,是基于 opencv 的。
OpencvRecognition.match 方法接收 2 个参数,分别是需要寻找的图标文件路径,完整的屏幕截图文件路径,返回识别到的中心坐标。
并且会创建一个新的图片,标识出识别到的具体位置,用来 debug。

import org.opencv.calib3d.Calib3d;
import org.opencv.core.*;
import org.opencv.features2d.*;
import org.opencv.highgui.Highgui;

import java.io.File;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;

/**
 * @author weijianrao
 */
public class OpencvRecognition {

    public static double[] match(String template, String source) {
        double[] ret = new double[2];
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        System.out.println("开始匹配");
        System.out.println("加载图片");
        Mat templateImage = Highgui.imread(template, Highgui.CV_LOAD_IMAGE_COLOR);
        Mat sourceImage = Highgui.imread(source, Highgui.CV_LOAD_IMAGE_COLOR);

        MatOfKeyPoint templateKeyPoints = new MatOfKeyPoint();
        FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);
        System.out.println("检测关键点");
        detector.detect(templateImage, templateKeyPoints);

        DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.SURF);

        MatOfKeyPoint templateDescriptors = new MatOfKeyPoint();
        System.out.println("计算描述符");
        extractor.compute(templateImage, templateKeyPoints, templateDescriptors);

        // Create the matrix for output image.
        Mat outputImage = new Mat(templateImage.rows(), templateImage.cols(), Highgui.CV_LOAD_IMAGE_COLOR);
        Scalar newKeypointColor = new Scalar(255, 0, 0);

        System.out.println("Drawing key points on object image...");
        Features2d.drawKeypoints(templateImage, templateKeyPoints, outputImage, newKeypointColor, 0);

        // Match object image with the scene image
        MatOfKeyPoint sourceKeyPoints = new MatOfKeyPoint();
        MatOfKeyPoint sourceDescriptors = new MatOfKeyPoint();
        System.out.println("Detecting key points in background image...");
        detector.detect(sourceImage, sourceKeyPoints);
        System.out.println("Computing descriptors in background image...");
        extractor.compute(sourceImage, sourceKeyPoints, sourceDescriptors);

        Mat matchoutput = new Mat(sourceImage.rows() * 2, sourceImage.cols() * 2, Highgui.CV_LOAD_IMAGE_COLOR);
        Scalar matchestColor = new Scalar(0, 255, 0);

        List<MatOfDMatch> matches = new LinkedList<MatOfDMatch>();
        DescriptorMatcher descriptorMatcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
        System.out.println("Matching object and scene images...");
        descriptorMatcher.knnMatch(templateDescriptors, sourceDescriptors, matches, 2);

        System.out.println("Calculating good match list...");
        LinkedList<DMatch> goodMatchesList = new LinkedList<DMatch>();

        float nndrRatio = 0.7f;

        for (int i = 0; i < matches.size(); i++) {
            MatOfDMatch matofDMatch = matches.get(i);
            DMatch[] dmatcharray = matofDMatch.toArray();
            DMatch m1 = dmatcharray[0];
            DMatch m2 = dmatcharray[1];

            if (m1.distance <= m2.distance * nndrRatio) {
                goodMatchesList.addLast(m1);
            }
        }

        if (goodMatchesList.size() >= 7) {
            System.out.println("找到了!!!");

            List<KeyPoint> templateKeypointlist = templateKeyPoints.toList();
            List<KeyPoint> sourceKeypointlist = sourceKeyPoints.toList();

            LinkedList<Point> templatePoints = new LinkedList<Point>();
            LinkedList<Point> sourcePoints = new LinkedList<Point>();

            for (int i = 0; i < goodMatchesList.size(); i++) {
                templatePoints.addLast(templateKeypointlist.get(goodMatchesList.get(i).queryIdx).pt);
                sourcePoints.addLast(sourceKeypointlist.get(goodMatchesList.get(i).trainIdx).pt);
            }

            MatOfPoint2f templateMatOfPoint2f = new MatOfPoint2f();
            templateMatOfPoint2f.fromList(templatePoints);
            MatOfPoint2f scnMatOfPoint2f = new MatOfPoint2f();
            scnMatOfPoint2f.fromList(sourcePoints);

            Mat homography = Calib3d.findHomography(templateMatOfPoint2f, scnMatOfPoint2f, Calib3d.RANSAC, 3);

            Mat templateCorners = new Mat(4, 1, CvType.CV_32FC2);
            Mat sourceCorners = new Mat(4, 1, CvType.CV_32FC2);

            templateCorners.put(0, 0, new double[]{0, 0});
            templateCorners.put(1, 0, new double[]{templateImage.cols(), 0});
            templateCorners.put(2, 0, new double[]{templateImage.cols(), templateImage.rows()});
            templateCorners.put(3, 0, new double[]{0, templateImage.rows()});

            System.out.println("Transforming object corners to scene corners...");
            Core.perspectiveTransform(templateCorners, sourceCorners, homography);

            Mat img = Highgui.imread(source, Highgui.CV_LOAD_IMAGE_COLOR);

            Core.line(img, new Point(sourceCorners.get(0, 0)), new Point(sourceCorners.get(1, 0)), new Scalar(0, 255, 0), 4);
            Core.line(img, new Point(sourceCorners.get(1, 0)), new Point(sourceCorners.get(2, 0)), new Scalar(0, 255, 0), 4);
            Core.line(img, new Point(sourceCorners.get(2, 0)), new Point(sourceCorners.get(3, 0)), new Scalar(0, 255, 0), 4);
            Core.line(img, new Point(sourceCorners.get(3, 0)), new Point(sourceCorners.get(0, 0)), new Scalar(0, 255, 0), 4);

            ret[0] = (sourceCorners.get(0, 0)[0] + sourceCorners.get(1, 0)[0] + sourceCorners.get(2, 0)[0] + sourceCorners.get(3, 0)[0]) / 4;
            ret[1] = (sourceCorners.get(0, 0)[1] + sourceCorners.get(1, 0)[1] + sourceCorners.get(2, 0)[1] + sourceCorners.get(3, 0)[1]) / 4;
            Core.circle(img, new Point(ret), 10, new Scalar(0, 0, 255), 3);

            System.out.println("Drawing matches image...");
            MatOfDMatch goodMatches = new MatOfDMatch();
            goodMatches.fromList(goodMatchesList);

            Features2d.drawMatches(templateImage, templateKeyPoints, sourceImage, sourceKeyPoints, goodMatches, matchoutput, matchestColor, newKeypointColor, new MatOfByte(), 2);

            //Highgui.imwrite("C:\\Users\\weijianrao.LEXINFINTECH\\Desktop\\outputImage.jpg", outputImage);
            //Highgui.imwrite("C:\\Users\\weijianrao.LEXINFINTECH\\Desktop\\matchoutput.jpg", matchoutput);
            String dirName = new File(source).getParent();
            String baseName = new File(source).getName().replace(".png", "") + "_debug" + ".png";
            String debugPic = Paths.get(dirName).resolve(baseName).toString();
            Highgui.imwrite(debugPic, img);
        } else {
            System.out.println("Object Not Found");
        }
        return ret;
    }
}
raoweijian 回复

整体性能还比较好,识别一次基本上在几十 ms。

raoweijian 回复

哦哦,那我试下,之前只想着在最后结果验证的时候使用 opencv,没有想到在元素定位的时候使用

raoweijian 回复

问下我在 java 里面使用 maven 去编译工程,这个 highgui 的这个类,找不见 pom 依赖,这个是需要引入 jar 包么

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册