Python脚本保留指定颜色区域异常:输出全白问题排查
问题
我有29000张JPG图片,想仅保留图片中#c7d296颜色区域,其余区域填充为白色。因为数量太多没法用Photoshop,所以写了Python脚本,但运行后输出全是白色,没保留目标颜色区域,求排查问题:
import cv2 import os import numpy as np import keyboard def keep_color_only(input_file, output_directory, color_range, fuzziness): try: # Read the input image img = cv2.imread(input_file) # Convert image to HSV color space hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Define lower and upper bounds for the color range lower_color = np.array(color_range[0]) upper_color = np.array(color_range[1]) # Threshold the HSV image to get only desired colors mask = cv2.inRange(hsv, lower_color, upper_color) # Invert the mask mask_inv = cv2.bitwise_not(mask) # Create a white background image white_background = np.full_like(img, (255, 255, 255), dtype=np.uint8) # Combine the original image with the white background using the mask result = cv2.bitwise_and(img, img, mask=mask) result = cv2.bitwise_or(result, white_background, mask=mask_inv) # Output file path output_file = os.path.join(output_directory, os.path.basename(input_file)) # Save the resulting image cv2.imwrite(output_file, result) except Exception as e: print(f"Error processing {input_file}: {str(e)}") def process_images(input_directory, output_directory, color_range, fuzziness): # Create output directory if it doesn't exist if not os.path.exists(output_directory): os.makedirs(output_directory) # Process each JPG file in the input directory for filename in os.listdir(input_directory): if filename.lower().endswith('.jpg'): input_file = os.path.join(input_directory, filename) keep_color_only(input_file, output_directory, color_range, fuzziness) # Check for 'F7' key press to stop the process if keyboard.is_pressed('F7'): print("Process stopped by user.") return def main(): input_directory = r'E:\Desktop\inf\CROP' output_directory = r'E:\Desktop\inf\OUTPUT' # Color range in HSV format color_range = [(75, 90, 160), (95, 255, 255)] # Lower and upper bounds for HSV color range fuzziness = 80 process_images(input_directory, output_directory, color_range, fuzziness) print("Color removal completed.") if __name__ == "__main__": main()
注:颜色范围的fuzziness需设置为80。
问题根源与修复方案
核心问题
- HSV颜色范围完全错误:手动设置的
[(75, 90, 160), (95, 255, 255)]和目标色#c7d296的真实HSV值不匹配,导致cv2.inRange生成的mask全为黑色,最终所有区域都被替换成白色。 - fuzziness参数未被使用:标注了需要设置模糊度80,但脚本完全没用到这个参数来扩展颜色匹配范围,无法覆盖目标色的色差。
修复步骤
1. 计算目标色的HSV值
把#c7d296的RGB值(199, 210, 150)转换成OpenCV的HSV格式(OpenCV中H范围是0-179,S/V是0-255),目标色的HSV约为(70, 33, 82)。
2. 用fuzziness扩展颜色范围
基于目标HSV值,用fuzziness=80计算上下界:
- H通道:处理环形范围的边界溢出(比如H-80为负时加180)
- S/V通道:限制在0-255之间
3. 修改脚本代码
替换main函数中的颜色范围设置逻辑,同时让fuzziness生效:
def main(): input_directory = r'E:\Desktop\inf\CROP' output_directory = r'E:\Desktop\inf\OUTPUT' # 目标颜色#c7d296的RGB值(注意OpenCV是BGR顺序) target_bgr = np.array([150, 210, 199], dtype=np.uint8).reshape(1, 1, 3) target_hsv = cv2.cvtColor(target_bgr, cv2.COLOR_BGR2HSV)[0][0] fuzziness = 80 # 计算HSV上下界,处理H通道的环形特性 lower_h = (target_hsv[0] - fuzziness) % 180 upper_h = (target_hsv[0] + fuzziness) % 180 lower_s = max(0, target_hsv[1] - fuzziness) upper_s = min(255, target_hsv[1] + fuzziness) lower_v = max(0, target_hsv[2] - fuzziness) upper_v = min(255, target_hsv[2] + fuzziness) # 处理H范围跨0度的情况 if lower_h > upper_h: color_range = [(lower_h, lower_s, lower_v), (179, upper_s, upper_v), (0, lower_s, lower_v), (upper_h, upper_s, upper_v)] else: color_range = [(lower_h, lower_s, lower_v), (upper_h, upper_s, upper_v)] process_images(input_directory, output_directory, color_range, fuzziness) print("Color removal completed.")
同时修改keep_color_only函数中的mask生成逻辑,处理H范围跨0的情况:
def keep_color_only(input_file, output_directory, color_range, fuzziness): try: img = cv2.imread(input_file) if img is None: print(f"Failed to read {input_file}") return hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 生成mask,处理H范围跨0的情况 if len(color_range) == 4: mask1 = cv2.inRange(hsv, np.array(color_range[0]), np.array(color_range[1])) mask2 = cv2.inRange(hsv, np.array(color_range[2]), np.array(color_range[3])) mask = cv2.bitwise_or(mask1, mask2) else: lower_color = np.array(color_range[0]) upper_color = np.array(color_range[1]) mask = cv2.inRange(hsv, lower_color, upper_color) mask_inv = cv2.bitwise_not(mask) white_background = np.full_like(img, (255, 255, 255), dtype=np.uint8) result = cv2.bitwise_and(img, img, mask=mask) result = cv2.bitwise_or(result, white_background, mask=mask_inv) output_file = os.path.join(output_directory, os.path.basename(input_file)) cv2.imwrite(output_file, result) except Exception as e: print(f"Error processing {input_file}: {str(e)}")
说明
- 用OpenCV自带的转换函数计算目标色HSV,避免手动计算出错
- 处理H通道的环形特性,确保颜色范围不会遗漏跨0度的情况
- 让fuzziness参数真正参与颜色范围的扩展,符合需求
内容的提问来源于stack exchange,提问作者Pubg Mobile
相关产品推荐
相关产品推荐

