当前位置: 首页 > news >正文

24.java openCV4.x 入门-Imgproc之轮廓凸包与凹陷检测(形状识别)

专栏简介

💒个人主页
📖心灵鸡汤📖

我们唯一拥有的就是今天,唯一能把握的也是今天


建议把本文当作笔记来看,据说专栏目录里面有相应视频🤫
📰专栏目录

Imgproc之轮廓凸包与凸起缺陷检测

  • 一、凸包检测
    • 1.凸轮廓检测
    • 2.凸包寻找
  • 二、凸包凹陷检测

一、凸包检测

1.凸轮廓检测

凸轮廓是指在轮廓上的任意两点之间的直线段都位于轮廓内部。这个方法可以用于检查轮廓的凸性质,以便在图像处理中进行相应的操作,比如在计算凸包时进行预处理

isContourConvex(MatOfPoint contour)
参数:
contour一个 MatOfPoint 类型的对象,表示输入的轮廓
返回一个布尔值,如果输入的轮廓是凸的,则返回 true,否则返回 false

2.凸包寻找

convexHull用于找到输入点集的凸包

convexHull(MatOfPoint points, MatOfInt hull, boolean clockwise)
参数:
points一个包含点集的 MatOfPoint 对象
hull 输出的凸包。它可以是以下两种形式之一
1.整数向量,包含凸包点的索引。在这种情况下,凸包元素是原始数组中凸包点的0-based索引(因为凸包点集合是原始点集的一个子集)
2.点向量。在这种情况下,hull元素是凸包点本身
clockwise 方向标志。如果为true,则输出凸包按顺时针方向排列。否则,按逆时针方向排列。假设的坐标系中,X轴指向右侧,Y轴指向上方
**注意:** `points` and `hull`应该是不同的数组, 有用的链接: https://www.learnopencv.com/convex-hull-using-opencv-in-python-and-c/

示例一、

       MatOfPoint matOfPoint = new MatOfPoint();//随机设置点集matOfPoint.fromArray(new Point(1,2),//0new Point(2,1), //1new Point(4,2),//2new Point(4,4),//3new Point(2,3)//4);//定义输出凸包MatOfInt hull = new MatOfInt();//查找凸包Imgproc.convexHull(matOfPoint,hull,false);//打印结果System.out.println("点集数据:\n " + matOfPoint.dump());System.out.println("凸包数据:\n " + hull.dump());System.out.println("凸包对应点集数据:" );List points = matOfPoint.toList();hull.toList().forEach(hu->{System.out.println(hu+">>"+ points.get(hu));});

结果:

在这里插入图片描述

由上图可以看出,存储顺序似乎与描述不符。这是由于我们是按照坐标系x在右,y在下的原因。(了解即可)

示例二、

        // 加载图像灰度化Mat src = Imgcodecs.imread(FileUtil.resPath+"imgproc/convex_hull_hand.jpeg");// 转换为灰度图Mat gray = new Mat();Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);// 二值化Mat dst = new Mat();Imgproc.threshold(gray, dst, 50, 255, Imgproc.THRESH_BINARY);// 寻找轮廓List contours = new ArrayList<>();Mat hierarchy = new Mat();//查找轮廓,仅检索外部轮廓,仅保留端点Imgproc.findContours(dst, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);// 创建一个空白的列表,用于存储所有的凸包点//获取轮廓的凸包contours.forEach(contour->{List pts =new ArrayList<>();//点集List points = contour.toList();MatOfInt hull = new MatOfInt();//获取凸包Imgproc.convexHull(contour,hull,false);//将凸包转换为坐标// 将凸包的索引转换为点坐标MatOfPoint hullPoints = new MatOfPoint();hullPoints.create((int) hull.size().height, 1, CvType.CV_32SC2);for (int j = 0; j < hull.size().height; j++) {int index = (int) hull.get(j, 0)[0];double[] point = new double[]{contour.get(index, 0)[0],contour.get(index, 0)[1]};hullPoints.put(j, 0, point);}pts.add(hullPoints);//绘制凸包线段Imgproc.polylines(src,pts,true,new Scalar(0,255,0),2);});Imgcodecs.imwrite(FileUtil.resPath+"imgproc/polylines_hand_result.jpg",src);

