【PAT_1054】The Dominant Color

本文介绍了一种算法,用于从给定的图像中找出占总面积一半以上的严格主导颜色。通过统计输入颜色的出现次数,该算法能够在复杂的数据集中快速定位到主导颜色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

在计算机内存的幕后,颜色总是被称为每个像素的一系列24位信息。 在图像中,具有最大比例区域的颜色称为主色。 严格主导的颜色占总面积的一半以上。 现在给出分辨率M乘N的图像(例如,800x600),指出严格主导的颜色。其实就是找出一堆数中占一半以上的数字

输入

M(<=800):每一行有多少个像素
N(<=600)有多少行
N行数字,每行M个数字(数字范围为 [0, 224))

输出

输出最多的数字。

解题思路

因为主导数字占总数字数的一半以上,所以对输入的数字统计出现次数,碰到相同的次数+1,不相同次数-1,当次数为0时,统计数字应该为当前数字。

代码


#include<stdio.h>
#include<iostream>
using namespace std;

int main() {
	int m, n;
	cin >> m >> n;
	int temp,res=0,counts=0;
	for (int i = 0; i <m*n; i++) {
		    scanf("%d", &temp);
        if(counts==0){
            res = temp;
        }else if(counts>m*n/2)break;
        if(temp==res)counts++;
        else counts--;
	}
	cout<<res<<endl;
	return 0;
}


