autojs多分辨率找透明图

22 篇文章 0 订阅

牙叔教程 简单易懂

声明

本教程是教查找透明图的, 找透明图逻辑都是类似的, 不针对任何app.

效果

目标: 找图片中的双人头
在这里插入图片描述

本次测试一共使用了三种分辨率的图片

  • 1600x720
  • 2310x1080
  • 2400x1080

每种分辨率各5张,

上图中左上角的头像, 可以看出是一个黑白图片, 是把一张2400x1080的大图, 灰度化, 二值化, 然后裁剪双人区域得到的, 所有分辨率图片找图, 都是用的同一张双人头小图.

有必要继续看下去吗

  • 多分辨率找图你有思路吗
  • 你会找透明图吗
  • 你在多种分辨率下, 找透明图, 会不会?
  • 你想不想看几十篇教程来学习sift
  • 你会把java版本的sift改成autojs的吗
  • 你想花掉两个星期的时间来研究一个东西吗

如果你对以上对你来说, 没有任何问题, 那就没必要看下去, 划走吧.

环境

手机: Mi 11 Pro
Android版本: 11
Autojs版本: 9.0.10

备注

autojs8自带的opencv版本是3, 不包含sift,
autojs9自带的opencv版本是4, 包含sift,

多分辨率找透明图思路

多分辨率找图用sift,
透明图先二值化, 然后再找图

二值化图片

在这里插入图片描述

我们需要选择一个合适的阈值来二值化, 因此需要可视化的调整阈值,
本教程挑选的阈值是246,
在这个阈值下, 二值化后的图片上, 只剩下双人头和右下角的星星,
可以最大限度的帮助我们排除图片中的噪音,

下面是阈值为246的时候, 对应的二值图
在这里插入图片描述

二值化代码

本代码非常优秀, 即使在ui界面16ms刷新的频率下, 也没有内存泄漏发生,
值得新手仔细研究

"ui";
engines.all().map((ScriptEngine) => {
  if (engines.myEngine().toString() !== ScriptEngine.toString()) {
    ScriptEngine.forceStop();
  }
});
importClass(org.opencv.imgproc.Imgproc);
importClass(org.opencv.core.Mat);
ui.layout(
  <vertical>
    <img id="原图"></img>
    <horizontal>
      <text>阈值: </text>
      <text id="threshold">0</text>
      <seekbar id="seekbar" margin="9" w="*"></seekbar>
    </horizontal>
    <img id="二值化"></img>
  </vertical>
);
let imgPath = "./截图1.png";
imgPath = files.path(imgPath);
let img = images.read(imgPath);
let bitmap = img.getBitmap();
log(bitmap);
ui.原图.setImageBitmap(bitmap);

ui.seekbar.setMax(255);

let thresholdBitmap;
ui.seekbar.setOnSeekBarChangeListener({
  onProgressChanged: function (seekBar, progress, fromUser) {
    if (fromUser) {
      let lastBitmap = thresholdBitmap;
      ui.threshold.setText(String(progress));
      let threshold = parseInt(progress);
      log("二值化之前 img = " + img);
      let thresholdImg = 二值化(img, threshold);
      thresholdBitmap = thresholdImg.getBitmap();
      ui.二值化.setImageBitmap(thresholdBitmap);
      ui.post(function () {
        thresholdImg.recycle();
      });
      if (lastBitmap) {
        log("lastBitmap = ");
        log(lastBitmap);
        lastBitmap.recycle();
      }
    }
  },
});

events.on("exit", function () {
  bitmap.recycle();
  img.recycle();
  thresholdBitmap.recycle();
});

/* ---------------------------自定义函数----------------------------------------------- */

function 二值化(img, threshold) {
  log("threshold = " + threshold);
  let trainImage = img.mat;
  let trainImage_gray = new Mat();
  Imgproc.cvtColor(trainImage, trainImage_gray, Imgproc.COLOR_BGR2GRAY);
  let binary = new Mat();
  // Imgproc.threshold(trainImage_gray, binary, threshold, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
  Imgproc.threshold(trainImage_gray, binary, threshold, 255, Imgproc.THRESH_BINARY);
  trainImage_gray.release();
  var newImg = com.stardust.autojs.core.image.ImageWrapper.ofMat(binary);
  return newImg;
}

裁剪图片

电脑上的话, 我用的是ps裁剪图片,
手机上的话, 可以使用有裁剪功能的app,
如果你找不到合适的app, 可以公众号回复 照片编辑器
该app有裁剪功能,
下面是我们从二值图中, 裁剪出的双人头
在这里插入图片描述

保存图片到sd卡

opencv中的图片格式都是Mat, 把Mat保存到sd卡, 代码如下

function viewMat(mat) {
  let mat2 = mat.clone();
  Imgproc.cvtColor(mat, mat2, Imgproc.COLOR_BGRA2RGBA);
  let tempFilePath = files.join(files.getSdcardPath(), "脚本", "mat.png");
  Imgcodecs.imwrite(tempFilePath, mat2);
  mat2.release();
  app.viewFile(tempFilePath);
}

中间有一行转换颜色的代码, 是因为mat默认使用bgr, 而不是rgb,
不转换颜色的话, 图片颜色看着就不正常.

读到这里你应该有这些东西了

  • 原图
  • 二值化的原图
  • 裁剪出来的双人头小图

接下来就该sift上场了

sift找图效果

在这里插入图片描述

图片中连接双人头的彩色线两端的点, 就是sift在两种图片中找到的相似度最高的特征点,
在右下角的星星上, 也有一个特征点, 因此有一条紫色的线连过去了,
图片中的蓝色矩形是用来包裹相似特征点的,

再看看别的图
在这里插入图片描述

这张图效果就很好, 没有受到右下角星星的影响, 再看看别的图片
在这里插入图片描述

在这里插入图片描述

从图片中可以看到, 右下角的星星影响了我们的找图, 因此我们找图的时候,
可以先裁剪掉右侧对我们找图无用的图片, 比如把图片右侧三分之一的都裁减掉,
这样就避免了右下角星星对找图的影响.
所有没用的地方都可以预先裁减掉, 然后再去找图
在这里插入图片描述

因此, 我的自定义方法就有一个区域参数,
只保留我们有用的部分, 图片中的其他部分, 全部裁掉

/**
 * @description:
 * @param {img} bigImg
 * @param {img} smallImg
 * @param {Array} rect [left, top, right, bottom]
 * @return {Array} [left, top, right, bottom]
 */
function findImageSift(bigImg, smallImg, rect) {...}

总结

以上就是查找透明图的基本步骤,
这种方法理论是可行的, 实际效果, 我们要测试后才知道,

该方法是否符合任何场景呢?
当然是不可能的, 我们会遇到不同的场景, 需要对每个场景采取合适的方法,
找图这种, 我不认为有通用的方法, 尤其是手机分辨率那么多种,
但本方案是目前此场景中最合适的方案,

学会这个, 你的找图功力又前进一大步,
你的找图功力, 即将大圆满呢, 给自己点个赞吧 !

名人名言

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

声明

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

bilibili

牙叔教程

微信公众号 牙叔教程

在这里插入图片描述

QQ群

747748653
在这里插入图片描述

完整源码 立即查看

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

牙叔教程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值