基于Python的OpenCV库实现图像的安全读取与保存指南

Written by

in

文章目录
  • 本文介绍了一套基于OpenCV的健壮图像读取和保存方案,重点解决了中文路径处理、格式兼容性和图像质量保持等常见问题。通过ImageIO类的封装,实现了: 安全读取:通过二进制读取+解码的方式规避中文路径问题 灵活保存:支持多种图像格式,并能根据格式特点优化保存参数 批量处理:提供完整的文件夹级处理方案 错误处理:添加适当的异常处理提高代码健壮性 以上就是基于Python的OpenCV库实现图像的安全读取与保存指南的详细内容,更多关于Python OpenCV图像读取与保存的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: openCV-Python笔记之解读图像的读取、显示和保存问题 python+opencv 读取文件夹下的所有图像并批量保存ROI的方法 Python中OpenCV与Matplotlib的图像操作入门指南 Python图像处理篇之opencv实现坐姿检测 使用Python和OpenCV进行视觉图像分割的代码示例
  • 目录
    • 1 常用函数介绍
      • 1.1 图像读取的核心函数
      • 1.2 图像保存的智能实现
    • 2 图像读取和保存的常见场景
      • 2.1 单文件处理场景
      • 2.2 批量处理场景
    • 3 实例演示
      • 3.1 完整的工作流程示例
      • 3.2 不同格式的处理示例
    • 4 常见问题及解决方案
      • 4.1 中文路径问题
      • 4.2 图像保存失败
      • 4.3 通道顺序问题
      • 4.4 图像质量保持
    • 5 总结

      在OpenCV中,cv2.imread() 是主要的图像读取函数,但它有一个明显的限制:无法直接处理中文路径。这就是为什么我们需要采用更安全可靠的读取方法。

      def image_read(self)->np.ndarray:
          """安全读取中文路径的图像,支持单通道、三通道(BGR)、四通道(BGRA)"""
          # 二进制读取 + OpenCV解码
          source_path = Path(self.source_image_path)
          raw_data = np.fromfile(source_path, dtype=np.uint8)
          return cv2.imdecode(raw_data, cv2.IMREAD_UNCHANGED)  # 保留原始通道信息
      

      这种方法的核心优势在于:

      • 规避中文路径问题:通过np.fromfile以二进制方式读取文件,完全绕过路径编码问题
      • 保留原始信息:使用cv2.IMREAD_UNCHANGED参数确保图像的通道数和位深不被修改
      • 格式兼容性强:支持TIFF、PNG、JPEG等多种图像格式

      图像保存同样需要特别注意格式兼容性和质量保持:

      def image_write(self, image:np.ndarray, file_extension:str ='.tif')->bool:
          # 根据不同格式设置优化参数
          if file_extension in ['.tif', '.tiff']:
              encode_params = [cv2.IMWRITE_TIFF_COMPRESSION, 1]  # 无压缩
          elif file_extension in ['.png']:
              encode_params = [cv2.IMWRITE_PNG_COMPRESSION, 0]   # 无压缩
          # ... 其他格式处理
      

      OpenCV的cv2.imwrite()函数支持多种图像格式,包括JPEG、PNG、BMP和TIFF等,只需通过文件扩展名即可指定输出格式。

      对于单个图像文件的处理,我们的类提供了直接的接口:

      # 单个图像文件的读取和保存
      source_path = "输入图像路径.tif"
      target_path = "输出图像路径.png"
      
      image_io = ImageIO(source_path, target_path)
      image = image_io.image_read()  # 读取图像
      success = image_io.image_write(image, ".png")  # 保存为PNG格式
      

      这种场景适用于:

      • 格式转换:将图像从一种格式转换为另一种格式
      • 简单处理:读取-处理-保存的简单工作流
      • 质量检查:验证图像能否正常读取和保存

      在实际项目中,经常需要处理整个文件夹中的图像:

      source_folder = Path("源文件夹")
      target_folder = Path("目标文件夹")
      file_io = FileIO(source_folder, target_folder)
      
      # 获取所有图像文件路径
      image_paths = file_io.filter_by_strings(file_io.list_file_paths(True), [".tif", ".jpg"], True)
      
      for image_path in image_paths:
          source_image_path = Path(image_path)
          target_image_path = target_folder / source_image_path.name
          image_io = ImageIO(source_image_path, target_image_path)
          image = image_io.image_read()
          image_io.image_write(image, ".tif")  # 保持原格式或转换为指定格式
      

      批量处理需要注意:

      • 文件过滤:根据扩展名筛选目标图像文件
      • 路径管理:正确构建源路径和目标路径
      • 错误处理:确保单个文件处理失败不影响整体流程

      以下是一个完整的图像处理流程示例,展示了从读取到保存的整个过程:

      from pathlib import Path
      import cv2
      import numpy as np
      from submodule.file_io import FileIO
      #ImageIO类只涉及到图像数据的读取和储存,不涉及到图像数据的修改
      class ImageIO:
      
          def __init__(self, source_image_path: None | str | Path, target_image_path: None | str | Path) -> None:
              """
              初始化 FileIO 实例
      
              Args:
                  source_image_path: 读取图像路径。如果提供,会检查其是否存在。
                  target_image_path: 保存图像路径。保存时必须提供
              """
              # 处理源文件夹:如果提供则转换为Path,并检查存在性(但不创建)
              self.source_image_path = Path(source_image_path) if source_image_path is not None else None
              if self.source_image_path is not None and not self.source_image_path.exists():
                  # 根据你的需求决定:如果源文件夹必须存在,可以抛出异常
                  # raise ValueError(f"源目录不存在: {self.source_folder}")
                  # 或者仅记录警告,取决于你的业务逻辑
                  print(f"警告: 源文件可能不存在: {self.source_image_path}")
              self.target_image_path = Path(target_image_path)
      
          def image_read(self)->np.ndarray:
              """安全读取中文路径的图像,支持单通道、三通道(BGR)、四通道(BGRA)"""
              # 二进制读取 + OpenCV解码
              source_path = Path(self.source_image_path)
              raw_data = np.fromfile(source_path, dtype=np.uint8)
              return cv2.imdecode(raw_data, cv2.IMREAD_UNCHANGED)  # 保留原始通道信息
      
          def image_write(self, image:np.ndarray, file_extension:str ='.tif')->bool:
              """安全保存图像(支持中文路径),支持多种格式的无损保存
      
              Args:
                  image: 要保存的图像数据
                  file_extension: 文件扩展名,支持 '.tif','.tiff', '.png', '.jpg', '.jpeg', '.webp' 等
      
              Returns:
                  bool: 保存成功返回True,否则返回False
              """
              target_image_path= Path(self.target_image_path)
      
      
              # 根据文件扩展名设置不同的无损保存参数 [1,7,10](@ref)
              file_extension = file_extension.lower()
      
              if file_extension in ['.tif', '.tiff']:
                  # TIFF格式:使用无压缩 [7](@ref)
                  encode_params = [cv2.IMWRITE_TIFF_COMPRESSION, 1]
              elif file_extension in ['.png']:
                  # PNG格式:压缩级别0(不压缩)[7](@ref)
                  encode_params = [cv2.IMWRITE_PNG_COMPRESSION, 0]
              elif file_extension in ['.jpg', '.jpeg']:
                  # JPEG格式:最高质量100(虽然JPEG固有有损,但100是最小损失)[1](@ref)
                  encode_params = [cv2.IMWRITE_JPEG_QUALITY, 100]
              elif file_extension in ['.webp']:
                  # WebP格式:最高质量100 [10](@ref)
                  encode_params = [cv2.IMWRITE_WEBP_QUALITY, 100]
              else:
                  # 其他格式不使用压缩参数
                  encode_params = []
      
              # 使用imencode避免中文路径问题 [8](@ref)
              success, encoded_image = cv2.imencode(file_extension, image, params=encode_params)
      
              if success:
                  encoded_image.tofile(target_image_path)
                  return True
              else:
                  print(f"图像保存失败,格式: {file_extension}")
                  return False
      if __name__ == "__main__":
          source_folder = Path(r"source")
          target_folder = Path(r"target")
          file_io = FileIO(source_folder, target_folder)#创建FileIO实例处理文件列表
          file_paths = file_io.list_file_paths(True) #获取所有文件路径
          image_paths = file_io.filter_by_strings(file_paths,[".tif"],True)#获取.tif文件的路径
          file_io.clear_folder(target_folder)# 清空目标文件夹(谨慎使用)
          # 处理每个图像
          for image_path in image_paths:
              source_image_path = Path(image_path) #目标图像路径
              target_image_path = target_folder / source_image_path.name #要保存的图像路径,可以修改名称来重命名
              image_io = ImageIO(source_image_path,target_image_path) #实例化ImageIO类
              image = image_io.image_read() #读取目标图像数据,BGR
      
              # 可在此处添加图像处理代码
              # 例如:调整大小、应用滤镜等
      
              image_io.image_write(image,file_extension=".tif") #保存图像数据至目标文件夹,可以设置指定格式
              print("成功读取并保存:", f"{source_image_path} -> {target_image_path}")
      

      不同的图像格式有不同的特点和适用场景:

      • TIFF格式:适合需要无损保存的科学图像和医学图像
      • PNG格式:适合需要透明通道的图像,无损压缩
      • JPEG格式:适合照片类图像,有损压缩但文件较小
      • WebP格式:现代格式,提供优秀的压缩率

      问题描述:直接使用cv2.imread()读取包含中文路径的文件时返回None

      解决方案:采用二进制读取+解码的方式:

      raw_data = np.fromfile(source_path, dtype=np.uint8)
      image = cv2.imdecode(raw_data, cv2.IMREAD_UNCHANGED)
      

      问题描述cv2.imwrite()返回False,图像保存失败。

      可能原因和解决方案

      • 目标路径不存在:确保目标目录已创建
      target_path.parent.mkdir(parents=True, exist_ok=True)
      
      1. 权限问题:检查是否有写入权限
      2. 磁盘空间不足:检查磁盘空间

      问题描述:OpenCV使用BGR通道顺序,而其他库(如Matplotlib)使用RGB顺序,导致颜色显示异常。

      解决方案:在显示前转换通道顺序:

      # 将BGR转换为RGB
      image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
      

      问题描述:保存后图像质量下降。

      解决方案:根据格式设置合适的保存参数:

      • JPEG:设置质量参数为95-100
      • PNG:设置压缩级别为0(无压缩)
      • TIFF:使用无损压缩选项

      本文介绍了一套基于OpenCV的健壮图像读取和保存方案,重点解决了中文路径处理、格式兼容性和图像质量保持等常见问题。通过ImageIO类的封装,实现了:

      1. 安全读取:通过二进制读取+解码的方式规避中文路径问题
      2. 灵活保存:支持多种图像格式,并能根据格式特点优化保存参数
      3. 批量处理:提供完整的文件夹级处理方案
      4. 错误处理:添加适当的异常处理提高代码健壮性

      以上就是基于Python的OpenCV库实现图像的安全读取与保存指南的详细内容,更多关于Python OpenCV图像读取与保存的资料请关注风君子博客其它相关文章!

      您可能感兴趣的文章:

      • openCV-Python笔记之解读图像的读取、显示和保存问题
      • python+opencv 读取文件夹下的所有图像并批量保存ROI的方法
      • Python中OpenCV与Matplotlib的图像操作入门指南
      • Python图像处理篇之opencv实现坐姿检测
      • 使用Python和OpenCV进行视觉图像分割的代码示例

      站内搜索