java-opencv简单识别箭头

前言

对形状识别了解的不是太多,本篇算是个简单入门。因为最近比较忙闲暇时间不多了解的不算深入写的有不对的地方还请评论区留言。

声明下 :还有这里的识别没有用深度学习最近在学demo,也没用模板匹配类的(很久前写了一个象棋棋谱识别的例子用的模板一个一个匹配的:象棋棋谱之棋子识别(三))。

这里学习参考了网上的一些思路用java写了个demo,形状的话常见的有三角形、正方形、长方形、平行四边形、梯形因为定义公式也比较简单所以识别也相对容易;多边形类的就需要自己发现特点然后去处理了。

思路

  1. 首先轮廓提取。
  2. 因为轮廓是由一个一个点连线得到的所以需要获取轮廓的点的坐标和个数。
  3. 得到轮廓凸包的坐标点的索引。(凸包就是最外层的连线下图红色。所有的点是通过轮廓得到的。中间的排除掉了是凸包得到的就是最外层的点)
  1. 能拿到点我们也就能做很多东西了。常见的形状识别例如正方形:是四个点、四条边长相等、每个角度是90°、我们也可以不通过角度通过计算用面积是否跟正方形的面积相等进行判断。对于边长和角度我们可以对坐标点排序(也就是顺时针、逆时针)然后计算得到,角度应该有API的。

本篇的箭头识别demo

效果

这里再说下凸包看下下图就明白了绿线

处理的方式

先说下外面的7个点,这是个逆时针标识的

  1. 首先获取轮廓,参数意思可以在网上搜这里不在多写了。或者参考我之前写的一篇(java调用opencv轮廓检测
bash 复制代码
Imgproc.findContours(clone, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
  1. 首先这个箭头是由七个坐标点组成的,进行坐标点个数判断。
arduino 复制代码
//多边形包围轮廓
Imgproc.approxPolyDP(curve, approxCurve, 0.025 * Imgproc.arcLength(curve, true), true);
//这个参数就是返回的坐标点
approxCurve.toArray().length
  1. 然后凸包得到的坐标点会比正常的点数少2个。
vbscript 复制代码
//true=顺时针方向 false=逆时针方向 这里我观察了下开始是从上面中间的位置开始的
//hull.toArray().length 返回的是上面approxPolyDP得到的坐标位置
Imgproc.convexHull(CommonCVUtils.poit2fTOPoint(approxCurve), hull, true);
int arrIndex[] = hull.toArray();
  1. 箭头的顶点判断做了些特殊处理,是根据少的点数(中间的两个点)判断出来的根据先后顺序。首先得到少的是那些顶点。方法可能有些笨(可以在评论区指出)
ini 复制代码
//第一个参数是 2多边形包围轮廓的顶点
//第二个参数是 4凸包得到的顶点索引(第一个参数的索引)
public static Point findTip(MatOfPoint contour, MatOfInt indexes) {
    int arrIndex[] = indexes.toArray();
    Point arrContour[] = contour.toArray();
    //得到少的顶点位置
    int indices[] = new int[2];
    int k=0;
    for(int j=0;j<arrContour.length;j++){
        boolean flag = false;
        for(int i=0;i<arrIndex.length;i++){
            if(arrIndex[i]==j){
              flag=true;
              break;
            }
        }
        if(!flag){
            indices[k++]=j;
        }
    }

    //得到最小的顶点和最大的顶点坐标
    int index0=Math.min(indices[0],indices[1]);
    int index1=Math.max(indices[0],indices[1]);

    //箭头朝左 凸包内的点第二个就是
    if(index1==arrContour.length-1 && index0 - 2>-1){
        return arrContour[index0 - 2];
    }

    //箭头朝下
    if(index1-index0==4) {
        return arrContour[index0+2];
    }else{
    //这里的判断是上和右
        if (index1 + 2 > arrContour.length - 1) {
            return arrContour[arrContour.length - index1 - 2];
        } else {
            return arrContour[index1 + 2];
        }
    }
}

结束。

相关推荐
??tobenewyorker几秒前
力扣打卡第二十一天 中后遍历+中前遍历 构造二叉树
数据结构·c++·算法·leetcode
蓝澈11218 分钟前
迪杰斯特拉算法之解决单源最短路径问题
java·数据结构
Kali_0715 分钟前
使用 Mathematical_Expression 从零开始实现数学题目的作答小游戏【可复制代码】
java·人工智能·免费
贾全22 分钟前
第十章:HIL-SERL 真实机器人训练实战
人工智能·深度学习·算法·机器学习·机器人
rzl0227 分钟前
java web5(黑马)
java·开发语言·前端
GIS小天37 分钟前
AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年7月4日第128弹
人工智能·算法·机器学习·彩票
guojl1 小时前
深度解读jdk8 HashMap设计与源码
java
guojl1 小时前
深度解读jdk8 ConcurrentHashMap设计与源码
java
满分观察网友z1 小时前
开发者的“右”眼:一个树问题如何拯救我的UI设计(199. 二叉树的右视图)
算法
阿蒙Amon1 小时前
【Python小工具】使用 OpenCV 获取视频时长的详细指南
python·opencv·音视频