美文网首页JS脚本
Auto.pro opencv实例:获取界面上线条的交点

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

作者: 魔力sama | 来源:发表于2019-07-31 12:35 被阅读0次

    情景

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


    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以外的函数。

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/acezrctx.html