使用PyMuPDF提取PDF图片遇异常:漏图、尺寸异常及偏色求助
解决PDF图片提取缺失、尺寸异常及颜色偏暗问题
问题描述
使用以下基于fitz(PyMuPDF)的Python代码提取PDF图片时,出现部分图片缺失、部分提取出的图片尺寸为1×1的情况,此前尝试提取时还存在图片颜色偏暗的问题,需要实现原样提取PDF中的所有图片。
原代码:
import fitz # Open the PDF file file = fitz.open("D41813 LS K2W COLLAR TOP 000751556 (0318).pdf") # Iterate through each page of the PDF for pageNumber, page in enumerate(file, start=1): # Get the list of images on the current page for imgNumber, img in enumerate(page.get_images(full=True), start=1): xref = img[0] # Extract the image pix = fitz.Pixmap(file, xref) # Convert the image to RGB if it is not already in that format if pix.n > 4 or pix.alpha: # Check if the image is CMYK or has alpha channel pix = fitz.Pixmap(fitz.csRGB, pix) # Save the image with a unique filename pix.save(f"page{pageNumber}_img{imgNumber}.jpg") # Close the PDF file file.close()
解决方案
1. 过滤1×1尺寸的占位图片
PDF中这类极小图片多为内部标记或透明占位元素,直接过滤即可:
# 在提取Pixmap后添加尺寸判断 if pix.width <= 1 and pix.height <= 1: continue # 跳过无效占位图
2. 修复颜色偏暗问题
CMYK转RGB时默认转换逻辑易出现色彩偏差,优先保留原图格式可避免损失:
# 获取图片原始格式(从PDF图片元数据中提取) img_ext = img[1].split(".")[-1].lower() if len(img[1]) > 0 else "png" # 仅在目标格式为JPG且需要色彩转换时处理 if img_ext in ("jpg", "jpeg") and (pix.n > 4 or pix.alpha): pix = fitz.Pixmap(fitz.csRGB, pix) pix.save(f"page{pageNumber}_img{imgNumber}.jpg") else: # 保存为原始格式(如PNG),最大程度保留色彩信息 pix.save(f"page{pageNumber}_img{imgNumber}.{img_ext}")
3. 提取所有嵌入式图片(含页面未直接引用的)
部分图片存储在PDF资源中但未被页面显式引用,遍历所有xref对象可补全提取:
# 遍历PDF所有对象,提取图片类型资源 for xref in range(1, file.xref_length()): # 判断当前对象是否为图片 if file.xref_get_key(xref, "Subtype")[1] == "/Image": pix = fitz.Pixmap(file, xref) if pix.width <= 1 and pix.height <= 1: continue # 色彩转换与保存逻辑同前 if pix.n > 4 or pix.alpha: pix = fitz.Pixmap(fitz.csRGB, pix) pix.save(f"image_xref{xref}.jpg")
完整优化代码
import fitz def extract_pdf_images(pdf_path): file = fitz.open(pdf_path) # 提取页面可见图片 for page_num, page in enumerate(file, start=1): for img_num, img in enumerate(page.get_images(full=True), start=1): xref = img[0] pix = fitz.Pixmap(file, xref) # 跳过极小占位图 if pix.width <= 1 and pix.height <= 1: continue # 获取原始图片格式 img_ext = img[1].split(".")[-1].lower() if img[1] else "png" # 处理色彩空间并保存 if (pix.n > 4 or pix.alpha) and img_ext in ("jpg", "jpeg"): pix = fitz.Pixmap(fitz.csRGB, pix) pix.save(f"page{page_num}_img{img_num}.jpg") else: pix.save(f"page{page_num}_img{img_num}.{img_ext}") # 释放资源 if pix.n > 0: pix = None # 提取所有嵌入式图片(补充页面未引用的) for xref in range(1, file.xref_length()): if file.xref_get_key(xref, "Subtype")[1] == "/Image": pix = fitz.Pixmap(file, xref) if pix.width <= 1 and pix.height <= 1: continue if pix.n > 4 or pix.alpha: pix = fitz.Pixmap(fitz.csRGB, pix) pix.save(f"image_xref{xref}.jpg") if pix.n > 0: pix = None file.close() # 调用提取函数 extract_pdf_images("D41813 LS K2W COLLAR TOP 000751556 (0318).pdf")
关键说明
- 极小尺寸图片属于PDF内部冗余元素,过滤后不影响真实内容提取。
- 保留原始图片格式是避免色彩偏差的核心,仅在需要JPG格式时才进行CMYK转RGB。
- 遍历所有xref对象可覆盖页面未显式引用的嵌入式图片,解决缺失问题。
内容的提问来源于stack exchange,提问作者dheeraj gakkampudi
相关产品推荐
相关产品推荐