结果:

convex_hull_hand.jpegpolylines_hand_result.jpg
convex_hull_hand.jpegpolylines_hand_result.jpg

二、凸包凹陷检测

查找轮廓的凸起缺陷。

convexityDefects(MatOfPoint contour, MatOfInt convexhull, MatOfInt4 convexityDefects)
参数:
contour 输入的轮廓,通常是一个点的数组
convexhull 使用convexHull方法获得的凸包,其中应包含构成凸包的轮廓点的索引
convexityDefects 每个凸起缺陷都表示为4个元素的整数向量(也称为Vec4i):(起始索引,结束索引,最远点的索引,fixpt_depth),其中索引是原始轮廓中凸起缺陷开始、结束和最远点的0基索引,而fixpt_depth是固定点近似(具有8位小数)最远轮廓点与凸包之间的距离。也就是说,要获得深度的浮点值,需要将fixpt_depth除以256.0

示例一、

       MatOfPoint matOfPoint = new MatOfPoint();//设置点集matOfPoint.fromArray(new Point(1,2),//0new Point(2,2),new Point(2,1), //1new Point(3,2),new Point(4,2),//2new Point(4,4),//3new Point(3,3),new Point(2,3)//4);//定义输出凸包MatOfInt hull = new MatOfInt();//查找凸包Imgproc.convexHull(matOfPoint,hull,false);//打印结果System.out.println("点集数据:\n " + matOfPoint.dump());System.out.println("凸包数据:\n " + hull.dump());System.out.println("凸包对应点集数据:" );hull.toList().forEach(hu -> {Point point = matOfPoint.toList().get(hu);System.out.println("point = " + point);});//执行凸包缺陷检测MatOfInt4 matOfInt4 = new MatOfInt4();Imgproc.convexityDefects(matOfPoint,hull,matOfInt4);//打印结果System.out.println("凸包缺陷数据:\n " + matOfInt4.dump());System.out.println("凸包缺陷对应点集合数据:");List integers = matOfInt4.toList();int size = integers.size()/4;for (int i = 0; i < size; i++) {//起始索引int startIndex = integers.get(i*4);//结束索引int endIndex = integers.get(i*4+1);//最远索引int farstIndex =  integers.get(i*4+2);//距离int fixptDepth = integers.get(i*4+3);double depth =(double) fixptDepth/256.0;//举例System.out.println("depth = " + depth);//凸起缺陷坐标Point point = matOfPoint.toList().get(farstIndex);System.out.println("point = " + point);}