import os import numpy as np import shutil import matplotlib.pyplot as plt from PIL import Image, ImageDraw, ImageFont from tqdm import tqdm import math import json import random import string import colorsys import cv2 # 添加OpenCV用于更好的颜色处理 # 优化的颜色类别及其HSV范围 COLOR_CATEGORIES = [ {"name": "红色", "h_range": [(0, 10), (350, 360)], "s_min": 40, "v_min": 40}, # 红色范围优化 {"name": "橙色", "h_range": [(11, 25)], "s_min": 40, "v_min": 40}, {"name": "黄色", "h_range": [(26, 45)], "s_min": 40, "v_min": 40}, {"name": "绿色", "h_range": [(46, 160)], "s_min": 40, "v_min": 40}, # 扩大绿色范围 {"name": "青色", "h_range": [(161, 200)], "s_min": 40, "v_min": 40}, {"name": "蓝色", "h_range": [(201, 270)], "s_min": 40, "v_min": 40}, # 扩大蓝色范围 {"name": "紫色", "h_range": [(271, 310)], "s_min": 40, "v_min": 40}, # 缩小紫色范围 {"name": "粉色", "h_range": [(311, 349)], "s_min": 30, "v_min": 40}, # 中性色放在最后,避免过早匹配 {"name": "白色", "s_max": 30, "v_min": 220}, # 提高白色阈值 {"name": "银灰色", "s_max": 30, "v_range": (180, 229)}, {"name": "灰色", "s_max": 20, "v_range": (100, 179)}, # 限制灰色范围 {"name": "黑色", "v_max": 50}, # 提高黑色阈值 {"name": "棕色", "h_range": [(10, 45)], "s_min": 20, "v_range": (30, 180)} ] # 参考颜色(用于可视化) REFERENCE_COLORS = { "红色": (255, 0, 0), "橙色": (255, 165, 0), "黄色": (255, 255, 0), "绿色": (0, 128, 0), "青色": (0, 255, 255), "蓝色": (0, 0, 255), "紫色": (128, 0, 128), "粉色": (255, 192, 203), "白色": (255, 255, 255), "银灰色": (192, 192, 192), "灰色": (128, 128, 128), "黑色": (0, 0, 0), "棕色": (165, 42, 42), "其他": (200, 200, 200) } # 中心区域大小(宽高的比例) CENTER_REGION_RATIO = 1 / 3 # 颜色显著性阈值(低于此值视为不显著) COLOR_SIGNIFICANCE_THRESHOLD = 8.0 # 降低阈值 def enhance_color_contrast(image): """增强图像颜色对比度""" # 转换为LAB颜色空间 lab = cv2.cvtColor(image, cv2.COLOR_RGB2LAB) # 分离通道 l, a, b = cv2.split(lab) # 应用CLAHE增强对比度 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) l = clahe.apply(l) # 合并通道并转换回RGB enhanced_lab = cv2.merge((l, a, b)) enhanced_image = cv2.cvtColor(enhanced_lab, cv2.COLOR_LAB2RGB) return enhanced_image def rgb_to_hsv(r, g, b): """将RGB转换为HSV(0-360, 0-100, 0-100)""" r, g, b = r / 255.0, g / 255.0, b / 255.0 h, s, v = colorsys.rgb_to_hsv(r, g, b) h = h * 360 s = s * 100 v = v * 100 return h, s, v def get_color_percentages(img): """计算中心区域内每种颜色的像素比例(使用OpenCV优化)""" try: # 转换为numpy数组 img_array = np.array(img) # 应用颜色增强 img_array = enhance_color_contrast(img_array) # 计算中心区域 height, width, _ = img_array.shape center_h = int(height / 2) center_w = int(width / 2) region_h = int(height * CENTER_REGION_RATIO) region_w = int(width * CENTER_REGION_RATIO) # 计算中心区域边界 top = max(0, center_h - region_h // 2) bottom = min(height, center_h + region_h // 2) left = max(0, center_w - region_w // 2) right = min(width, center_w + region_w // 2) # 确保区域有效 if bottom <= top or right <= left: return {"其他": 100}, (0, 0, 0, 0) # 裁剪中心区域 center_region = img_array[top:bottom, left:right] total_pixels = center_region.shape[0] * center_region.shape[1] if total_pixels == 0: return {"其他": 100}, (top, left, bottom, right) # 初始化颜色计数 color_counts = {color["name"]: 0 for color in COLOR_CATEGORIES} color_counts["其他"] = 0 # 将图像转换为HSV hsv_image = np.zeros_like(center_region, dtype=np.float32) for y in range(center_region.shape[0]): for x in range(center_region.shape[1]): r, g, b = center_region[y, x] h, s, v = rgb_to_hsv(r, g, b) hsv_image[y, x] = [h, s, v] # 创建颜色掩码 masks = {} for color in COLOR_CATEGORIES: mask = np.ones((center_region.shape[0], center_region.shape[1]), dtype=bool) # 处理色相范围 if "h_range" in color: h_mask = np.zeros_like(mask, dtype=bool) for h_min, h_max in color["h_range"]: # 处理色相环绕 if h_min > h_max: h_mask |= (hsv_image[:, :, 0] >= h_min) | (hsv_image[:, :, 0] <= h_max) else: h_mask |= (hsv_image[:, :, 0] >= h_min) & (hsv_image[:, :, 0] <= h_max) mask &= h_mask # 处理饱和度 if "s_min" in color: mask &= (hsv_image[:, :, 1] >= color["s_min"]) if "s_max" in color: mask &= (hsv_image[:, :, 1] <= color["s_max"]) # 处理明度 if "v_min" in color: mask &= (hsv_image[:, :, 2] >= color["v_min"]) if "v_max" in color: mask &= (hsv_image[:, :, 2] <= color["v_max"]) if "v_range" in color: v_min, v_max = color["v_range"] mask &= (hsv_image[:, :, 2] >= v_min) & (hsv_image[:, :, 2] <= v_max) masks[color["name"]] = mask # 计算每个颜色的像素数(按优先级顺序) # 首先处理彩色,然后处理中性色 all_masks = np.zeros_like(mask, dtype=bool) color_order = ["红色", "橙色", "黄色", "绿色", "青色", "蓝色", "紫色", "粉色", "棕色", "白色", "银灰色", "灰色", "黑色"] for color_name in color_order: if color_name in masks: # 减去已分配的区域 current_mask = masks[color_name] & ~all_masks color_counts[color_name] = np.count_nonzero(current_mask) all_masks |= current_mask # 计算剩余像素为"其他" color_counts["其他"] = np.count_nonzero(~all_masks) # 转换为百分比 color_percentages = { color: (count / total_pixels) * 100 for color, count in color_counts.items() } return color_percentages, (top, left, bottom, right) except Exception as e: print(f"计算颜色比例时出错: {str(e)}") return {"其他": 100}, (0, 0, 0, 0) def get_dominant_color(color_percentages): """获取中心区域的主导颜色,优先非中性色""" try: # 排除中性色和其他类别 non_neutral_colors = {k: v for k, v in color_percentages.items() if k not in ["白色", "银灰色", "灰色", "黑色", "其他"]} # 如果有显著的非中性色,使用其中最大的 if non_neutral_colors: max_non_neutral = max(non_neutral_colors.items(), key=lambda x: x[1]) if max_non_neutral[1] >= COLOR_SIGNIFICANCE_THRESHOLD: return max_non_neutral[0] # 否则选择比例最高的颜色(包括中性色) all_colors = {k: v for k, v in color_percentages.items() if k != "其他"} if all_colors: return max(all_colors.items(), key=lambda x: x[1])[0] return "其他" except: return "其他" def mark_center_region(img, region_coords, dominant_color, color_percent): """在图像上标记中心区域和主导颜色信息""" try: draw_img = img.copy() draw = ImageDraw.Draw(draw_img) # 绘制矩形标记中心区域 top, left, bottom, right = region_coords draw.rectangle([left, top, right, bottom], outline="red", width=3) # 添加文本标签 label = f"主导颜色: {dominant_color} ({color_percent:.1f}%)" try: # 尝试加载字体 try: font = ImageFont.truetype("arial.ttf", 20) except: font = ImageFont.truetype("DejaVuSans.ttf", 20) text_bbox = draw.textbbox((0, 0), label, font=font) text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] except: # 回退到简单估算 text_width = len(label) * 10 text_height = 20 text_x = left + 10 text_y = top - text_height - 10 if top > text_height + 10 else top + 10 # 绘制文本背景 draw.rectangle( [ text_x - 5, text_y - 5, text_x + text_width + 5, text_y + text_height + 5 ], fill="black" ) # 添加文本 draw.text((text_x, text_y), label, fill="red", font=font if 'font' in locals() else None) return draw_img except: return img.copy() def analyze_image_color(img_path): """分析图片中心区域颜色""" try: img = Image.open(img_path) if img.mode != 'RGB': img = img.convert('RGB') # 分析中心区域颜色 color_percentages, region_coords = get_color_percentages(img) # 获取主导颜色 dominant_color = get_dominant_color(color_percentages) color_percent = color_percentages.get(dominant_color, 0) # 标记中心区域 marked_img = mark_center_region(img, region_coords, dominant_color, color_percent) # 保存调试信息 debug_info = { "filename": os.path.basename(img_path), "color_percentages": color_percentages, "dominant_color": dominant_color, "region": region_coords } return { "dominant_color": dominant_color, "color_percentages": color_percentages, "marked_img": marked_img, "region_coords": region_coords, "color_percent": color_percent, "debug_info": debug_info } except Exception as e: print(f"处理图片 {img_path} 时出错: {str(e)}") return None def generate_random_prefix(length=8): """生成随机前缀,避免文件名冲突""" return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) def sort_images_by_color(folder_path): """按中心区域主导颜色排序图片,优先非中性色,直接在原文件上重命名""" try: valid_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp'] image_files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f)) and os.path.splitext(f)[1].lower() in valid_extensions] if not image_files: print("文件夹中没有图片文件") return [] print(f"找到 {len(image_files)} 张图片,分析中心区域颜色...") # 存储图片分析结果和调试信息 image_data = [] debug_info_list = [] failed_files = [] # 分析每张图片 for img_file in tqdm(image_files, desc="分析图片"): img_path = os.path.join(folder_path, img_file) try: analysis = analyze_image_color(img_path) if analysis is None: failed_files.append(img_file) continue # 保存标记图像 marked_img_path = os.path.join(folder_path, f"debug_marked_{img_file}") analysis["marked_img"].save(marked_img_path) # 保存调试信息 debug_info_list.append(analysis["debug_info"]) image_data.append({ "filename": img_file, "path": img_path, "analysis": analysis, "extension": os.path.splitext(img_file)[1] }) except Exception as e: print(f"分析图片 {img_file} 时出错: {str(e)}") failed_files.append(img_file) if not image_data: print("没有成功分析任何图片") return [] if failed_files: print(f"未能分析 {len(failed_files)} 张图片") # 保存调试信息到文件 debug_path = os.path.join(folder_path, "color_debug_info.json") with open(debug_path, "w", encoding="utf-8") as f: json.dump(debug_info_list, f, indent=2, ensure_ascii=False) # 按颜色类别排序 color_priority = { "红色": 1, "橙色": 2, "黄色": 3, "绿色": 4, "青色": 5, "蓝色": 6, "紫色": 7, "粉色": 8, "棕色": 9, "白色": 10, "银灰色": 11, "灰色": 12, "黑色": 13, "其他": 14 } image_data.sort(key=lambda x: color_priority.get(x["analysis"]["dominant_color"], 14)) # 生成随机前缀,避免文件名冲突 random_prefix = generate_random_prefix() # 第一步:使用随机前缀重命名所有文件,避免冲突 for img_info in image_data: old_path = img_info["path"] temp_path = os.path.join(folder_path, f"{random_prefix}_{img_info['filename']}") os.rename(old_path, temp_path) img_info["temp_path"] = temp_path # 第二步:重命名为最终文件名 print("\n排序完成!正在重命名图片...") for idx, img_info in enumerate(tqdm(image_data, desc="重命名图片")): analysis = img_info["analysis"] dominant_color = analysis["dominant_color"] color_percent = analysis["color_percent"] # 生成新文件名(避免非法字符) safe_color_name = dominant_color.replace("/", "_").replace("\\", "_") new_filename = (f"{idx + 1:04d}_{safe_color_name}_" f"P{color_percent:.1f}%" f"{img_info['extension']}") new_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(img_info["temp_path"], new_path) # 更新文件信息 img_info["filename"] = new_filename img_info["path"] = new_path print(f"\n排序完成!所有图片已按中心区域颜色重命名") return image_data except Exception as e: print(f"排序图片时出错: {str(e)}") return [] def create_color_histogram(color_percentages, save_path): """创建颜色比例直方图""" try: # 过滤掉比例小于1%的颜色 filtered = {k: v for k, v in color_percentages.items() if v >= 1.0} if not filtered: return False # 获取颜色对应的RGB值 colors = [REFERENCE_COLORS.get(color, (200, 200, 200)) for color in filtered.keys()] colors_normalized = [tuple(c / 255 for c in color) for color in colors] # 创建直方图 plt.figure(figsize=(12, 6)) bars = plt.bar(filtered.keys(), filtered.values(), color=colors_normalized) plt.title('中心区域颜色分布', fontsize=14) plt.xlabel('颜色类别', fontsize=12) plt.ylabel('像素比例 (%)', fontsize=12) plt.xticks(rotation=45, ha='right') plt.grid(axis='y', linestyle='--', alpha=0.7) # 在柱子上添加数值标签 for bar in bars: height = bar.get_height() if height > 5: # 只在大干5%的柱子上显示标签 plt.text(bar.get_x() + bar.get_width() / 2., height, f'{height:.1f}%', ha='center', va='bottom', fontsize=9) # 添加显著性阈值线 plt.axhline(y=COLOR_SIGNIFICANCE_THRESHOLD, color='r', linestyle='--', alpha=0.7) plt.text(len(filtered) - 0.5, COLOR_SIGNIFICANCE_THRESHOLD + 1, f'显著性阈值 ({COLOR_SIGNIFICANCE_THRESHOLD}%)', color='r', fontsize=9, ha='right') plt.tight_layout() plt.savefig(save_path, dpi=120) plt.close() return True except Exception as e: print(f"创建直方图时出错: {str(e)}") return False def create_analysis_report(sorted_images, folder_path): """创建详细分析报告""" try: if not sorted_images: print("没有可用的图片数据生成报告") return # 1. 整体主导颜色分布 color_counts = {} for img in sorted_images: color = img["analysis"]["dominant_color"] color_counts[color] = color_counts.get(color, 0) + 1 # 创建主导颜色分布图 if color_counts: plt.figure(figsize=(12, 6)) colors = [REFERENCE_COLORS.get(color, (200, 200, 200)) for color in color_counts.keys()] colors_normalized = [tuple(c / 255 for c in color) for color in colors] plt.bar(list(color_counts.keys()), list(color_counts.values()), color=colors_normalized) plt.title('图片主导颜色分布', fontsize=14) plt.xlabel('颜色类别', fontsize=12) plt.ylabel('图片数量', fontsize=12) plt.xticks(rotation=45, ha='right') plt.grid(axis='y', linestyle='--', alpha=0.7) plt.tight_layout() plt.savefig(os.path.join(folder_path, 'dominant_color_distribution.jpg'), dpi=120) plt.close() # 2. 颜色优先级分布 priority_colors = ["红色", "橙色", "黄色", "绿色", "青色", "蓝色", "紫色", "粉色", "棕色", "白色", "银灰色", "灰色", "黑色", "其他"] valid_priority_colors = [color for color in priority_colors if color in color_counts] if valid_priority_colors: priority_counts = [color_counts[color] for color in valid_priority_colors] plt.figure(figsize=(14, 6)) bar_colors = [tuple(c / 255 for c in REFERENCE_COLORS[color]) for color in valid_priority_colors] plt.bar(valid_priority_colors, priority_counts, color=bar_colors) plt.title('颜色分布', fontsize=14) plt.xlabel('颜色类别', fontsize=12) plt.ylabel('图片数量', fontsize=12) plt.tight_layout() plt.savefig(os.path.join(folder_path, 'color_distribution.jpg'), dpi=120) plt.close() # 3. 创建示例图片网格 sample_size = min(12, len(sorted_images)) if sample_size > 0: sample_indices = np.linspace(0, len(sorted_images) - 1, sample_size, dtype=int) sample_images = [sorted_images[i] for i in sample_indices] plt.figure(figsize=(14, 10)) plt.suptitle('图片中心区域颜色分析示例', fontsize=16) cols = 4 rows = math.ceil(sample_size / cols) for i, img_info in enumerate(sample_images): plt.subplot(rows, cols, i + 1) try: # 添加标题 dominant_color = img_info["analysis"]["dominant_color"] color_percent = img_info["analysis"]["color_percent"] title = f"{dominant_color} ({color_percent:.1f}%)\n{img_info['filename']}" plt.title(title, fontsize=9) # 尝试加载原始图片 try: img = Image.open(img_info["path"]) img.thumbnail((200, 200)) plt.imshow(img) except: # 显示占位符 plt.imshow(np.zeros((200, 200, 3), dtype=np.uint8)) except: plt.imshow(np.zeros((200, 200, 3), dtype=np.uint8)) plt.title("图片加载失败", fontsize=9) plt.axis('off') plt.tight_layout(rect=[0, 0, 1, 0.96]) plt.savefig(os.path.join(folder_path, 'color_analysis_examples.jpg'), dpi=120) plt.close() # 4. 为每张图片创建颜色直方图 print("为每张图片生成颜色直方图...") for img_info in tqdm(sorted_images, desc="生成直方图"): base_name = os.path.splitext(img_info["filename"])[0] hist_path = os.path.join(folder_path, f"hist_{base_name}.jpg") create_color_histogram(img_info["analysis"]["color_percentages"], hist_path) # 5. 创建文本报告 report_path = os.path.join(folder_path, "color_analysis_report.txt") with open(report_path, "w", encoding="utf-8") as f: f.write("=" * 80 + "\n") f.write("图片中心区域颜色分析报告\n") f.write("=" * 80 + "\n\n") f.write(f"分析图片总数: {len(sorted_images)}\n") f.write(f"中心区域比例: {CENTER_REGION_RATIO * 100:.0f}%\n") f.write(f"颜色显著性阈值: {COLOR_SIGNIFICANCE_THRESHOLD}%\n\n") f.write("-" * 80 + "\n") f.write("颜色分布统计:\n") f.write("-" * 80 + "\n") for color, count in sorted(color_counts.items(), key=lambda x: x[1], reverse=True): f.write(f"{color}: {count}张 ({count / len(sorted_images) * 100:.1f}%)\n") f.write("\n" + "-" * 80 + "\n") f.write("图片详细信息:\n") f.write("-" * 80 + "\n") for img_info in sorted_images: analysis = img_info["analysis"] dominant_color = analysis["dominant_color"] color_percent = analysis["color_percent"] f.write(f"文件名: {img_info['filename']}\n") f.write(f"主导颜色: {dominant_color} ({color_percent:.1f}%)\n") # 列出主要颜色 sorted_colors = sorted( analysis["color_percentages"].items(), key=lambda x: x[1], reverse=True ) f.write("所有颜色比例:\n") for color, percent in sorted_colors: if percent >= 1.0: # 只显示占比超过1%的颜色 significance = "(显著)" if percent >= COLOR_SIGNIFICANCE_THRESHOLD else "" f.write(f" - {color}: {percent:.1f}% {significance}\n") f.write("\n") # 6. 保存JSON格式数据 json_path = os.path.join(folder_path, "color_data.json") with open(json_path, "w", encoding="utf-8") as f: json_data = [] for img_info in sorted_images: data = { "filename": img_info["filename"], "dominant_color": img_info["analysis"]["dominant_color"], "color_percent": img_info["analysis"]["color_percent"], "color_percentages": img_info["analysis"]["color_percentages"] } json_data.append(data) json.dump(json_data, f, indent=2, ensure_ascii=False) print(f"\n分析报告已保存到: {folder_path}") return True except Exception as e: print(f"创建分析报告时出错: {str(e)}") return False def main(): try: # 输入文件夹路径 folder_path = input("请输入图片文件夹路径: ").strip() if not os.path.exists(folder_path): print("错误:指定的路径不存在") return if not os.path.isdir(folder_path): print("错误:指定的路径不是文件夹") return # 安装OpenCV如果尚未安装 try: import cv2 except ImportError: print("安装OpenCV以增强颜色分析...") import subprocess subprocess.run(['pip', 'install', 'opencv-python'], check=True) import cv2 # 排序图片 sorted_images = sort_images_by_color(folder_path) if not sorted_images: print("没有图片可供生成报告") return # 创建分析报告 create_analysis_report(sorted_images, folder_path) print("\n所有操作已完成!") print(f"排序后的图片已保存在: {folder_path}") print("生成的分析报告包括:") print("- dominant_color_distribution.jpg: 主导颜色分布图") print("- color_distribution.jpg: 颜色分布图") print("- color_analysis_examples.jpg: 分析示例图") print("- hist_*.jpg: 每张图片的颜色直方图") print("- color_analysis_report.txt: 详细文本报告") print("- color_data.json: JSON格式颜色数据") print("- color_debug_info.json: 调试信息") except Exception as e: print(f"程序运行时出错: {str(e)}") if __name__ == "__main__": # 检查并安装必要的依赖 print("=" * 60) print("图片中心区域颜色分析工具") print("=" * 60) print("正在检查依赖...") dependencies = { 'numpy': 'numpy', 'tqdm': 'tqdm', 'PIL': 'Pillow', 'matplotlib': 'matplotlib', 'opencv-python': 'opencv-python' } missing_deps = [] for lib, pkg in dependencies.items(): try: __import__(lib.split('-')[0]) # 处理带连字符的包名 print(f" ✓ {lib} 已安装") except ImportError: print(f" ✗ {lib} 未安装") missing_deps.append(pkg) if missing_deps: print("\n缺少依赖,正在安装...") import subprocess try: subprocess.run(['pip', 'install'] + missing_deps, check=True) print("\n依赖安装完成!") except Exception as e: print(f"安装依赖失败: {str(e)}") print("请手动安装缺少的包:") for dep in missing_deps: print(f" pip install {dep}") exit(1) print("\n开始图片分析...") main()
07-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值