Python图像处理全流程:从OpenCV基础到完整分类项目实战
最近在图像处理项目中经常遇到需要批量处理图片、提取特征并进行分类的需求。无论是做简单的图像分类还是复杂的计算机视觉应用掌握基础的图像处理流程都是必备技能。本文将围绕图像处理的核心步骤从环境搭建到完整项目实现带你走通一个典型的图像处理项目全流程。本文适合有一定Python基础的开发者特别是想要入门计算机视觉或需要快速上手图像处理项目的同学。通过本文你将学会如何配置图像处理环境、使用OpenCV和PIL进行基础操作、实现图像特征提取并完成一个完整的图像分类项目。1. 图像处理基础概念1.1 什么是数字图像处理数字图像处理是指使用计算机算法对数字图像进行分析和处理的技术。简单来说就是将图像转换成数字矩阵然后通过数学运算来改善图像质量、提取有用信息或进行模式识别。数字图像由像素组成每个像素都有特定的位置和颜色值。对于灰度图像每个像素用一个数值表示亮度对于彩色图像通常用RGB三个通道的数值组合来表示颜色。1.2 常见的图像处理任务图像处理涵盖多种任务主要包括图像增强改善图像视觉效果如对比度调整、锐化等图像分割将图像分成有意义的区域特征提取从图像中提取关键信息如边缘、角点等目标检测识别图像中的特定物体图像分类将图像归入预定义的类别1.3 图像处理的应用场景图像处理技术广泛应用于各个领域医疗影像分析CT、MRI图像处理自动驾驶道路识别、障碍物检测安防监控人脸识别、行为分析工业检测产品质量自动检测遥感图像分析地质勘探、环境监测2. 环境准备与工具配置2.1 Python环境要求本文基于Python 3.8环境推荐使用Anaconda进行环境管理。以下是主要依赖库及其版本# 创建新的conda环境 conda create -n image-processing python3.8 conda activate image-processing # 安装核心依赖 pip install opencv-python4.5.5.64 pip install pillow9.0.1 pip install numpy1.21.5 pip install matplotlib3.5.1 pip install scikit-learn1.0.2 pip install tensorflow2.7.0 # 可选用于深度学习相关任务2.2 开发工具推荐对于图像处理项目推荐使用以下工具组合Jupyter Notebook适合实验和可视化调试VS Code Python插件提供完整的开发环境PyCharm专业的Python IDE适合大型项目2.3 测试图像准备为了方便后续演示我们先准备一些测试图像。你可以从公开数据集中下载或者使用自己的图片。import os import urllib.request from PIL import Image # 创建测试图像目录 os.makedirs(test_images, exist_okTrue) # 下载示例图像可选 test_images [ https://example.com/image1.jpg, # 替换为实际可用的图像URL https://example.com/image2.jpg ] for i, url in enumerate(test_images): try: urllib.request.urlretrieve(url, ftest_images/sample_{i}.jpg) print(f下载完成: sample_{i}.jpg) except: print(f下载失败: {url}) # 创建简单的测试图像 img Image.new(RGB, (100, 100), color(i*50, i*30, i*70)) img.save(ftest_images/sample_{i}.jpg)3. 图像处理核心库详解3.1 OpenCV基础操作OpenCV是计算机视觉领域最流行的库之一提供了丰富的图像处理功能。import cv2 import numpy as np import matplotlib.pyplot as plt # 读取图像 def read_image_opencv(image_path): 使用OpenCV读取图像 # 以彩色模式读取 img_bgr cv2.imread(image_path) # 将BGR转换为RGBOpenCV默认使用BGR格式 img_rgb cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) return img_rgb # 图像基本信息获取 def get_image_info(image_path): 获取图像的基本信息 img cv2.imread(image_path) if img is None: return 图像读取失败 height, width, channels img.shape image_size img.size data_type img.dtype info { 尺寸: f{width} x {height}, 通道数: channels, 总像素数: image_size, 数据类型: data_type } return info # 测试函数 image_path test_images/sample_0.jpg img read_image_opencv(image_path) info get_image_info(image_path) print(图像信息:, info) plt.imshow(img) plt.title(示例图像) plt.axis(off) plt.show()3.2 PIL/Pillow库使用PILPython Imaging Library是另一个常用的图像处理库特别适合基本的图像操作。from PIL import Image, ImageFilter, ImageEnhance import numpy as np # 使用PIL处理图像 def pil_basic_operations(image_path): PIL库的基础操作示例 # 打开图像 img Image.open(image_path) # 基本属性 print(f格式: {img.format}) print(f尺寸: {img.size}) print(f模式: {img.mode}) # 图像转换 img_gray img.convert(L) # 转换为灰度图 img_resized img.resize((200, 200)) # 调整尺寸 # 图像增强 enhancer ImageEnhance.Contrast(img) img_contrast enhancer.enhance(1.5) # 增加对比度 # 应用滤镜 img_blur img.filter(ImageFilter.BLUR) img_sharp img.filter(ImageFilter.SHARPEN) return { original: img, gray: img_gray, resized: img_resized, contrast: img_contrast, blur: img_blur, sharp: img_sharp } # 测试PIL操作 results pil_basic_operations(test_images/sample_0.jpg) # 显示结果 fig, axes plt.subplots(2, 3, figsize(15, 10)) images list(results.values()) titles list(results.keys()) for i, (ax, img, title) in enumerate(zip(axes.flat, images, titles)): ax.imshow(img) ax.set_title(title) ax.axis(off) plt.tight_layout() plt.show()3.3 NumPy在图像处理中的应用NumPy是Python科学计算的基础库图像在NumPy中表示为多维数组便于进行数学运算。# 图像与NumPy数组的转换 def image_to_array_operations(image_path): 图像与NumPy数组的相互转换和操作 # 使用OpenCV读取为NumPy数组 img cv2.imread(image_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) print(f图像数组形状: {img_rgb.shape}) print(f数组数据类型: {img_rgb.dtype}) print(f像素值范围: {img_rgb.min()} - {img_rgb.max()}) # 数组操作示例 # 1. 裁剪图像 cropped img_rgb[50:150, 50:150] # 裁剪中心区域 # 2. 通道分离 r_channel img_rgb[:, :, 0] g_channel img_rgb[:, :, 1] b_channel img_rgb[:, :, 2] # 3. 亮度调整 brightened np.clip(img_rgb * 1.2, 0, 255).astype(np.uint8) # 4. 颜色通道交换 swapped img_rgb.copy() swapped[:, :, 0] img_rgb[:, :, 2] # R和B通道交换 swapped[:, :, 2] img_rgb[:, :, 0] return { original: img_rgb, cropped: cropped, red_channel: r_channel, green_channel: g_channel, blue_channel: b_channel, brightened: brightened, channel_swapped: swapped } # 测试NumPy操作 array_results image_to_array_operations(test_images/sample_0.jpg) # 可视化结果 fig, axes plt.subplots(2, 4, figsize(20, 10)) images list(array_results.values()) titles list(array_results.keys()) for i, (ax, img, title) in enumerate(zip(axes.flat, images, titles)): if len(img.shape) 2: # 单通道图像 ax.imshow(img, cmapgray) else: # 多通道图像 ax.imshow(img) ax.set_title(title) ax.axis(off) plt.tight_layout() plt.show()4. 图像预处理技术4.1 图像尺寸标准化在实际项目中经常需要将图像调整到统一尺寸以便处理。def standardize_image_size(image_path, target_size(224, 224)): 将图像调整到标准尺寸保持宽高比 img cv2.imread(image_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 获取原始尺寸 h, w img_rgb.shape[:2] target_h, target_w target_size # 计算缩放比例 scale min(target_w / w, target_h / h) new_w int(w * scale) new_h int(h * scale) # 调整尺寸 resized cv2.resize(img_rgb, (new_w, new_h)) # 创建目标尺寸的画布 canvas np.zeros((target_h, target_w, 3), dtypenp.uint8) # 将调整后的图像放在画布中央 start_x (target_w - new_w) // 2 start_y (target_h - new_h) // 2 canvas[start_y:start_ynew_h, start_x:start_xnew_w] resized return canvas # 测试尺寸标准化 standardized standardize_image_size(test_images/sample_0.jpg) plt.figure(figsize(10, 5)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(cv2.imread(test_images/sample_0.jpg), cv2.COLOR_BGR2RGB)) plt.title(原始图像) plt.axis(off) plt.subplot(1, 2, 2) plt.imshow(standardized) plt.title(标准化后 (224x224)) plt.axis(off) plt.show()4.2 图像增强技术图像增强可以改善图像质量为后续处理提供更好的输入。def image_augmentation(image_path): 图像增强技术示例 img cv2.imread(image_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) augmentations {} # 1. 旋转 rows, cols img_rgb.shape[:2] rotation_matrix cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1) # 旋转45度 rotated cv2.warpAffine(img_rgb, rotation_matrix, (cols, rows)) augmentations[rotated] rotated # 2. 平移 translation_matrix np.float32([[1, 0, 50], [0, 1, 30]]) # x方向平移50y方向平移30 translated cv2.warpAffine(img_rgb, translation_matrix, (cols, rows)) augmentations[translated] translated # 3. 翻转 flipped_h cv2.flip(img_rgb, 1) # 水平翻转 flipped_v cv2.flip(img_rgb, 0) # 垂直翻转 augmentations[flipped_horizontal] flipped_h augmentations[flipped_vertical] flipped_v # 4. 亮度调整 hsv cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV) hsv[:, :, 2] cv2.multiply(hsv[:, :, 2], 1.5) # 增加亮度 brightened cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) augmentations[brightened] brightened # 5. 添加噪声 noisy img_rgb.copy() noise np.random.normal(0, 25, img_rgb.shape).astype(np.uint8) noisy cv2.add(noisy, noise) augmentations[noisy] noisy return augmentations # 测试图像增强 augmentation_results image_augmentation(test_images/sample_0.jpg) # 可视化增强结果 fig, axes plt.subplots(2, 3, figsize(15, 10)) images [cv2.cvtColor(cv2.imread(test_images/sample_0.jpg), cv2.COLOR_BGR2RGB)] list(augmentation_results.values()) titles [原始图像] list(augmentation_results.keys()) for i, (ax, img, title) in enumerate(zip(axes.flat, images, titles)): ax.imshow(img) ax.set_title(title) ax.axis(off) plt.tight_layout() plt.show()5. 图像特征提取5.1 颜色特征提取颜色特征是图像分析中最基础的特征之一。def extract_color_features(image_path): 提取图像的颜色特征 img cv2.imread(image_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) features {} # 1. 颜色直方图 hist_r cv2.calcHist([img_rgb], [0], None, [256], [0, 256]) hist_g cv2.calcHist([img_rgb], [1], None, [256], [0, 256]) hist_b cv2.calcHist([img_rgb], [2], None, [256], [0, 256]) features[histogram_red] hist_r.flatten() features[histogram_green] hist_g.flatten() features[histogram_blue] hist_b.flatten() # 2. 颜色矩均值、标准差、偏度 mean np.mean(img_rgb, axis(0, 1)) std np.std(img_rgb, axis(0, 1)) features[color_mean] mean features[color_std] std # 3. 主色调提取使用K-means pixels img_rgb.reshape(-1, 3) pixels np.float32(pixels) # 使用K-means找到主要颜色 criteria (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0) _, labels, centers cv2.kmeans(pixels, 5, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) centers np.uint8(centers) dominant_colors centers[np.argsort(np.bincount(labels.flatten()))[::-1]] features[dominant_colors] dominant_colors return features # 测试颜色特征提取 color_features extract_color_features(test_images/sample_0.jpg) print(颜色特征提取结果:) print(fRGB均值: {color_features[color_mean]}) print(fRGB标准差: {color_features[color_std]}) print(f主色调: {color_features[dominant_colors]}) # 可视化颜色直方图 plt.figure(figsize(12, 4)) colors [red, green, blue] for i, color in enumerate(colors): plt.plot(color_features[fhistogram_{color}], colorcolor, labelcolor.upper()) plt.title(颜色直方图) plt.xlabel(像素值) plt.ylabel(频次) plt.legend() plt.show()5.2 纹理特征提取纹理特征描述图像表面的 patterns 和结构信息。def extract_texture_features(image_path): 提取图像的纹理特征 img cv2.imread(image_path) img_gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) features {} # 1. LBP局部二值模式特征 def calculate_lbp_pixel(gray_img, x, y): center gray_img[y, x] values [] # 3x3邻域 for dy in [-1, 0, 1]: for dx in [-1, 0, 1]: if dx 0 and dy 0: continue nx, ny x dx, y dy if 0 nx gray_img.shape[1] and 0 ny gray_img.shape[0]: values.append(1 if gray_img[ny, nx] center else 0) else: values.append(0) # 转换为二进制数 binary .join(str(v) for v in values) return int(binary, 2) # 计算整个图像的LBP lbp_result np.zeros_like(img_gray) for y in range(1, img_gray.shape[0]-1): for x in range(1, img_gray.shape[1]-1): lbp_result[y, x] calculate_lbp_pixel(img_gray, x, y) features[lbp_image] lbp_result features[lbp_histogram] cv2.calcHist([lbp_result], [0], None, [256], [0, 256]).flatten() # 2. 灰度共生矩阵GLCM特征 def calculate_glcm(gray_img, dx, dy): glcm np.zeros((256, 256), dtypenp.uint32) for y in range(gray_img.shape[0] - abs(dy)): for x in range(gray_img.shape[1] - abs(dx)): i gray_img[y, x] j gray_img[y dy, x dx] glcm[i, j] 1 return glcm glcm calculate_glcm(img_gray, 1, 0) # 水平方向 glcm_normalized glcm / glcm.sum() if glcm.sum() 0 else glcm # 计算GLCM特征 energy np.sum(glcm_normalized ** 2) contrast 0 for i in range(256): for j in range(256): contrast glcm_normalized[i, j] * (i - j) ** 2 features[glcm_energy] energy features[glcm_contrast] contrast return features # 测试纹理特征提取 texture_features extract_texture_features(test_images/sample_0.jpg) print(纹理特征提取结果:) print(fGLCM能量: {texture_features[glcm_energy]:.4f}) print(fGLCM对比度: {texture_features[glcm_contrast]:.4f}) # 可视化LBP结果 plt.figure(figsize(10, 5)) plt.subplot(1, 2, 1) plt.imshow(cv2.cvtColor(cv2.imread(test_images/sample_0.jpg), cv2.COLOR_BGR2GRAY), cmapgray) plt.title(原始灰度图) plt.axis(off) plt.subplot(1, 2, 2) plt.imshow(texture_features[lbp_image], cmapgray) plt.title(LBP特征图) plt.axis(off) plt.show()6. 完整的图像分类项目实战6.1 项目需求分析我们将实现一个简单的图像分类器用于区分不同类别的图像。这个项目将涵盖从数据准备到模型评估的完整流程。项目目标构建一个能够自动分类图像的机器学习模型支持多种图像类别识别提供完整的训练和预测流程6.2 数据集准备与预处理import os import numpy as np from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder from sklearn.svm import SVC from sklearn.metrics import classification_report, accuracy_score import joblib class ImageClassifier: def __init__(self, image_size(64, 64)): self.image_size image_size self.label_encoder LabelEncoder() self.model None self.feature_extractor None def load_and_preprocess_data(self, data_dir): 加载和预处理图像数据 images [] labels [] # 假设数据目录结构为data_dir/class_name/*.jpg for class_name in os.listdir(data_dir): class_dir os.path.join(data_dir, class_name) if not os.path.isdir(class_dir): continue for image_file in os.listdir(class_dir): if image_file.lower().endswith((.jpg, .jpeg, .png)): image_path os.path.join(class_dir, image_file) try: # 读取并预处理图像 img cv2.imread(image_path) if img is None: continue img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_resized cv2.resize(img_rgb, self.image_size) # 提取特征这里使用简单的颜色直方图 features self.extract_simple_features(img_resized) images.append(features) labels.append(class_name) except Exception as e: print(f处理图像 {image_path} 时出错: {e}) continue return np.array(images), np.array(labels) def extract_simple_features(self, image): 提取简单的图像特征颜色直方图 纹理特征 features [] # 颜色直方图特征 for i in range(3): # RGB三个通道 hist cv2.calcHist([image], [i], None, [16], [0, 256]) features.extend(hist.flatten()) # 转换为灰度图提取纹理特征 gray cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # LBP特征简化版 lbp_features self.simplified_lbp(gray) features.extend(lbp_features) return np.array(features) def simplified_lbp(self, gray_image): 简化的LBP特征提取 # 使用均匀模式LBP减少特征维度 lbp np.zeros_like(gray_image) for i in range(1, gray_image.shape[0]-1): for j in range(1, gray_image.shape[1]-1): center gray_image[i, j] binary_code 0 # 只考虑8个邻域点 neighbors [ gray_image[i-1, j-1], gray_image[i-1, j], gray_image[i-1, j1], gray_image[i, j-1], gray_image[i, j1], gray_image[i1, j-1], gray_image[i1, j], gray_image[i1, j1] ] for k, neighbor in enumerate(neighbors): if neighbor center: binary_code | (1 k) lbp[i, j] binary_code # 计算直方图作为特征 hist, _ np.histogram(lbp.flatten(), bins16, range(0, 255)) return hist / hist.sum() if hist.sum() 0 else hist def train(self, X, y): 训练分类模型 # 编码标签 y_encoded self.label_encoder.fit_transform(y) # 使用支持向量机分类器 self.model SVC(kernelrbf, probabilityTrue, random_state42) self.model.fit(X, y_encoded) print(模型训练完成!) def predict(self, X): 预测图像类别 if self.model is None: raise ValueError(模型尚未训练请先调用train方法) predictions self.model.predict(X) return self.label_encoder.inverse_transform(predictions) def predict_proba(self, X): 预测概率 if self.model is None: raise ValueError(模型尚未训练请先调用train方法) return self.model.predict_proba(X) def evaluate(self, X_test, y_test): 评估模型性能 y_pred self.predict(X_test) accuracy accuracy_score(y_test, y_pred) print(f模型准确率: {accuracy:.4f}) print(\n详细分类报告:) print(classification_report(y_test, y_pred)) return accuracy # 创建模拟数据集实际项目中替换为真实数据 def create_sample_dataset(): 创建示例数据集用于演示 os.makedirs(sample_data/cat, exist_okTrue) os.makedirs(sample_data/dog, exist_okTrue) # 创建简单的示例图像 for i in range(20): # 猫的图像偏蓝色调 cat_img np.random.randint(50, 150, (64, 64, 3), dtypenp.uint8) cat_img[:, :, 0] np.random.randint(100, 200, (64, 64)) # 更多蓝色 cv2.imwrite(fsample_data/cat/cat_{i}.jpg, cat_img) # 狗的的图像偏黄色调 dog_img np.random.randint(50, 150, (64, 64, 3), dtypenp.uint8) dog_img[:, :, 0] np.random.randint(50, 100, (64, 64)) # 较少蓝色 dog_img[:, :, 1] np.random.randint(100, 200, (64, 64)) # 更多绿色 cv2.imwrite(fsample_data/dog/dog_{i}.jpg, dog_img) # 创建示例数据集 create_sample_dataset() # 训练分类器 classifier ImageClassifier() print(加载和预处理数据...) X, y classifier.load_and_preprocess_data(sample_data) print(f数据形状: {X.shape}) print(f标签类别: {np.unique(y)}) # 划分训练测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) print(开始训练模型...) classifier.train(X_train, y_train) print(评估模型性能...) accuracy classifier.evaluate(X_test, y_test)6.3 模型优化与调参from sklearn.model_selection import GridSearchCV from sklearn.ensemble import RandomForestClassifier def optimize_model(X_train, y_train): 使用网格搜索优化模型参数 # 定义参数网格 param_grid { n_estimators: [50, 100, 200], max_depth: [10, 20, None], min_samples_split: [2, 5, 10], min_samples_leaf: [1, 2, 4] } # 使用随机森林 rf RandomForestClassifier(random_state42) # 网格搜索 grid_search GridSearchCV( rf, param_grid, cv5, scoringaccuracy, n_jobs-1, verbose1 ) grid_search.fit(X_train, y_train) print(最佳参数:, grid_search.best_params_) print(最佳分数:, grid_search.best_score_) return grid_search.best_estimator_ # 如果需要更优性能可以尝试优化 # best_model optimize_model(X_train, y_train)6.4 模型保存与加载def save_model(classifier, model_pathimage_classifier.pkl): 保存训练好的模型 model_data { model: classifier.model, label_encoder: classifier.label_encoder, image_size: classifier.image_size } joblib.dump(model_data, model_path) print(f模型已保存到: {model_path}) def load_model(model_pathimage_classifier.pkl): 加载已保存的模型 model_data joblib.load(model_path) classifier ImageClassifier(image_sizemodel_data[image_size]) classifier.model model_data[model] classifier.label_encoder model_data[label_encoder] print(模型加载成功!) return classifier # 保存模型 save_model(classifier) # 加载模型示例 # loaded_classifier load_model()7. 常见问题与解决方案7.1 图像读取失败问题问题现象cv2.imread()返回NonePIL.Image.open()抛出异常常见原因文件路径错误或文件不存在文件格式不受支持文件损坏权限问题解决方案def safe_image_read(image_path): 安全的图像读取函数包含错误处理 if not os.path.exists(image_path): raise FileNotFoundError(f图像文件不存在: {image_path}) # 尝试使用OpenCV读取 img cv2.imread(image_path) if img is not None: return img # 如果OpenCV失败尝试使用PIL try: pil_img Image.open(image_path) # 转换为OpenCV格式 img cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR) return img except Exception as e: raise ValueError(f无法读取图像文件 {image_path}: {e}) # 使用示例 try: img safe_image_read(test_images/sample_0.jpg) print(图像读取成功) except Exception as e: print(f读取失败: {e})7.2 内存不足问题问题现象处理大量图像时程序崩溃出现内存错误解决方案def process_large_dataset(image_paths, batch_size32): 分批处理大量图像避免内存溢出 results [] for i in range(0, len(image_paths), batch_size): batch_paths image_paths[i:i batch_size] batch_results [] for path in batch_paths: try: img safe_image_read(path) # 处理图像... features extract_color_features(path) # 使用前面定义的函数 batch_results.append(features) except Exception as e: print(f处理 {path} 时出错: {e}) batch_results.append(None) results.extend(batch_results) print(f已完成批次 {i//batch_size 1}/{(len(image_paths)-1)//batch_size 1}) # 强制垃圾回收 import gc gc.collect() return results7.3 图像质量不一致问题问题现象图像尺寸、格式、质量差异大影响模型训练效果解决方案def standardize_image_quality(image_path, target_size(224, 224), quality95): 标准化图像质量 img safe_image_read(image_path) # 调整尺寸 img_resized cv2.resize(img, target_size) # 增强对比度如果需要 lab cv2.cvtColor(img_resized, cv2.COLOR_BGR2LAB) l, a, b cv2.split(lab) # 应用CLAHE增强对比度 clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8, 8)) l clahe.apply(l) lab cv2.merge([l, a, b]) enhanced cv2.cvtColor(lab, cv2.COLOR_LAB2BGR) return enhanced # 批量标准化 def batch_standardize(input_dir, output_dir, target_size(224, 224)): 批量标准化图像质量 os.makedirs(output_dir, exist_okTrue) for filename in os.listdir(input_dir): if filename.lower().endswith((.jpg, .jpeg, .png)): input_path os.path.join(input_dir, filename) output_path os.path.join(output_dir, filename) try: standardized standardize_image_quality(input_path, target_size) cv2.imwrite(output_path, standardized) print(f已处理: {filename}) except Exception as e: print(f处理 {filename} 时出错: {e})8. 图像处理最佳实践8.1 代码组织与模块化良好的代码组织可以提高项目的可维护性和可扩展性。# image_utils.py - 图像处理工具函数 图像处理工具模块 import cv2 import numpy as np from PIL import Image import os class ImageProcessor: def __init__(self, configNone): self.config config or {} def load_image(self, path): 加载图像 return safe_image_read(path) def preprocess(self, image): 预处理图像 # 实现具体的预处理逻辑 pass def extract_features(self, image): 提取特征 # 实现特征提取逻辑 pass # config.py - 配置文件 项目配置文件 IMAGE_CONFIG { default_size: (224, 224), supported_formats: [.jpg, .jpeg, .png, .bmp], quality_threshold: 95 }