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];
        }
    }
}

结束。

相关推荐
哎呦没31 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
jndingxin1 小时前
OpenCV视频I/O(14)创建和写入视频文件的类:VideoWriter介绍
人工智能·opencv·音视频
Kalika0-01 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
编程、小哥哥1 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
sp_fyf_20241 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
IT学长编程2 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇2 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码2 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
我是哈哈hh3 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
郭二哈3 小时前
C++——模板进阶、继承
java·服务器·c++