ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PyMuPDF IRect 完全指南:整数坐标像素边界框的构造、语义与实战应用

PyMuPDF IRect 完全指南:整数坐标像素边界框的构造、语义与实战应用 图像处理【免费下载链接】PyMuPDFPyMuPDF is a high performance Python library for data extraction, analysis, conversion manipulation of PDF (and other) documents.项目地址https://gitcode.com/gh_mirrors/py/PyMuPDF点击查看免费下载PyMuPDF 的IRect类是以整数坐标定义的矩形边界框bounding box与浮点型的Rect几乎同构专门用于描述像素区域如渲染时接收图像数据的区域。本篇基于官方文档 docs/irect.rst 并结合 src/init.py 中的真实实现系统讲解 IRect 的构造方式、空/无限/有效等边界语义、全部方法与属性以及它在 Pixmap 创建、局部渲染和包围盒计算中的实际用法。读完本文你将能熟练地在像素级场景中构建、转换、求交与检测 IRect并理解其底层取整与坐标换算机制。IRect 是什么Rect 的整数坐标兄弟类IRect是一个由四个整数x0, y0, x1, y1定义的矩形边界框与 Rect 非常相似唯一的区别是四个角坐标全部为整数。它主要用于指定一块像素区域例如在渲染时接收图像数据而Rect则用于浮点坐标下的页面几何描述单位是点72 点 1 英寸。从源码看IRect 的方法与属性与 Rect 同名且许多实现直接复用了 Rect 的对应方法再对结果取整。例如 src/init.py 中def __add__(self, p): return Rect.__add__(self, p).round() def intersect(self, r): return Rect.intersect(self, r).round() def transform(self, m): return Rect.transform(self, m).round()也就是说IRect的绝大多数运算都是先按 Rect 的浮点逻辑计算再通过round()收拢回整数网格。因此凡是在 Rect 一节中讨论过的空、有效、无限等矩形语义对 IRect 同样成立详见下文边界语义小节。构造 IRect五种重载与底层取整逻辑IRect 的构造器是重载的官方文档 docs/irect.rst 给出以下形式构造形式说明IRect()全零矩形即IRect(0, 0, 0, 0)IRect(x0, y0, x1, y1)四个整数坐标IRect(irect)由另一个 IRect 拷贝生成新副本IRect(sequence)由包含 4 个数字的 Python 序列构造IRect(p0, p1)/IRect(p0, x1, y1)/IRect(x0, y0, p1)由点与坐标混合构造源码 docstring 中也列出了这几种其中sequence必须是包含 4 个数字的 Python 序列类型list、tuple 等均可。非整数的数字会被截断非数值会抛出异常——这一点在 tests/test_geometry.py 的test_irect中有明确验证IRect(1)、IRect(1, 2, 3, 4, 5)、IRect((1, 2, 3, 4, 5))、IRect(1, 2, 3, x)均会报错。取整方向不是简单的 int() 截断值得注意的细节是IRect 构造时的截断并非对四个坐标统一做int()取整。查看 util_make_irect 的实现def util_make_irect( *args, p0None, p1None, x0None, y0None, x1None, y1None): a, b, c, d util_make_rect( *args, p0p0, p1p1, x0x0, y0y0, x1x1, y1y1) def convert(x, ceil): if ceil: return int(math.ceil(x)) else: return int(math.floor(x)) a convert(a, False) b convert(b, False) c convert(c, True) d convert(d, True) return a, b, c, d前两个坐标x0, y0向下取整floor后两个坐标x1, y1向上取整ceil。这与 Rect.round() 的语义完全一致左上角向外扩右下角向外扩得到的是包含原矩形的最小整数矩形而不是简单的四舍五入。这保证了 IRect 总是完整覆盖它所对应的浮点矩形区域。边界语义空、有效、无限IRect 继承了 Rect 的全部边界语义参见 docs/rect.rst其中明确说明这些论述同样适用于 IRect有效validx0 x1且y0 y1即右下角确实位于左上角的东南方向。注意在 MuPDF 坐标系中 y 轴方向是从上到下的。源码中is_valid属性src/init.py正是这样判断的。空emptyx0 x1或y0 y1。无效矩形必然是空矩形。width与height在坐标倒挂时被置为 0因为源码中宽度定义为max(0, self.x1 - self.x0)src/init.py。无限infinite整个 PyMuPDF 中恰好只有一个无限矩形定义是x0 y0 FZ_MIN_INF_RECT且x1 y1 FZ_MAX_INF_RECT。它包含一切其他矩形主要用于技术性用途例如某函数调用形式上需要一个矩形参数、但语义上希望忽略该参数时。无限矩形不是空的。这两个关键常量在 src/init.py 中定义# largest 32bit integers surviving C float conversion roundtrips # used by MuPDF to define infinite rectangles FZ_MIN_INF_RECT -0x80000000 # -2147483648 FZ_MAX_INF_RECT 0x7fffff80 # 2147483520之所以选择这两个值是因为它们是能在 C float 转换往返中幸存下来的最大/最小 32 位整数。普通矩形坐标也不能超出FZ_MIN_INF_RECT到FZ_MAX_INF_RECT的范围。对应的顶层工厂函数INFINITE_IRECT()、INFINITE_RECT()、INFINITE_QUAD()、EMPTY_RECT()定义在 src/init.pydef INFINITE_IRECT(): return IRect(FZ_MIN_INF_RECT, FZ_MIN_INF_RECT, FZ_MAX_INF_RECT, FZ_MAX_INF_RECT)方法与属性总览官方文档给出如下速查表本文后续将逐项展开属性 / 方法简述IRect.contains检查另一个对象是否被包含IRect.get_area计算矩形面积IRect.intersect与另一矩形的公共部分IRect.intersects检查是否存在非空交集IRect.morph以一点和一矩阵进行变换IRect.torect变换到另一矩形的矩阵IRect.norm欧几里得范数IRect.normalize使矩形有限规范化角点IRect.bottom_left左下角点别名blIRect.bottom_right右下角点别名brIRect.height矩形高度IRect.is_empty矩形是否为空IRect.is_infinite矩形是否为无限IRect.rect对应的Rect等价物IRect.top_left左上角点别名tlIRect.top_right右上角点别名trIRect.quad由四角构成的QuadIRect.width矩形宽度IRect.x0左上角 X 坐标IRect.x1右下角 X 坐标IRect.y0左上角 Y 坐标IRect.y1右下角 Y 坐标核心方法详解get_area([unit])按像素、英寸、厘米或毫米计算面积get_area()计算矩形面积不带参数时等价于abs(IRect)的数值。与空矩形一样无限矩形的面积也是 0。可选的unit参数支持四种单位px像素默认、in英寸、cm厘米、mm毫米返回类型为float。其底层换算逻辑见 src/init.py 的_rect_areadef _rect_area(width, height, args): unit args[0] if args else px u {px: (1, 1), in: (1.0, 72.0), cm: (2.54, 72.0), mm: (25.4, 72.0)} f (u[unit][0] / u[unit][1]) ** 2 return f * width * height可见换算基准是72 点 1 英寸例如get_area(cm)即(2.54/72.0) ** 2 * width * height把以点像素为单位的面积换算为平方厘米。intersect(ir)原地求交计算当前矩形与ir的公共矩形区域并原地替换当前矩形。若二者任一为空结果也为空若任一为无限则取另一个作为结果两者皆无限则结果无限。源码实现是先走Rect.intersect再round()def intersect(self, r): Restrict rectangle to intersection with rectangle r. return Rect.intersect(self, r).round()注意它是返回新对象而非就地修改docstring 中restrict的语义使用时应接收返回值。contains(x)包含检测检查x是否被包含在矩形中。x可以是rect_like、point_like或一个数字。语义细节若x是空矩形则永远返回 True若当前矩形为空则对非空矩形或点永远返回 False若x是数字则检查它是否为四个分量之一即等于 x0、y0、x1、y1 中的某一个x in irect与irect.contains(x)完全等价源码中__contains__直接委托给Rect.__contains__见 src/init.py。值得提醒的是由于矩形是半开的见下文语义小节只有左上角(x0, y0)永远属于矩形其余三个角不属于。intersects(r)非空交集检测检查当前矩形与rect_like参数r是否包含非空的公共 IRect。若二者任一为无限或空则恒为 False。返回值类型为bool。源码同样委托给Rect.intersectssrc/init.py。torect(rect)计算变换矩阵v1.19.3 新增计算把当前矩形变换到目标矩形rect的矩阵。要求两个矩形都不能为空或无限否则抛出ValueError。返回值是一个 Matrix满足self * mat rect典型用途是在页面坐标与 Pixmap 像素坐标之间做变换。其实现src/init.py非常直观——先平移到原点、再缩放、再平移到位def torect(self, r): r Rect(r) if self.is_infinite or self.is_empty or r.is_infinite or r.is_empty: raise ValueError(rectangles must be finite and not empty) return ( Matrix(1, 0, 0, 1, -self.x0, -self.y0) * Matrix(r.width / self.width, r.height / self.height) * Matrix(1, 0, 0, 1, r.x0, r.y0) )morph(fixpoint, matrix)以固定点进行仿射变换v1.17.0 新增以点fixpoint为固定点、用matrix对矩形应用矩阵变换返回一个新的 Quad。它是同名 quad 方法的包装若矩形为无限则返回无限 QuadINFINITE_QUAD()。源码def morph(self, p, m): if self.is_infinite: return INFINITE_QUAD() return self.quad.morph(p, m)norm()欧几里得范数v1.16.0 新增把矩形视为四个数字组成的向量返回其欧几里得范数def norm(self): return math.sqrt(sum([c*c for c in self]))normalize()让矩形变得有限通过交换角点使矩形规范化若x1 x0则交换 x0/x1若y1 y0则交换 y0/y1。完成后右下角确实位于左上角的东南方向但结果仍可能是空矩形。源码为原地修改并返回自身src/init.pydef normalize(self): Replace rectangle with its valid version. if self.x1 self.x0: self.x0, self.x1 self.x1, self.x0 if self.y1 self.y0: self.y0, self.y1 self.y1, self.y0 return self属性详解角点、尺寸与类型转换IRect 的所有角点属性都以 Point 对象返回源码 src/init.py属性别名值top_lefttlPoint(x0, y0)top_righttrPoint(x1, y0)bottom_leftblPoint(x0, y1)bottom_rightbrPoint(x1, y1)尺寸与坐标属性widthabs(x1 - x0)的整数结果源码中实现为max(0, self.x1 - self.x0)倒挂时归零height同理max(0, self.y1 - self.y0)x0/y0左 / 上侧角点的坐标intx1/y1右 / 下侧角点的坐标int。状态属性is_emptyTrue当且仅当x0 x1 or y0 y1src/init.pyis_infiniteTrue当且仅当恰好是那个唯一的无限矩形即x0 y0 FZ_MIN_INF_RECT and x1 y1 FZ_MAX_INF_RECTsrc/init.py。类型转换属性rect以浮点数表示相同坐标的 Rect实现为Rect(self)src/init.pyquad由四角构成的四边形Quad(irect.tl, irect.tr, irect.bl, irect.br)src/init.py。另外IRect 还额外提供了include_point(p)与include_rect(r)源码 src/init.py分别把矩形扩张到包含某点 / 某矩形并返回新的 IRect——注意这两个方法在官方速查表中未列出但源码与测试均确认其存在def include_point(self, p): rect self.rect.include_point(p) return rect.irect def include_rect(self, r): rect self.rect.include_rect(r) return rect.irect这在逐步收集多个点/块的包围盒场景中非常实用tests/test_geometry.py 对此有验证例如IRect(10, 20, 100, 200).include_point(Point(150, 250))结果为(10, 20, 150, 250)而include_rect((0, 0, 0, 0))空矩形不会改变原矩形。序列协议与算术运算符IRect 遵循 Python 序列协议详见文档 docs/irect.rst 末尾的 note因此四个分量可以通过索引访问irect[0]到irect[3]对应(x0, y0, x1, y1)源码__getitem__src/init.py也支持索引赋值irect[2] 5会执行int(5)后写入对应分量越界抛出IndexError源码__setitem__src/init.pylen(irect)恒为 4支持与元组等长序列比较__eq__支持哈希__hash__因此 IRect 可以作为字典键或集合成员。算术运算符方面矩形可与 Matrix 相乘、与 Point/向量做加减等完整规则见 docs/algebra.rst。IRect 的运算符实现src/init.py模式统一——先按 Rect 的规则运算再round()回整数例如def __add__(self, p): return Rect.__add__(self, p).round() def __and__(self, x): return Rect.__and__(self, x).round() # 交集 def __or__(self, x): return Rect.__or__(self, x).round() # 并集 def __mul__(self, m): return Rect.__mul__(self, m).round() # 矩阵变换与 Rect 的互转Rect.irect / round()从浮点 Rect 到 IRect 的转换有两个途径Rect.irect属性等价于Rect.round()方法的结果Rect.round()方法生成包含该矩形的最小 IRect。注意这不是简单地对各边做四舍五入左上角向左上取整、右下角向右下取整。文档 docs/rect.rst 给出示例 pymupdf.Rect(0.5, -0.01, 123.88, 455.123456).round() IRect(0, -1, 124, 456)同时也提醒了一个可能的悖论非空 Rect 取整后可能得到空 IRect因为 MuPDF 的算法允许 1e-3 的容差例如Rect(100, 100, 200, 100.001)非空但其round()结果是IRect(100, 100, 200, 100)——空的。设计像素区域裁剪逻辑时需留意这一点。反向转换则直接使用irect.rect属性得到浮点坐标的等价 Rect便于参与页面级以点为单位的几何运算。实战应用像素区域与渲染裁剪IRect 最典型的应用场景就是像素级操作。下面结合仓库测试与源码给出几个真实用例。1. 用 IRect 直接构造 Pixmap在 tests/test_general.py 中IRect 被直接用于指定 Pixmap 的尺寸与像素区域from pymupdf import IRect, Pixmap, CS_RGB, Colorspace image Pixmap(Colorspace(CS_RGB), IRect(0, 0, 13, 37))因为像素缓冲区需要整数行列数用 IRect 描述接收图像数据的区域是语义上最自然的选择——这正是官方文档对 IRect 用途的原始定义。2. 用 IRect 做局部渲染裁剪在 tests/test_pixmap.py 中IRect 被用作页面渲染的 clip 区域page.get_pixmap(clippymupdf.IRect(0, 0, 100, 100)).save(test_3134_irect.jpg)当需要只渲染页面左上角 100×100 像素的矩形区域时直接传入 IRect 作为clip即可避免对整页进行不必要的渲染。3. 文本/绘图包围盒的取整在 tests/test_general.py 中从词块数据得到的浮点 bbox 通过.irect转成整数坐标bbox1 pymupdf.Rect(w1[:4]).irect # its IRect coordinates bbox0 pymupdf.Rect(w0[:4]).irect这在需要把文本块坐标对齐到像素网格例如与图像遮罩、高亮框对齐时非常实用保证了取整方向始终是外扩包含不会遗漏任何浮点覆盖区域。4. 借助 torect 做坐标映射当需要把一个 IRect 区域例如像素窗口映射到另一个矩形例如页面矩形时torect()返回的 Matrix 可以直接用于坐标变换src pymupdf.IRect(0, 0, 100, 100) # 像素窗口 dst page.rect # 页面区域 mat src.torect(dst) # self * mat dst小结IRect 是 PyMuPDF 的整数坐标矩形与 Rect 共享全部语义但专门面向像素级区域图像缓冲区、渲染裁剪构造时x0/y0向下取整、x1/y1向上取整util_make_irect保证 IRect 完整覆盖对应的浮点矩形空 / 有效 / 无限三种状态有精确的代数定义无限矩形全库唯一由FZ_MIN_INF_RECT/FZ_MAX_INF_RECT常量界定src/init.py全部运算通过Rect 计算 round()取整实现src/init.py行为可预测、结果始终为整数典型用途包括 Pixmap 构造、clip局部渲染、包围盒像素对齐以及借助torect()进行坐标映射。进一步阅读Rect 与矩形语义、Point 点类型、Quad 四边形、Matrix 矩阵、几何代数运算以及仓库中对应的单元测试 tests/test_geometry.py 与 tests/test_pixmap.py。赞分享图像处理【免费下载链接】PyMuPDFPyMuPDF is a high performance Python library for data extraction, analysis, conversion manipulation of PDF (and other) documents.项目地址https://gitcode.com/gh_mirrors/py/PyMuPDF点击查看免费下载相关推荐目标检测边界框完全指南从构造原理到坐标转换详解目标检测边界框完全指南从构造原理到坐标转换详解 Object Detection Metrics 是评估目标检测算法性能最流行的工具库其中的 Boundin人工智能计算机视觉模型评测YOLOv10 实时目标距离计算实战基于边界框质心与像素-米换算的完整指南YOLOv10 实时目标距离计算实战基于边界框质心与像素 米换算的完整指南 距离计算是计算机视觉空间分析中的常见需求。本文基于当前 YOLOv10 仓库Ne人工智能深度学习计算机视觉CANN ops-cv ToAbsoluteBBox 算子解析归一化边界框到绝对像素坐标的 NPU 实现指南CANN ops cv ToAbsoluteBBox 算子解析归一化边界框到绝对像素坐标的 NPU 实现指南 ToAbsoluteBBox 是 CANN op算子库人工智能计算机视觉图像处理CANN上一篇SQLBoiler中文快速入门指南下一篇vfox 迁移指南从nvm、fvm、sdkman平滑过渡的终极方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表