autojs象棋识别棋子

牙叔教程 简单易懂

解决问题第一原则

把问题写下来

原图

饱和度

明度

灰度

各个维度的图片没什么区别,

干脆用原图

霍夫找圆

可以看到, 圆的位置基本上正确, 但是又有些许偏差,

让圆更准确的思路

上图已经找到了圆, 在这个圆的基础上, 通过轮廓或者文字的颜色去纠正圆的偏差,

理论上可以纠正圆的位置, 非本文重点, 仅供思路参考

棋子截图

上面是所有的棋子截图, 当选中棋子后, 四个角会有红色标志

可能会对找图产生干扰, 所以我们把棋子的截图半径再搞小点

发现还有个东西没搞, 那就是图片到底是哪个棋子

这个应该用圆的位置来推算

只要圆形的纵坐标相差不大, 就认为他们在同一排

所有圆分6组, 底层+ 中炮 + 五卒

  • 红方3组
  • 黑方3组

遍历圆形, 以第一个圆为起点类, 其他圆形与之按照纵坐标比较,

相差不大就归为一类, 否则归为其他类,

最后再按照纵坐标排序, 就把6组圆分开了

分组完成, 下面给分组按纵坐标排序

pieceGroups.sort(function (pieceGroup1, pieceGroup2) {
  let piece1 = pieceGroup1[0];
  let piece2 = pieceGroup2[0];
  if (piece1.circle.y < piece2.circle.y) {
    return -1;
  } else if (piece1.circle.y > piece2.circle.y) {
    return 1;
  } else {
    return 0;
  }
});
复制代码

接下每个棋子组, 要按照横坐标排序

for (var i = 0; i < pieceGroups.length; i++) {
  let pieceGroup = pieceGroups[i];
  pieceGroup.sort(function (piece1, piece2) {
    if (piece1.circle.x < piece2.circle.x) {
      return -1;
    } else if (piece1.circle.x > piece2.circle.x) {
      return 1;
    } else {
      return 0;
    }
  });
}
复制代码

重新裁剪棋子图片, 并且记录棋子的名字;

颜色暂时按照图片, 黑色在上方, 红色在下方,

后期优化的时候, 颜色可以在图片上取多个点, 民主投票,

那种颜色票数多, 就是那种颜色

非本教程重点, 思路仅供参考

for (var i = 0; i < pieceGroups.length; i++) {
  let pieceGroup = pieceGroups[i];
  for (var j = 0; j < pieceGroup.length; j++) {
    let piece = pieceGroup[j];
    let circle = piece.circle;
    let checkPieceArea = calculateCheckPieceArea(img, circle);
    let chessPieceImg = clipChessPieceImg(img, checkPieceArea);
    let color;
    if (count < 15) {
      color = "黑";
    } else {
      color = "红";
    }
    let filePath = dir + "/" + piece.num + "-" + color + "-" + pieceNames[count] + ".png";
    log(filePath);
    files.createWithDirs(filePath);
    images.save(chessPieceImg, filePath);
    chessPieceImg.recycle();
    count++;
  }
}
复制代码

万事俱备, 验证一下,

验证步骤

  1. 走几步象棋
  2. 截图
  3. 查看识别结果

又发现一个问题, 有重复的棋子,

重新来过, 把重复的棋子删掉不要

for (var i = 0; i < pieceGroups.length; i++) {
  let pieceGroup = pieceGroups[i];
  for (var j = 0; j < pieceGroup.length; j++) {
    let piece = pieceGroup[j];
    let circle = piece.circle;
    let checkPieceArea = calculateCheckPieceArea(img, circle);
    let chessPieceImg = clipChessPieceImg(img, checkPieceArea);
    let color;
    if (count <= 15) {
      color = "黑";
    } else {
      color = "红";
    }
    let archivedPiece = archivedPieces[color + pieceNames[count]];
    if (archivedPiece) {
      // 重复的棋子, 只留下一个
      count++;
      continue;
    } else {
      archivedPieces[color + pieceNames[count]] = 1;
    }
    let filePath = dir + "/" + piece.num + "-" + color + "-" + pieceNames[count] + ".png";
    files.createWithDirs(filePath);
    images.save(chessPieceImg, filePath);
    chessPieceImg.recycle();
    count++;
  }
}
复制代码

此时, 棋子的图片应该有14张

再次识别象棋, 识别出来后, 写上绿色的文字

for (var i = 0; i < pieces.length; i++) {
  let piece = pieces[i];
  var points = images.matchTemplate(img, piece.img, {
    threshold: 0.9,
  }).points;
  if (points) {
    points.forEach((point) => {
      canvas.drawText(piece.name, point.x, point.y, textPaint);
    });
  }
}
复制代码

全部识别正确

测试环境

手机: Mi 11 Pro
Android版本: 12
Autojs版本: 9.1.13

名人名言

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

声明

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

微信公众号 牙叔教程

猜你喜欢

转载自juejin.im/post/7082775328896057352