#!/usr/bin/env python3 # -*- coding: utf-8 -*- import cv2 import numpy as np import os import argparse import matplotlib.pyplot as plt def analyze_yellow_area_ratio(image_path, debug=False, save_result=False): """ 专门针对黄色区域的分析算法 参数: image_path: 图片路径 debug: 是否显示处理过程中的图像,用于调试 save_result: 是否保存处理结果图像 返回: yellow_ratio: 黄色区域占比(0-1之间的浮点数) """ # 读取图片 img = cv2.imread(image_path) if img is None: raise ValueError(f"无法读取图片: {image_path}") # 获取图片文件名(不带路径和扩展名) filename = os.path.splitext(os.path.basename(image_path))[0] # 转换为HSV色彩空间(更适合颜色分割) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 提取图像的各个通道 h, s, v = cv2.split(hsv) # 黄色在HSV中的范围:色调约为20-30度(OpenCV中为10-30) # 黄色通常有较高的饱和度和亮度 yellow_hue_lower = np.array([20, 100, 100]) yellow_hue_upper = np.array([40, 255, 255]) # 创建黄色区域掩码 yellow_mask = cv2.inRange(hsv, yellow_hue_lower, yellow_hue_upper) # 应用形态学操作 kernel = np.ones((5, 5), np.uint8) yellow_mask = cv2.morphologyEx(yellow_mask, cv2.MORPH_OPEN, kernel) yellow_mask = cv2.morphologyEx(yellow_mask, cv2.MORPH_CLOSE, kernel) # 使用连通区域分析,去除小的噪点区域 num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(yellow_mask, connectivity=8) # 过滤小的连通区域 min_size = 500 # 最小连通区域大小 filtered_yellow_mask = np.zeros_like(yellow_mask) # 从索引1开始,因为0是背景 for i in range(1, num_labels): if stats[i, cv2.CC_STAT_AREA] >= min_size: filtered_yellow_mask[labels == i] = 255 # 计算黄色区域占比 height, width = yellow_mask.shape total_pixels = height * width yellow_pixels = np.sum(filtered_yellow_mask == 255) yellow_ratio = yellow_pixels / total_pixels # 在原图上标记黄色区域 result = img.copy() overlay = img.copy() overlay[filtered_yellow_mask > 0] = [0, 165, 255] # 用橙色标记黄色区域 cv2.addWeighted(overlay, 0.4, img, 0.6, 0, result) # 半透明效果 # 显示检测结果信息 cv2.putText(result, f"Yellow Ratio: {yellow_ratio:.2%}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 165, 255), 2) # 调试模式:显示处理过程图像 if debug: plt.figure(figsize=(15, 10)) plt.subplot(231) plt.title("Original Image") plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.subplot(232) plt.title("Hue Channel") plt.imshow(h, cmap='hsv') plt.subplot(233) plt.title("Saturation Channel") plt.imshow(s, cmap='gray') plt.subplot(234) plt.title("Initial Yellow Mask") plt.imshow(yellow_mask, cmap='gray') plt.subplot(235) plt.title("Filtered Yellow Mask") plt.imshow(filtered_yellow_mask, cmap='gray') plt.subplot(236) plt.title("Yellow Detection Result") plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)) plt.tight_layout() plt.show() # 保存结果 if save_result: result_dir = "results" os.makedirs(result_dir, exist_ok=True) output_path = os.path.join(result_dir, f"{filename}_yellow_area_result.jpg") cv2.imwrite(output_path, result) print(f"结果已保存至: {output_path}") return yellow_ratio def main(): parser = argparse.ArgumentParser(description='分析图片中黄色区域占比') parser.add_argument('--image_path', default='./image_20250525_090252.png', type=str, help='图片路径') parser.add_argument('--debug', default=False, action='store_true', help='显示处理过程图像') parser.add_argument('--save', action='store_true', help='保存处理结果图像') args = parser.parse_args() try: yellow_ratio = analyze_yellow_area_ratio(args.image_path, args.debug, args.save) print(f"黄色区域占比: {yellow_ratio:.2%}") except Exception as e: print(f"错误: {e}") if __name__ == "__main__": main()