autojs识别羊了个羊的方块区域

752 阅读3分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第4篇文章,点击查看活动详情

牙叔教程 简单易懂

观察图片, 图像分上下两层, 上层亮一点, 下层暗一点;

因此, 我们用亮度这个维度来入手;

再次观察图片, 方块的背景色是米黄色, 颜色还是比较纯的, 也可以从这个维度试试;

我们先试试背景色吧

提取背景色数据

颜色一致, 要测试的话, 用ps的魔棒工具测试, 效率最高;

可以看到, 魔棒工具选出了所有的米黄色背景图, 非常棒;

我们用autojs提供的方法来试试

images.inRange(img, lowerBound, upperBound)

[v4.1.0新增]

img {Image} 图片

lowerBound {string} | {number} 颜色下界

upperBound {string} | {number} 颜色下界

返回 {Image}

颜色的范围, 我们同样用ps的魔棒工具, 多取几个点, 然后找到rgb的最大值和最小值

红色: 最小242, 最大248

绿色: 最小253, 最大255

蓝色: 最小203, 最大207

然后转换成十六进制颜色, 这个用电脑自带的计算机算算

lowerBound F2FDCB

upperBound F8FFCF

lowerBound F2FDCB
upperBound F8FFCF

提取某种颜色区间的图片代码

let lowerBound = "#F2FDCB";
let upperBound = "#F8FFCF";
let rangeImg = images.inRange(img, lowerBound, upperBound);
let rangeImgPath = "/sdcard/脚本/sheep1InRange.png";
rangeImg.saveTo(rangeImgPath);
media.scanFile(rangeImgPath);
yashuImgTool.viewImgFile(rangeImgPath);

提取的图片效果

大概的背景都提取出来了, 我们修改一下颜色值, 把应该提取出来, 而没有提取的颜色区间修正一下;

有些地方没提取到, 可以用 ps 或者 mt管理器 继续提取图片中的颜色, 或者写个脚本采集背景区域的颜色;

最终选择的颜色阈值如下

let lowerBound = "#d0c0b0";
let upperBound = "#FfFFDb";

该阈值提取的图片如下

提取区域信息

图片已经整理成黑白色了, 我们提取一下这些方块的轮廓数据

Imgproc.findContours(binary, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE, Point());
Imgproc.drawContours(img.mat, contours, -1, Scalar(255, 0, 0, 255), 3, 8);
let rgbMat = img.mat.clone();
Imgproc.cvtColor(img.mat, rgbMat, Imgproc.COLOR_BGR2RGBA);
let tempFilePath = files.join(files.getSdcardPath(), "脚本", "mat.png");
Imgcodecs.imwrite(tempFilePath, rgbMat);

提取出来的轮廓区域, 都用红色方块画出来了

去除噪点

仔细看上面的图片, 有几个红色的点, 这个属于噪点;

要去除噪点, 可以设置一个阈值, 如果面积小于多少, 就去掉该轮廓

先打印看看轮廓的数据, 轮廓的面积用轮廓的最小外接矩形来算

for (let i = 0; i < contours.size(); ++i) {
    let item = contours.get(i);
    let rotateRect = Imgproc.boundingRect(item);
    let contourData = {
        width: rotateRect.width,
        height: rotateRect.height,
        area: rotateRect.area(),
    };
    contourDataArr.push(contourData);
}

轮廓的数据

[ { width: 55, height: 55, area: 3025 },
    { width: 55, height: 55, area: 3025 },
    { width: 1, height: 1, area: 1 },
    { width: 55, height: 56, area: 3080 },
    { width: 56, height: 55, area: 3080 },
    { width: 56, height: 55, area: 3080 },
    { width: 55, height: 56, area: 3080 },
    { width: 1, height: 1, area: 1 },
    { width: 55, height: 56, area: 3080 },
    { width: 1, height: 1, area: 1 },
    { width: 1, height: 1, area: 1 },
    { width: 56, height: 55, area: 3080 } ]

可以看到, 轮廓面积基本都在3000以上, 我们的阈值就设置3000;

过滤不符合规则的轮廓

let filteredContourDataArr = contourDataArr.filter((contourData) => {
    return contourData.area > 3000;
});

绘制轮廓

filteredContourDataArr.map((contourData) => {
    Imgproc.drawContours(img.mat, contours, contourData.index, new Scalar(0, 0, 255), 3, 8);
});

去掉噪点后的轮廓

活干完了, 不要忘记回收资源;

图片用recycle, mat用release

img.recycle();
rangeImg.recycle();
hierarchy.release();
rgbMat.release();

总结

既然通过颜色区间, 已经实现了目的, 那么就不用其他方法试了,;

识别还是比较简单的, 只识别了上层比较亮的部分,

下层暗的地方, 没有识别, 如果要识别的话, 也没有好办法, 除非机器学习;

网上有很多通关教程, 修改http之类的,

这个教程主要是介绍opencv的图片处理, 目的不在于过关;

非要试试过关的话, 用脚本模拟点击, 我估计过不了, 除非运气好;

因为脚本截图, 只能分析到上层较亮的部分, 下层分析不到, 属于数据不全;

数据不全, 就过不了

环境

设备: 小米11pro
Android版本: 12
Autojs版本: 9.2.13

名人名言

思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问 --- 牙叔教程

声明

部分内容来自网络 本教程仅用于学习, 禁止用于其他用途

微信公众号 牙叔教程