JS脚本

Auto.pro opencv实例:获取界面上线条的交点

2019-07-31  本文已影响0人  魔力sama

情景

这两天在玩重装战姬,因此分享一下遇到的问题和解法:敌方要攻打某个据点,并以虚线表示目标点,需要拖动我方部队到目标点防守。
场景如下图:


example.png

解决思路

  1. 截图(废话)
  2. 识别出我方位置
  3. 筛选出红色
  4. 获取线条
  5. 通过方程计算出直线的交点
  6. 将我方部分拖拽到交点

下面给出3-5的详细代码和说明

importClass(org.opencv.core.MatOfByte)
importClass(org.opencv.imgcodecs.Imgcodecs)
importClass(org.opencv.imgproc.Imgproc)
importClass(org.opencv.core.Core)
importClass(org.opencv.core.CvType)
importClass(org.opencv.core.Mat)
importClass(org.opencv.core.MatOfPoint)
importClass(org.opencv.core.MatOfPoint2f)
importClass(org.opencv.core.Point)
importClass(org.opencv.core.Size)
importClass(org.opencv.core.Scalar)
importClass(java.io.ByteArrayInputStream)
importClass(java.util.ArrayList)

function getCrossPoint (img) {
    var hsv = new Mat()
    var redImg = new Mat()
    // 将原图片转换成hsv格式
    Imgproc.cvtColor(img.mat, hsv, Imgproc.COLOR_BGR2HSV)
    // 筛选颜色,将结果保存到redImg,第一个Scalar是hsv颜色下限,第二个为hsv上限。这里筛选的是红色,这部分红色在hsv分量里位于紫色区间,因此取紫色分量范围。
    Core.inRange(hsv, new Scalar(120, 43, 46), new Scalar(150, 255, 255), redImg)

    var lines = new Mat()
    // 获取直线数组,由于这里是虚线,因此最后一个参数(间距)设长一点,为30
    Imgproc.HoughLinesP(redImg, lines, 1, Math.PI/180, 80, 80, 30)

    if (!lines) {
        return null
    }
    // 获取前两条直线(也可以遍历所有的直线,不过这里默认只有一个交点,所以取前两条就够用)
    var lineA = lines.get(0, 0)
    var lineB = lines.get(1, 0)
    log('lineA', lineA)
    log('lineB', lineB)
    if (!lineA || !lineB) {
        return null
    }
    return checkPoint(lineA, lineB)
}

// 通过方程计算交点
function checkPoint(LineA, LineB)
{
    if (!LineA || !LineB) {
        return null
    }

    //求出LineA斜率
    var ka = (LineA[3] - LineA[1]) / (LineA[2] - LineA[0])
    //求出LineB斜率
    var kb = (LineB[3] - LineB[1]) / (LineB[2] - LineB[0])
    
    // 可以对斜率进行筛选,比如斜率相等、差值小于5%则返回null

    // 如果斜率差值小于5%,则返回null
    if (Math.abs((ka - kb)/ka) < 0.05) {
        return null
    }

    var x = parseInt((ka*LineA[0] - LineA[1] - kb*LineB[0] + LineB[1]) / (ka - kb));
    var y = parseInt((ka*kb*(LineA[0] - LineB[0]) + ka*LineB[1] - kb*LineA[1]) / (ka - kb));

    // 对交点进行筛选,如果交点不在两条线段上,则返回null
       var x = parseInt((ka*LineA[0] - LineA[1] - kb*LineB[0] + LineB[1]) / (ka - kb));
    var y = parseInt((ka*kb*(LineA[0] - LineB[0]) + ka*LineB[1] - kb*LineA[1]) / (ka - kb));
    
    if (
        (x - LineA[0]) * (x - LineA[2]) <= 0 && (y - LineA[1]) * (y - LineA[3]) <= 0 &&
        (x - LineB[0]) * (x - LineB[2]) <= 0 && (y - LineB[1]) * (y - LineB[3]) <= 0
    ) {
        return [x, y]
    } else {
        return null
    }
}

export default {
    getCrossPoint
}

(有些包没有用到,偷懒直接用上次例子的包了)

值得注意的是,importClass加载的opencv包需要在调用了auto.pro的images.xxx函数之后才能生效。因此在执行getCrossPoint之前,应该先随便执行一个images的read以外的函数。

上一篇下一篇

猜你喜欢

热点阅读