You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

问题根源与修复方案

核心问题

  1. HSV颜色范围完全错误:手动设置的[(75, 90, 160), (95, 255, 255)]和目标色#c7d296的真实HSV值不匹配,导致cv2.inRange生成的mask全为黑色,最终所有区域都被替换成白色。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:23:18