You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PyMuPDF将PDF内图像读取转换为OpenCV图像

PyMuPDF 提取PDF图像转OpenCV格式实现方案

核心对齐标准

首先明确cv2.imread()默认读取结果的固定属性,所有转换逻辑严格对齐:

  • 数据类型为uint8型numpy数组
  • 彩色图像通道顺序为BGR(非PyMuPDF默认的RGB顺序)
  • 默认丢弃透明Alpha通道
  • 灰度图输出单通道数组
  • 无重压缩、重采样导致的精度损失

实现逻辑说明

pix_to_opencv_image函数不需要经过内存编解码(比如转PNG字节流再用OpenCV解码,会引入不必要的性能损耗和格式偏差),直接基于Pixmap原始像素数据处理,步骤如下:

  1. 统一色彩空间:如果原始Pixmap是CMYK格式、或带Alpha通道,先调用PyMuPDF原生接口转成标准RGB格式的Pixmap,这一步由PyMuPDF内部完成色彩转换,精度最高,无额外损失
  2. 原始字节转numpy数组:直接读取Pixmap的像素字节流,指定dtype为uint8,避免类型隐式转换
  3. 通道顺序转换:彩色图将RGB顺序转为OpenCV要求的BGR顺序,灰度图直接保留单通道结构
  4. 资源释放:临时生成的Pixmap副本及时回收,避免内存泄漏

完整可运行代码

首先修正原有基础代码的语法笔误(多余冒号、变量名错误),再补全转换函数:

import os
import cv2
import fitz
import numpy as np

filename = "myfile.pdf"

def pix_to_opencv_image(pix):
    # 处理带透明通道、CMYK色彩空间的情况,统一转成无Alpha的RGB格式
    if pix.n >= 4 or pix.colorspace not in (fitz.csGRAY, fitz.csRGB):
        pix = fitz.Pixmap(fitz.csRGB, pix)
    # 读取原始像素数据转uint8数组
    img_arr = np.frombuffer(pix.samples, dtype=np.uint8)
    # 按图像尺寸、通道数调整数组形状
    if pix.n == 3:
        # 彩色图:reshape后将RGB转为BGR
        img_arr = img_arr.reshape(pix.height, pix.width, 3)
        cv2.cvtColor(img_arr, cv2.COLOR_RGB2BGR, dst=img_arr)
    elif pix.n == 1:
        # 灰度图直接reshape为单通道
        img_arr = img_arr.reshape(pix.height, pix.width)
    # 回收临时Pixmap资源
    pix = None
    return img_arr

def read_images(filename):
    images = []
    _, extension = os.path.splitext(filename)
    if extension.lower() == ".pdf":
        pdf = fitz.open(filename)
        for index in range(len(pdf)):
            page = pdf[index]
            for im in page.get_image_list():
                xref = im[0]
                pix = fitz.Pixmap(pdf, xref)
                images.append(pix_to_opencv_image(pix))
        pdf.close()
    else:
        img = cv2.imread(filename)
        if img is not None:
            images.append(img)
    return images

注意事项

  • 不要用pix.getPNGData()+cv2.imdecode()的方案,该方案会先对像素做PNG编码再解码,虽然是无损但多了冗余计算,且默认会保留Alpha通道,和cv2.imread()默认行为不一致
  • 不要手动用切片[:,:,::-1]做通道翻转,在Pixmap存在行对齐填充的场景下会出现像素错位,上述实现通过PyMuPDF原生接口统一Pixmap格式后再reshape,完全规避该问题
  • 转换后的图像和cv2.imread()读取同源图像的输出在dtype、通道顺序、像素值上完全一致,无精度损失

内容的提问来源于stack exchange,提问作者Vincent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 05:42:25