AutoJs6 icon indicating copy to clipboard operation
AutoJs6 copied to clipboard

请问如何实现全分辨率识图?

Open realcsnake2023 opened this issue 10 months ago • 11 comments

@SuperMonster003 和各位代码大佬,有个问题请教一下,从现在的版本看,现在的识图功能函数findImage()是模块匹配,通过截小图,并在全屏截图中识别的方法,这样基本上只可以本手机自身的截图(即分辨率是固定的),如果换了一个不同分辨率的手机,就会找不到图片。 所以请教一下,有什么方法可以实现分辨率识图?以方便我的脚本和截图在其他手机上正常工作。感谢!!

另外,有没有适配autojs6.6的手机截图和编辑工具推荐,以方便截图和简单的编辑?

[images.findImage(img, template[, options])](https://docs.autojs6.com/#/image?id=imagesfindimageimg-template-options)
img {Image} 大图片
template {Image} 小图片(模板)
options {Object} 找图选项
找图. 在大图片img中查找小图片template的位置(模块匹配), 找到时返回位置坐标(Point), 找不到时返回null.

realcsnake2023 avatar Apr 19 '25 14:04 realcsnake2023

这个问题很简单啊。 在大图里寻找小图,你只要确保大图是全屏截图就行了。 因为全屏截图的图片宽和高尺寸,就等于分辨率。 什么分辨率截的图,图片就是多大。

你在这张图片里面找到的小图坐标,就是对应这个分辨率的。

wengzhenquan avatar Apr 20 '25 00:04 wengzhenquan

这个问题很简单啊。 在大图里寻找小图,你只要确保大图是全屏截图就行了。 因为全屏截图的图片宽和高尺寸,就等于分辨率。 什么分辨率截的图,图片就是多大。

你在这张图片里面找到的小图坐标,就是对应这个分辨率的。

感谢解答。但我所表述的不是这个意思,比如,我的手机A的分辨率是896X1848,手机B的分辨率是1344X2772;我用手机A截屏并剪裁一个小图片(比如:完成按钮.jpg)用于以后运行代码时识别某个按钮;之后,我在手机A上运行代码

requestScreenCapture();
var img = captureScreen();
var templ = images.read("/sdcard/完成按钮.jpg");
var p = findImage(img, templ);
if(p){
    toast("找到啦:" + p);
}else{
    toast("没找到");
}

这时会正常找到截图并返回 找到啦:{516.0, 202.0}

但当我把完成按钮.jpg copy到手机B后,在手机B上运行同样的代码,则会因为找不到图而返回 没找到。 其原因是两台手机的分辨率不同。我的理解,findImage是基于模块找图(即同分辨率)的原理,所以不能找到,那么我就是想一个能让手机B中也可以正常运行代码并能识别图片的方法。

(主要是不想在手机B中重新截一次图,一是不方便,二是B手机是家里另一个人在用,他并不懂这些,一切还得我去折腾,所以不想这么麻烦)

realcsnake2023 avatar Apr 20 '25 13:04 realcsnake2023

为什么要用A手机的截图,拿去给B手机用呢? 代码在哪个手机上运行,就在哪个手机上截图就好了。 方案一:你的程序本来就要放在他手机上运行,就让程序自己去截图就好了。 开启“投影媒体”权限,就全自动了。

方案二:而且,你既然说有按钮,那就更简单了。 找到该按钮

    let button = className("android.widget.Button").text("你的按钮").findOne();

当然你的按钮可能是别的参数,但只要能通过程序找到,那么:

let bounds=button.bounds();

你可以获得它的bounds,这是一个数组,是这个组件的边缘坐标,对应布局分析里你所看到的坐标,它可能长这个样子:[203, 1033, 325, 1088] 然后截图就能使用这个坐标了。

let x=bounds[0];
let y=bounds[1];
let w=bounds[2]-x;
let h=bounds[3]-y;

方案三:可以利用这两个函数(但不保证行得通): setScaleBaseX(1080); setScaleBaseY(2400); 然后x使用cX(),y使用cY()。 setScaleBaseX、setScaleBaseY这两个函数设置你手机的分辨率。 当程序在其它分辨率手机上运行的时候,cX()、cY()设置的坐标会根据前面两个函数设置的分辨率进行自动伸缩。 在大部分的情况下是能伸缩的合适的坐标的。

每次我都是用这个用来初始化坐标,然后用方案二来替补。 如果找到了可以参照的组件,就更新坐标。


说实话,我没搞懂你的需求。 如果你只是为了找到一个按钮,通过findOne();无疑是最简单的方式,根本不需要截图,不需要从大图找小图。

wengzhenquan avatar Apr 20 '25 14:04 wengzhenquan

方案四: findImage函数调整相识度。

var p = findImage(pictures2, wx, {
        threshold: 0.8 // 相似度0.8
    });

我最低的时候,能把相似度调到0.1

wengzhenquan avatar Apr 20 '25 14:04 wengzhenquan

我曾经有一段代码是这么写的:

setScaleBaseX(1080);
setScaleBaseY(2400);
// 截全屏
var pictures2 = images.clip(captureScreen(), 0, 0, dwidth, dheight);
    images.save(pictures2, "./tmp/pictures2.png", "png", 100);
    
// 截小图,根据setScaleBaseX、setScaleBaseY设置的分辨率会自动伸缩
var hk_auto = images.clip(pictures2,
            cX(165), cY(1276), (cX(349) - cX(165)), (cY(1460) - cX(1276)));
        images.save(hk_auto, "./tmp/hk_auto.png", "png", 100);
// 然后就可以开始找图了
var p = findImage(pictures2, hk_auto, {
        threshold: 0.8 // 相似度0.8
    });

后来我改成了这样,的写法获取坐标:

function getClipParam() {
    let x = cX(101);
    let y = cY(638);
    var param = {
        x: x,
        y: y,
        w: (cX(979) - x),
        h: (cY(1622) - y)
    };

    let ycdj = textStartsWith("请在下图依次点击").findOne(2500);
    if (ycdj) {
        //找到合适的父组件
        while (ycdj.right() < dwidth * 2 / 3) {
            ycdj = ycdj.parent();
        }
        param.x = ycdj.left();
        param.y = ycdj.top();
        param.w = ycdj.right() - param.x;

    }

    let tida = className("android.widget.Button")
        .text("提交答案").findOne(2500);

    if (tida) {
        param.h = tida.top() - param.y;
    }

    return param;
}

先用cX,cY内置一个截图需要的数组,如果找到了参照的组件,再根据组件的边缘坐标,按需来构建更新坐标参数。 拿到这些参数,再截图,肯定能获取到自己需要的截图模样。

wengzhenquan avatar Apr 20 '25 14:04 wengzhenquan

也就是说,不论是大图还是小图,都在目标手机里自动截取。 你也不用去传输截图.jpg, 只要对方更新脚本,其它啥也不用管,只管运行就行。 自动适应分辨率,全程全自动。

wengzhenquan avatar Apr 20 '25 15:04 wengzhenquan

大图如下: Image

截取的小图如下:

Image

wengzhenquan avatar Apr 20 '25 15:04 wengzhenquan

@wengzhenquan 感谢!你的这个高级,我学习学习!

realcsnake2023 avatar Apr 20 '25 15:04 realcsnake2023

@wengzhenquan 感谢!你的这个高级,我学习学习!

加油,就是3套方案一起用。 方案一:让大图、小图两张图都在对方手机自动截取,让程序自己动。 方案三:用setScaleBaseX、setScaleBaseY、cX、cY自动伸缩坐标来截小图。这些坐标就设置你自己的手机分辨率的坐标就行。 基本到这里就可以了。 结合方案二,寻找参照组件的边缘坐标,来更新截图大小的参数,能确保万无一失。

wengzhenquan avatar Apr 20 '25 15:04 wengzhenquan

如果需要的目标组件难以直接找到。 还可以通过 控件节点 (UiObject)来辅助。 parent 获取父控件。 child(i) 获取子控件。 sibling(i)获取兄弟控件。 等等。

有很多丰富的函数可供你来使用,以助你找到可参照的控件,详情可查看文档。

wengzhenquan avatar Apr 20 '25 16:04 wengzhenquan

发现还是要多阅读文档 我发现超时的可以全用 wait自己不需要再写一个啦😂

itxve avatar Apr 21 '25 09:04 itxve