在这里插入图片描述

        // 加载图像Mat src = Imgcodecs.imread(FileUtil.resPath+"imgproc/convex_hull_hand.jpeg");// 转换为灰度图Mat gray = new Mat();Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);// 二值化Mat binary = new Mat();Imgproc.threshold(gray, binary, 50, 255, Imgproc.THRESH_BINARY);// 寻找轮廓List contours = new ArrayList<>();Mat hierarchy = new Mat();Imgproc.findContours(binary, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);// 创建一个空白的图像,用于绘制凸包Mat dst = Mat.zeros(src.size(), src.type());// 遍历每个轮廓for (int i = 0; i < contours.size(); i++) {MatOfPoint matOfPoint = contours.get(i);// 计算轮廓的凸包MatOfInt hull = new MatOfInt();Imgproc.convexHull(contours.get(i), hull, false);// 将凸包的索引转换为点坐标MatOfPoint hullPoints = new MatOfPoint();hullPoints.create((int) hull.size().height, 1, CvType.CV_32SC2);for (int j = 0; j < hull.size().height; j++) {int index = (int) hull.get(j, 0)[0];double[] point = new double[]{contours.get(i).get(index, 0)[0], contours.get(i).get(index, 0)[1]};hullPoints.put(j, 0, point);}// 绘制凸包Scalar color = new Scalar(0, 255, 0); // 绿色Imgproc.drawContours(dst, contours, i, color, 2); // 绘制轮廓List pts = new ArrayList();pts.add(hullPoints);Imgproc.polylines(src, pts, true, color, 2); // 绘制凸包//执行凸包缺陷检测MatOfInt4 matOfInt4 = new MatOfInt4();Imgproc.convexityDefects(matOfPoint,hull,matOfInt4);List integers = matOfInt4.toList();int size = integers.size()/4;int index =0;for (int r = 0; r <size; r++) {//起始索引int startIndex = integers.get(r*4);//结束索引int endIndex = integers.get(r*4+1);//最远索引int farstIndex =  integers.get(r*4+2);//距离int fixptDepth = integers.get(r*4+3);double depth =(double) fixptDepth/256.0;//过滤if (depth> 15){//凸起缺陷坐标Point point = matOfPoint.toList().get(farstIndex);//凸起缺陷点绘制Imgproc.circle(src,point,10,new Scalar(0,0,255),2);index++;}}System.out.println("过滤后凸起缺陷个数:"+index);// 保存结果图像Imgcodecs.imwrite(FileUtil.resPath+"imgproc/convex_defects_result.png", src);}

结果:

convex_hull_hand.jpegconvex_defects_result.png
convex_hull_hand.jpegconvex_defects_result.jpeg

此方法除了用于手势识别。还可以通过分析凹陷的位置和形状,推断物体的形状和轮廓。

万水千山总是情,本栏完全公开免费。点赞+收藏30,瞬更下一篇
上一篇:Imgproc之轮廓提取与绘制 下一篇:Imgproc之点集最小面积外接
http://www.dtcms.com/a/572690.html

相关文章:

  • IDEA 插件推荐
  • 虚拟 DOM(Virtual DOM)的工作原理及其性能优化机制
  • git详细使用教程
  • 北京工程工程建设交易信息网站和城乡建设部网站
  • soular零基础学习,如何通过工作台聚合TikLab所有工具链
  • 建立企业网站电商网站建设开题报告
  • css font-size 的妙用
  • Jenkins安装部署
  • 阿里云 CDN + 静态资源(图片 / JS/CSS)缓存优化
  • 荣耀前端开发面试题及参考答案
  • shtml怎么做网站建设学校网站多钱
  • Navicat 连接 SQL Server 报错 [08001] 超时错误(258)的排查与解决方案
  • Linux 使用 `wait` 函数回收子进程
  • 八股训练营第 8 天 | TCP连接三次握手的过程?TCP连接四次挥手的过程?HTTP的Keep-Alive是什么?
  • 【计算网络学习笔记】网络基础之网络协议栈
  • CyberSecEval 2
  • wordpress 两栏专业seo培训学校
  • 【浏览器CORS问题解决方案】SpringBoot+Vue3前后端全覆盖:浏览器跨域问题的多样化解决方案
  • 论述AI和人类的分工
  • 第四阶段C#通讯开发-6:Socket之UDP
  • 广州建设网站公司简介百度seo排名推广
  • 四自由度机械臂运动学与动力学分析
  • Spring Security 使用
  • Web3开发中的前端、后端与合约:角色定位与协作逻辑
  • 神经网络—— 人工神经网络
  • GroupNet:基于多尺度神经网络的交互推理轨迹预测
  • CANN 自定义算子实战:从智能门禁到工业质检,MindStudio 7.0 落地优化(时延 130ms + 漏检率 3%,代码可复现)
  • RecyclerView Item 点击 长按事件最佳实践(为什么长按要 return true?
  • 哪些软件可以做网站门户网站搭建方案
  • 【Java 开发日记】设计模式了解吗,知道什么是饿汉式和懒汉式吗?