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

如何用Python准确计算相似卡牌图片特征并修正现有代码

问题背景与需求

我在目录/passes下有100张同一卡牌的相似图片,每张图片存在以下差异:

  • 部分卡牌带有绿色或红色泼溅痕迹,泼溅量各不相同
  • 部分卡牌存在破损,仅保留原卡牌的部分区域

需要实现:

  1. 计算每张卡牌的绿色泼溅占比、红色泼溅占比以及破损区域占比
  2. 将这三项特征存储至DataFrame中

现有代码存在两个核心问题:

  • 破损严重的卡牌被误判为带有泼溅色
  • 卡牌本身的红棕底色干扰了红色泼溅的计算

修正后的代码
import os
import pandas as pd
from PIL import Image
import numpy as np

def crop_card(image_path):
    image = Image.open(image_path).convert("RGB")
    width, height = image.size
    card_width = int(width * 0.8)
    card_height = int(height * 0.8)
    card_left = int((width - card_width) / 2)
    card_top = int((height - card_height) / 2)
    card_right = card_left + card_width
    card_bottom = card_top + card_height
    card_image = image.crop((card_left, card_top, card_right, card_bottom))
    return card_image, card_image.size[0], card_image.size[1]

def calculate_damage_percentage(card_image):
    # 转换为灰度图,通过过暗/过亮区域识别破损
    gray = np.array(card_image.convert("L"))
    dark_pixels = np.sum(gray < 50)
    bright_pixels = np.sum(gray > 200)
    total_pixels = gray.size
    damage_percent = ((dark_pixels + bright_pixels) / total_pixels) * 100
    return damage_percent

def color_splatter_percentage(card_image, color_mask_func):
    img_array = np.array(card_image)
    total_pixels = img_array.shape[0] * img_array.shape[1]
    
    # 生成颜色掩码与破损掩码
    color_mask = color_mask_func(img_array)
    gray = np.array(card_image.convert("L"))
    damage_mask = (gray < 50) | (gray > 200)
    
    # 仅统计非破损区域内的泼溅像素
    valid_mask = color_mask & ~damage_mask
    splatter_count = np.sum(valid_mask)
    
    # 基于有效卡牌区域计算占比(排除破损)
    valid_card_pixels = total_pixels - np.sum(damage_mask)
    return (splatter_count / valid_card_pixels) * 100 if valid_card_pixels > 0 else 0.0

def green_splatter_mask(img_array):
    r, g, b = img_array[:, :, 0], img_array[:, :, 1], img_array[:, :, 2]
    # 绿色泼溅判定:G远大于R/B,且亮度足够
    return (g > r + 50) & (g > b + 50) & (g > 100)

def red_splatter_mask(img_array):
    r, g, b = img_array[:, :, 0], img_array[:, :, 1], img_array[:, :, 2]
    # 红色泼溅判定:R远大于G/B,排除红棕底色(G/B不能过低)
    return (r > g + 80) & (r > b + 80) & (g > 40) & (b > 30) & (r > 150)

if __name__ == '__main__':
    image_dir = "/passes"
    results = []

    for filename in os.listdir(image_dir):
        if filename.endswith(".jpg"):
            image_path = os.path.join(image_dir, filename)
            card_image, _, _ = crop_card(image_path)
            
            damage_percent = calculate_damage_percentage(card_image)
            green_percent = color_splatter_percentage(card_image, green_splatter_mask)
            red_percent = color_splatter_percentage(card_image, red_splatter_mask)

            results.append({
                "image": filename,
                "damage_percent": round(damage_percent, 2),
                "green_splatter_percent": round(green_percent, 2),
                "red_splatter_percent": round(red_percent, 2)
            })

    df = pd.DataFrame(results)
    print(df)
    # 可选:保存结果到CSV
    # df.to_csv("card_splatter_features.csv", index=False)

关键改进说明
  • 破损区域精准识别:

    • 改用NumPy批量处理像素,效率提升数倍
    • 通过灰度值的过暗(<50)和过亮(>200)区域定义破损,避免将破损误判为泼溅
    • 计算泼溅占比时,仅基于有效卡牌区域(排除破损部分)统计,结果更贴合实际泼溅比例
  • 红色泼溅抗干扰优化:

    • 增加g > 40和b > 30的限制,排除卡牌本身的红棕底色(底色的G/B值通常较低但不会极低)
    • 加大R与G/B的差值阈值(r > g + 80),确保识别的是鲜艳的红色泼溅而非底色
  • 绿色泼溅准确性提升:

    • 增加亮度限制(g > 100),排除暗部的误判
    • 加大G与R/B的差值(g > r + 50),确保识别的是明显的绿色泼溅

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:25:47