声明
本文仅供学习
使用情景
识别象棋位置
效果展示
原理
- openev霍夫找圆
- canvas画圆
- 悬浮窗显示图片
知识点
- 隐藏虚拟按钮
- 全屏显示图片
- HoughCircles的各个参数的意思
- 图片的回收
代码讲解
- ui 显示象棋图片
ui.layout( <vertical w="{{device.width}}px" h="{{device.height}}px"> <img src="file://./中国象棋.jpg"></img> </vertical> );
- 请求截图
if (!requestScreenCapture()) { toast("请求截图失败"); exit(); }
- 截图并保存
let screen = images.read(imgFilepath); images.save(screen, imgFilepath);
- 霍夫找圆
let data = 霍夫找圆(screen);
- canvas画圆
let newImgFilepath = showData(data, imgFilepath);
- 悬浮窗全屏显示图片
悬浮窗全屏显示图片(newImgFilepath);
完整源码
- main.js
"ui"; importClass(android.view.WindowManager); importClass(android.view.View); let showData = require("./showData"); hideBottomUI(); ui.layout( <vertical w="{{device.width}}px" h="{{device.height}}px"> <img src="file://./中国象棋.jpg"></img> </vertical> ); threads.start(function () { //请求截图 if (!requestScreenCapture()) { toast("请求截图失败"); exit(); } let imgFilepath = files.path("./中国象棋.jpg"); log(imgFilepath); log(files.exists(imgFilepath)); let screen = images.read(imgFilepath); images.save(screen, imgFilepath); let data = 霍夫找圆(screen); let newImgFilepath = showData(data, imgFilepath); 悬浮窗全屏显示图片(newImgFilepath); }); setInterval(function () {}, 1000); // ==================自定义函数=================================== function 霍夫找圆(screen) { // 对图像进行中值滤波,返回处理后的图像。 let grayImgInfo = images.grayscale(images.medianBlur(screen, 3)); // void HoughCircles( InputArray image, OutputArray circles, // int method, double dp, double minDist, // double param1=100, double param2=100, // int minRadius=0, int maxRadius=0 ); //dp,用来检测圆心的累加器图像的分辨率与输入图像之比的倒数,例如如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便只有输入图像一半的分辨率 //minDist 检测到的圆的圆心之间的最小距离,即让我们的算法能明显区分的两个不同圆之间的最小距离。如果这个参数设置过大,某些圆就不能被检测出来。 // param1:此参数是对应Canny边缘检测的最大阈值,最小阈值是此参数的一半 也就是说像素的值大于param1是会检测为边缘 // param2:它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了 // minRadius:表示能够检测的最小圆的半径 这里我们设置为0是因为他也要检测圆心 而圆心可以看作是半径为0的圆 // maxRadius:表示能够检测的最大圆的半径,这里我设置为100,那么表示圆半径大于100的圆不会被检测出来(这个是依据你要检测的图片而考虑) let findBalls = images.findCircles(grayImgInfo, { dp: 1, minDst: 80, param1: 100, param2: 45, minRadius: 50, maxRadius: 80, }); // log("找到的圆:" + JSON.stringify(findBalls)); let haveBalls = findBalls && findBalls.length > 0; grayImgInfo.recycle(); screen.recycle(); if (haveBalls) { log("有圆" + findBalls.length + "个"); return findBalls; } else { return false; } } function 悬浮窗全屏显示图片(imgFilepath) { log("全屏显示图片"); let screen = images.read(imgFilepath); var w = floaty.rawWindow( <frame gravity="center" bg="#44ffcc00"> <img id="img"></img> </frame> ); ui.run(function () { w.img.attr("src", "file://" + imgFilepath); }); w.setSize(-1, -1); w.setTouchable(false); setTimeout(function () { screen.recycle(); }, 1000); } function hideBottomUI() { // 隐藏虚拟键 let uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; uiFlags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; activity.getWindow().getDecorView().setSystemUiVisibility(uiFlags); //解决虚拟按键弹出,无法再次隐藏的问题 activity .getWindow() .getDecorView() .setOnSystemUiVisibilityChangeListener(function (i) { hideBottomUI(); }); }
- showData.js
function showData(dataList, imgPath) { ocrType = "牙叔圆形识别测试"; log("显示数据 imgPath = " + imgPath); var img = images.read(imgPath); var canvas = new Canvas(img); let circlePaint = new Paint(); circlePaint.setStrokeWidth(3); circlePaint.setColor(colors.parseColor("#00ff00")); circlePaint.setStyle(Paint.Style.STROKE); //空心矩形框 let textPaint = new Paint(); textPaint.setTextAlign(Paint.Align.CENTER); textPaint.setTextSize(30); textPaint.setStyle(Paint.Style.FILL); textPaint.setColor(colors.parseColor("#f000ff")); var len = dataList.length; for (var i = 0; i < len; i++) { let data = dataList[i]; // { x: 464.5, y: 566.5, radius: 15.399999618530273 }, canvas.drawCircle(data.x, data.y, data.radius, circlePaint); canvas.drawText(i + "", data.x, data.y, textPaint); } var image = canvas.toImage(); let newFilename = files.getNameWithoutExtension(imgPath) + "_" + ocrType + ".png"; let newFilepath = "/sdcard/脚本/" + ocrType + "/" + newFilename; files.createWithDirs(newFilepath); images.save(image, newFilepath); log("识别后的图片保存路径: " + newFilepath); img.recycle(); image.recycle(); return newFilepath; } events.on("exit", function () { log("结束运行 模块脚本"); }); module.exports = showData;
3.素材