You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何用OpenCV调整图片DPI?含当前检测及300DPI转换需求

解决OpenCV调整图片至300DPI的问题

我之前也碰到过类似的困惑,其实核心要先搞清楚:DPI是图片的元数据(描述每英寸显示的像素数),和像素尺寸是完全独立的两个属性。OpenCV的cv2.resize只负责修改像素数量,根本不会触碰DPI元数据,这就是为什么你用Photoshop验证后发现DPI没变化的原因。

要实现「仅当当前DPI低于300时调整至300DPI」的需求,我们需要结合OpenCV处理像素,再用Pillow库读取/写入DPI元数据,具体步骤如下:

步骤1:读取图片的DPI信息

OpenCV的cv2.imread不会读取图片的EXIF元数据,所以我们用Pillow来获取DPI。先确保你已经安装了Pillow:

pip install pillow

读取DPI的工具函数:

from PIL import Image

def get_image_dpi(image_path):
    with Image.open(image_path) as img:
        dpi = img.info.get('dpi')
        # 部分图片可能没有DPI元数据,默认按行业通用的72DPI处理
        if dpi is None:
            return (72, 72)
        return dpi

调用这个函数就能拿到当前图片的DPI:

dpi_x, dpi_y = get_image_dpi("source.png")
current_dpi = min(dpi_x, dpi_y)  # 取最小的DPI值作为判断标准

步骤2:计算缩放比例并调整像素尺寸

如果当前DPI低于300,我们需要计算缩放比例(scale = 300 / current_dpi),然后用cv2.resize调整像素尺寸。放大图片时推荐用cv2.INTER_CUBIC插值,能让画质更平滑,更适合OCR识别场景。

完整的处理函数:

import cv2
import numpy as np

def resize_image_to_300dpi(image_path, output_path):
    # 获取当前DPI
    dpi_x, dpi_y = get_image_dpi(image_path)
    current_dpi = min(dpi_x, dpi_y)
    
    if current_dpi >= 300:
        print("当前图片DPI已达标,直接保留原画质并写入300DPI元数据")
        with Image.open(image_path) as img:
            img.save(output_path, dpi=(300, 300))
        return
    
    # 用OpenCV读取图片(处理像素)
    image = cv2.imread(image_path)
    if image is None:
        raise ValueError("无法读取图片,请检查文件路径是否正确")
    
    # 计算缩放后的像素尺寸
    scale = 300 / current_dpi
    new_width = int(image.shape[1] * scale)
    new_height = int(image.shape[0] * scale)
    
    # 调整像素尺寸
    resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_CUBIC)
    
    # 用Pillow保存并写入300DPI元数据(OpenCV不支持写入DPI)
    # 先把OpenCV的BGR格式转换成PIL的RGB格式
    pil_image = Image.fromarray(cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB))
    pil_image.save(output_path, dpi=(300, 300))
    print(f"已将图片调整至300DPI,保存至{output_path}")

调用示例

resize_image_to_300dpi("source.png", "output_300dpi.png")

关键细节说明

  • 为什么必须用Pillow保存?因为OpenCV的imwrite函数只会写入像素数据,完全忽略DPI元信息,只有通过Pillow才能把300DPI的标记写入图片文件。
  • 插值方法选择:放大图片时,cv2.INTER_CUBIC比默认的INTER_LINEAR画质更清晰,能提升OCR的识别准确率。
  • 无DPI元数据的处理:如果图片没有标注DPI,我们默认按72DPI处理,这是多数图片的出厂默认值。

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

火山引擎 最新活动