autojs查找轮廓相似的图片

牙叔教程 简单易懂

效果展示

查找右上角的叉叉按钮
在这里插入图片描述

缘起

很多人都在想怎么查找右上角这个叉叉, 然后有人问我, 我就研究一下

环境

手机: Mi 11 Pro

Android版本: 11

Autojs版本: 9.0.10

思路

  • 先裁剪一张右上角的叉叉按钮截图
  • 提取大图小图的轮廓
  • 对比轮廓特征
  • 显示匹配最佳的轮廓

轮廓特征有哪些

  • 矩形度, 矩形度体现物体对其外接矩形的充满程度, 也就是轮廓面积和外接矩形的面积比例
  • 宽高比, 轮廓最小外接矩形的宽和高的比值
  • matchShapes比较两个轮廓的相似度

本文使用了以上3种, 来对比两个轮廓是否相似,

轮廓特征还有别的, 请百度OpenCV轮廓特征, 或者, Halcon区域特征

你将学到以下知识点

  • 轮廓外接矩形
  • 轮廓最小外接矩形
  • 提取图片轮廓
  • 绘制图片轮廓
  • 绘制文字到指定位置
  • 计算轮廓质心
  • 矩形度
  • 计算轮廓面积
  • 高斯, 二值化
  • opencv资源释放

轮廓分析

小图
3.png

大图
在这里插入图片描述

上面这个图片是依据matchShapes比较两个轮廓的相似度,
相似度的阈值设置为了9, 小于9的都会画出来,
图片中的数字就是该轮廓和叉叉按钮的相似度,

右上角的叉叉按钮截图是在1080X1920的分辨率上截图的,
大图是1152X2376,

大图中的叉叉按钮相似度是7.168, 不是最小的(数值越小越相似)
反而那个字是最低的,6.700,

所以我要加上其他特征,
矩形度宽高比,
加上以后, 其他轮廓都不符合特征,

就只剩下右上角的叉叉按钮了

轮廓查找适用场景

透明的按钮, 并且图形简单

提高轮廓查找准确性和速度

指定找图区域, 裁剪多余图片区域, 再用轮廓找图

代码讲解

1. 导入类
runtime.images.initOpenCvIfNeeded();
importClass(org.opencv.core.MatOfByte);
importClass(org.opencv.core.Scalar);
importClass(org.opencv.core.Point);
importClass(org.opencv.core.CvType);
importClass(java.util.List);
importClass(java.util.ArrayList);
importClass(java.util.LinkedList);
importClass(org.opencv.imgproc.Imgproc);
importClass(org.opencv.imgcodecs.Imgcodecs);
importClass(org.opencv.core.Core);
importClass(org.opencv.core.Mat);
importClass(org.opencv.core.MatOfDMatch);
importClass(org.opencv.core.MatOfKeyPoint);
importClass(org.opencv.core.MatOfRect);
importClass(org.opencv.core.Size);
importClass(org.opencv.features2d.DescriptorMatcher);
importClass(org.opencv.features2d.Features2d);
importClass(org.opencv.core.MatOfPoint2f);
2. 读取图片
var bigImgPath = "/storage/emulated/0/脚本/autojs查找轮廓相似的图片/大图_关闭广告.jpg";
var smallImgPath = "/storage/emulated/0/脚本/autojs查找轮廓相似的图片/小图_关闭广告.png";
var bigImg = $images.read(bigImgPath);
var smallImg = $images.read(smallImgPath);
let bigImgMat = bigImg.getMat(); // 大图
let smallImgMat = smallImg.getMat(); // 大图
3. 提取轮廓
contour_info(bigImgMat, bigImgContours);
contour_info(smallImgMat, smallImgContours);
4. 计算矩形度和宽高比
// 矩形度
let smallImgRectangularity = getRectangularity(smallImgContour);
// 宽高比
let smallImgAspectRatio = getAspectRatio(smallImgContour);
5. 设定矩形度上下限, 宽高比同理
let rectangularityUnit = 0.1;
let rectangularityLowerLimit =
  smallImgRectangularity - rectangularityUnit < 0 ? 0 : smallImgRectangularity - rectangularityUnit;
let rectangularityUpperLimit =
  smallImgRectangularity + rectangularityUnit > 1 ? 1 : smallImgRectangularity + rectangularityUnit;
6. 遍历大图的轮廓时, 比较轮廓特征
if (dist < distLimit) {
  // 矩形度
  let itemRectangularity = getRectangularity(item);
  if (1 || (itemRectangularity > rectangularityLowerLimit && itemRectangularity < rectangularityUpperLimit)) {
      // 宽高比
      let itemAspectRatio = getAspectRatio(item);
    if (1 || (itemAspectRatio > aspectRatioLowerLimit && itemAspectRatio < aspectRatioUpperLimit)) {
      相似的轮廓信息列表.push({
        dist: dist,
        area: area,
        itemRectangularity: itemRectangularity,
        itemAspectRatio: itemAspectRatio,
        contour: item,
        center: {
          x: centerX,
          y: centerY,
        },
        wh: {
          w: rotateRect.width,
          h: rotateRect.height,
        },
      });
    }
  }
}
7. 绘制轮廓和相似度
// cv::Scalar(v1, v2, v3, v4), 前面的三个参数是依次设置BGR的,和RGB相反,第四个参数设置图片的透明度
Imgproc.drawContours(bigImgMat, 排序后的轮廓list, -1, Scalar(0, 0, 255, 255), thickness, lineType);
Imgproc.putText(bigImgMat, content, ptTextBottomLeftPosition, fontFace, fontScale, Scalar(0, 0, 255, 255), thickness);
8. 查看mat对应的图片
let tempFilePath = files.join(files.getSdcardPath(), "脚本", "autojs查找轮廓相似的图片.png");
Imgcodecs.imwrite(tempFilePath, bigImgMat);
app.viewFile(tempFilePath);
bigImgMat.release();

名人名言

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

声明

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

bilibili

牙叔教程

微信公众号 牙叔教程

在这里插入图片描述

QQ群

747748653
在这里插入图片描述

完整源码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牙叔教程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值