牙叔教程 简单易懂
效果展示
查找右上角的叉叉按钮
缘起
很多人都在想怎么查找右上角这个叉叉, 然后有人问我, 我就研究一下
环境
手机: Mi 11 Pro
Android版本: 11
Autojs版本: 9.0.10
思路
- 先裁剪一张右上角的叉叉按钮截图
- 提取大图小图的轮廓
- 对比轮廓特征
- 显示匹配最佳的轮廓
轮廓特征有哪些
- 矩形度, 矩形度体现物体对其外接矩形的充满程度, 也就是轮廓面积和外接矩形的面积比例
- 宽高比, 轮廓最小外接矩形的宽和高的比值
- matchShapes比较两个轮廓的相似度
本文使用了以上3种, 来对比两个轮廓是否相似,
轮廓特征还有别的, 请百度OpenCV轮廓特征, 或者, Halcon区域特征
你将学到以下知识点
- 轮廓外接矩形
- 轮廓最小外接矩形
- 提取图片轮廓
- 绘制图片轮廓
- 绘制文字到指定位置
- 计算轮廓质心
- 矩形度
- 计算轮廓面积
- 高斯, 二值化
- opencv资源释放
轮廓分析
小图
大图
上面这个图片是依据matchShapes比较两个轮廓的相似度,
相似度的阈值设置为了9, 小于9的都会画出来,
图片中的数字就是该轮廓和叉叉按钮的相似度,
右上角的叉叉按钮截图是在1080*1920的分辨率上截图的,
大图是1152*2376,
大图中的叉叉按钮相似度是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文档, 最后才是群里问问
--- 牙叔教程
声明
部分内容来自网络
本教程仅用于学习, 禁止用于其他用途