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

从二值 Mask 获取外接矩形坐标

从二值 Mask 获取外接矩形坐标

语雀:https://www.yuque.com/lart/blog/lxnpun

Numpy-Based

np.where(condition) / np.nonzero(condition)

  • https://numpy.org/doc/stable/reference/generated/numpy.where.html
  • https://numpy.org/doc/stable/reference/generated/numpy.nonzero.html#numpy.nonzero

该方法只适用于获得标准的,即非倾斜的外接矩形。

这里的 condition 可以使自定义的等式,或者直接是一个确定的数组。使用后者时返回每个不等于 0 的位置的坐标。该坐标结果包含两个数组,为了便于理解这两个数组的含义,可以参考官方提供的例子:

>>> x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]])
>>> x
array([[3, 0, 0],
       [0, 4, 0],
       [5, 6, 0]])
>>> np.nonzero(x)
(array([0, 1, 2, 2]), array([0, 1, 0, 1]))

可以看到,返回的两个数组,第一个是第 0 维度的坐标,第二个是第 1 维度的坐标。也就是 按照索引维度由前向后依此对应

y_coords, x_coords = np.nonzero(ori_mask)  
x_min = x_coords.min()  
x_max = x_coords.max()  
y_min = y_coords.min()  
y_max = y_coords.max()

由于会返回非零区域内像素坐标,所以同时这两个函数可以被用来计算质心坐标,可见我的另一篇文档:https://www.yuque.com/lart/blog/gpbigm

OpenCV-Based

cv2.minAreaRect(contour)

  • https://docs.opencv.org/4.5.5/d3/dc0/group__imgproc__shape.html#ga3d476a3417130ae5154aea421ca7ead9

这可以获得最小的外接矩形,其会得到一个尽可能保卫对应轮廓的矩形,甚至是倾斜的。

核心代码为:

"""
rect[0]返回矩形的中心点,(x,y),实际上为y行x列的像素点
rect[1]返回矩形的长和宽,顺序一定不要弄错了,在旋转角度上有很重要的作用
rect[2]返回矩形的旋转角度,角度范围是[-90,0)
"""
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect) # 将边界框表示转化为四点坐标形式

一个典型的例子如下,要注意这里 cv2.minAreaRect 在返回点的时候的顺序有些特别。一般情况下最好不要对点的顺序有特别的要求。

def detect_rect(contours):
    squares = []
    for c in contours:
        rect = cv2.minAreaRect(c)
        """
        The lowest point of the rectangle(does not matter left or right) 
        will always be the first sub-list of the "box" ndarray. 
        Now this point will be the reference point to decide 
        what the next sub-list represents. 
        Meaning, the next sub-list will always represent the point 
        that you first get when you move in the clockwise direction.
        """
        box = cv2.boxPoints(rect)  
        squares.append(clockwise_box)
    return np.asarray(squares, dtype=np.int32)

contours, hierarchy = cv2.findContours(image, mode=cv2.RETR_LIST, method=cv2.CHAIN_APPROX_SIMPLE)
squares = detect_rect(contours=contours)

相关文章:

  • Tomcat 的本地部署及 SmartTomcat 的使用
  • Unity Shader LightMode 标签
  • linux搭建docker镜像服务
  • 解决mybatis用Map返回的字段全变大写的问题
  • 交联剂134272-64-3,MAL-NH2 HCl 在抗体的标记上面效果明显
  • mybatis第一次课
  • 全民拼购模式:社交电商与拼购新玩法
  • Linux笔记系列
  • 机器人冗余自由度优化过程中的零空间概念
  • ActiveMQ如何处理重复消息?如何保证消息的有序性?如何处理消息堆积?
  • 2022 面试必刷 461 道大厂架构面试真题汇总 + 面经 + 简历模板
  • vue中使用base64编码上传文件或者图片,以及base64编码的图片在img标签中使用
  • 企业应用选择租用云服务器还是租用物理服务器
  • sql2java-pagehelper:Spring AOP支持
  • java基础之策略模式[26]
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 【5+】跨webview多页面 触发事件(二)
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • Docker 笔记(2):Dockerfile
  • HomeBrew常规使用教程
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • pdf文件如何在线转换为jpg图片
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • tab.js分享及浏览器兼容性问题汇总
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 复杂数据处理
  • 面试总结JavaScript篇
  • 你真的知道 == 和 equals 的区别吗?
  • 排序算法之--选择排序
  • 前端存储 - localStorage
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 首页查询功能的一次实现过程
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • kubernetes资源对象--ingress
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​水经微图Web1.5.0版即将上线
  • ###C语言程序设计-----C语言学习(6)#
  • #NOIP 2014# day.1 T2 联合权值
  • (¥1011)-(一千零一拾一元整)输出
  • (javascript)再说document.body.scrollTop的使用问题
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (转载)hibernate缓存
  • ./和../以及/和~之间的区别
  • .apk文件,IIS不支持下载解决
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .NET 分布式技术比较
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .Net 中Partitioner static与dynamic的性能对比
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .net下简单快捷的数值高低位切换
  • .NET中两种OCR方式对比
  • @vue/cli脚手架