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

结束。

相关推荐
南山十一少26 分钟前
Spring Security+JWT+Redis实现项目级前后端分离认证授权
java·spring·bootstrap
427724002 小时前
IDEA使用git不提示账号密码登录,而是输入token问题解决
java·git·intellij-idea
chengooooooo2 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
李长渊哦2 小时前
常用的 JVM 参数:配置与优化指南
java·jvm
计算机小白一个2 小时前
蓝桥杯 Java B 组之设计 LRU 缓存
java·算法·蓝桥杯
万事可爱^3 小时前
HDBSCAN:密度自适应的层次聚类算法解析与实践
算法·机器学习·数据挖掘·聚类·hdbscan
大数据追光猿5 小时前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法
Dream it possible!5 小时前
LeetCode 热题 100_在排序数组中查找元素的第一个和最后一个位置(65_34_中等_C++)(二分查找)(一次二分查找+挨个搜索;两次二分查找)
c++·算法·leetcode
夏末秋也凉5 小时前
力扣-回溯-46 全排列
数据结构·算法·leetcode
南宫生5 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode