codewars:Sort binary tree by levels

博客内容提及对二叉树进行广度搜索,采用了队列这一数据结构,涉及到信息技术领域的数据结构和算法知识。

在这里插入图片描述
此题是广度搜索二叉树,使用队列

import os import cv2 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from pathlib import Path import re # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 class FastScratchDetector: """ 快速的浅层机械损伤检测器 优化了计算效率,保持合理的检测精度 """ def __init__(self): # 优化的检测参数 self.min_scratch_length = 50 self.max_scratch_width = 4 self.min_aspect_ratio = 8 self.hough_threshold = 40 self.min_line_length = 40 def preprocess_image_fast(self, image_path): """快速图像预处理""" try: # 读取图像并立即缩小尺寸 img = cv2.imread(image_path) if img is None: return None # 保存原始图像用于可视化 original = img.copy() # 快速调整图像大小 - 直接缩小到固定尺寸 h, w = img.shape[:2] if max(h, w) > 400: # 使用更小的尺寸 scale = 400 / max(h, w) new_size = (int(w * scale), int(h * scale)) img = cv2.resize(img, new_size) original = cv2.resize(original, new_size) # 简单的灰度转换和直方图均衡化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) enhanced = clahe.apply(gray) return { 'original': original, 'gray': enhanced, 'resized': img } except Exception as e: print(f"预处理错误: {e}") return None def detect_scratch_fast(self, gray_img, original_img): """快速划痕检测""" # 1. 边缘检测 edges = cv2.Canny(gray_img, 50, 150) # 2. 线段检测 - 只使用单一尺度 lines = cv2.HoughLinesP( edges, rho=1, theta=np.pi / 180, threshold=self.hough_threshold, minLineLength=self.min_line_length, maxLineGap=10 ) line_count = len(lines) if lines is not None else 0 # 3. 快速轮廓检测 binary = cv2.adaptiveThreshold( gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2 ) # 简单的形态学操作 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) contours, _ = cv2.findContours( binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) valid_contours = [] for contour in contours: area = cv2.contourArea(contour) if area < 20 or area > 800: continue rect = cv2.minAreaRect(contour) width, height = rect[1] length = max(width, height) width = min(width, height) if width > 0: aspect_ratio = length / width else: aspect_ratio = 0 if (length >= self.min_scratch_length and width <= self.max_scratch_width and aspect_ratio >= self.min_aspect_ratio): valid_contours.append(contour) # 快速病害检测 - 基于简单的颜色阈值 has_disease = self.fast_disease_check(gray_img) # 判断逻辑:有划痕特征且没有病害 has_scratch = line_count >= 2 or len(valid_contours) >= 1 has_mechanical_damage = has_scratch and not has_disease return { 'has_mechanical_damage': has_mechanical_damage, 'line_count': line_count, 'contour_count': len(valid_contours), 'has_disease': has_disease, 'lines': lines, 'contours': valid_contours, 'edges': edges, 'binary': binary } def fast_disease_check(self, gray_img): """快速病害检测""" # 使用简单的亮度阈值检测暗色区域(可能的病害) _, dark_regions = cv2.threshold(gray_img, 50, 255, cv2.THRESH_BINARY_INV) # 计算暗色区域比例 dark_ratio = np.sum(dark_regions > 0) / (gray_img.shape[0] * gray_img.shape[1]) # 如果暗色区域超过5%,认为可能有病害 return dark_ratio > 0.05 def analyze_image_fast(self, image_path): """快速分析图像""" preprocessed = self.preprocess_image_fast(image_path) if preprocessed is None: return None result = self.detect_scratch_fast(preprocessed['gray'], preprocessed['original']) result['preprocessed'] = preprocessed return result def visualize_detection_fast(self, analysis_result, save_path=None): """快速可视化检测结果""" if analysis_result is None: return fig, axes = plt.subplots(2, 3, figsize=(15, 10)) fig.suptitle('石榴浅层机械损伤快速检测分析', fontsize=16, fontweight='bold') original = analysis_result['preprocessed']['original'] gray = analysis_result['preprocessed']['gray'] # 原始图像 axes[0, 0].imshow(cv2.cvtColor(original, cv2.COLOR_BGR2RGB)) axes[0, 0].set_title('原始图像') axes[0, 0].axis('off') # 预处理后图像 axes[0, 1].imshow(gray, cmap='gray') axes[0, 1].set_title('预处理图像') axes[0, 1].axis('off') # 边缘检测结果 axes[0, 2].imshow(analysis_result['edges'], cmap='gray') axes[0, 2].set_title('边缘检测') axes[0, 2].axis('off') # 二值化图像 axes[1, 0].imshow(analysis_result['binary'], cmap='gray') axes[1, 0].set_title('二值化图像') axes[1, 0].axis('off') # 检测结果可视化 result_img = original.copy() # 绘制线段 if analysis_result['lines'] is not None: for line in analysis_result['lines']: x1, y1, x2, y2 = line[0] cv2.line(result_img, (x1, y1), (x2, y2), (0, 255, 0), 2) # 绘制轮廓 for contour in analysis_result['contours']: cv2.drawContours(result_img, [contour], -1, (255, 0, 0), 2) axes[1, 1].imshow(cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB)) axes[1, 1].set_title('检测结果\n(绿:线段, 蓝:轮廓)') axes[1, 1].axis('off') # 检测统计 axes[1, 2].axis('off') stats_text = f""" 检测统计: ========== 线段数量: {analysis_result['line_count']} 有效轮廓: {analysis_result['contour_count']} 病害迹象: {'是' if analysis_result['has_disease'] else '否'} 机械损伤: {'是' if analysis_result['has_mechanical_damage'] else '否'} """ axes[1, 2].text(0.1, 0.5, stats_text, fontsize=12, va='center', linespacing=1.8) axes[1, 2].set_title('检测统计') plt.tight_layout() if save_path: plt.savefig(save_path, dpi=300, bbox_inches='tight') print(f"可视化结果已保存: {save_path}") plt.show() class DetectionAnalyzer: """检测结果分析器""" def __init__(self): self.detection_results = [] self.weekly_stats = {} def add_result(self, week, tree_id, fruit_id, has_damage, line_count, contour_count, has_disease): """添加检测结果""" self.detection_results.append({ 'week': week, 'tree_id': tree_id, 'fruit_id': fruit_id, 'has_damage': has_damage, 'line_count': line_count, 'contour_count': contour_count, 'has_disease': has_disease }) # 更新周统计 if week not in self.weekly_stats: self.weekly_stats[week] = {'total': 0, 'damaged': 0, 'diseased': 0} self.weekly_stats[week]['total'] += 1 if has_damage: self.weekly_stats[week]['damaged'] += 1 if has_disease: self.weekly_stats[week]['diseased'] += 1 def generate_comprehensive_report(self, total_processed, total_detected): """生成综合分析报告""" if not self.detection_results: print("没有检测数据可生成报告") return df = pd.DataFrame(self.detection_results) # 创建综合报告 fig, axes = plt.subplots(2, 3, figsize=(18, 12)) fig.suptitle('石榴浅层机械损伤检测综合分析报告', fontsize=18, fontweight='bold') # 1. 每周损伤分布 weekly_damage = df.groupby('week')['has_damage'].sum() weeks = list(weekly_damage.index) damage_counts = list(weekly_damage.values) axes[0, 0].bar(weeks, damage_counts, color='lightcoral', alpha=0.7, edgecolor='darkred') axes[0, 0].set_xlabel('周数') axes[0, 0].set_ylabel('损伤果实数量') axes[0, 0].set_title('各周机械损伤分布') axes[0, 0].grid(True, alpha=0.3) # 在柱状图上添加数值标签 for i, v in enumerate(damage_counts): axes[0, 0].text(weeks[i], v + 0.1, str(v), ha='center', va='bottom') # 2. 总体检测比例 total_healthy = total_processed - total_detected pie_data = [total_detected, total_healthy] pie_labels = [f'机械损伤\n({total_detected})', f'健康果实\n({total_healthy})'] pie_colors = ['lightcoral', 'lightgreen'] axes[0, 1].pie(pie_data, labels=pie_labels, colors=pie_colors, autopct='%1.1f%%', startangle=90, textprops={'fontsize': 10}) axes[0, 1].set_title('总体检测比例') # 3. 每周检测率 weekly_rates = [] for week in sorted(self.weekly_stats.keys()): stats = self.weekly_stats[week] rate = stats['damaged'] / stats['total'] * 100 if stats['total'] > 0 else 0 weekly_rates.append(rate) axes[0, 2].plot(sorted(self.weekly_stats.keys()), weekly_rates, marker='o', linewidth=2, markersize=8, color='steelblue') axes[0, 2].set_xlabel('周数') axes[0, 2].set_ylabel('检测率 (%)') axes[0, 2].set_title('每周机械损伤检测率') axes[0, 2].grid(True, alpha=0.3) axes[0, 2].set_ylim(0, max(weekly_rates) * 1.2 if weekly_rates else 10) # 4. 特征分布 - 线段数量 line_counts = df['line_count'] axes[1, 0].hist(line_counts, bins=20, color='skyblue', alpha=0.7, edgecolor='black') axes[1, 0].set_xlabel('线段数量') axes[1, 0].set_ylabel('频次') axes[1, 0].set_title('线段数量分布') axes[1, 0].grid(True, alpha=0.3) # 5. 特征分布 - 轮廓数量 contour_counts = df['contour_count'] axes[1, 1].hist(contour_counts, bins=20, color='lightgreen', alpha=0.7, edgecolor='black') axes[1, 1].set_xlabel('轮廓数量') axes[1, 1].set_ylabel('频次') axes[1, 1].set_title('有效轮廓数量分布') axes[1, 1].grid(True, alpha=0.3) # 6. 统计摘要 axes[1, 2].axis('off') stats_text = f""" 检测统计摘要 ============ 总处理图像: {total_processed} 损伤果实数: {total_detected} 健康果实数: {total_healthy} 总体检测率: {total_detected / total_processed * 100:.2f}% 特征统计: - 平均线段数: {df['line_count'].mean():.2f} - 平均轮廓数: {df['contour_count'].mean():.2f} - 病害果实数: {df['has_disease'].sum()} 周统计: - 最高损伤周: 第{weekly_damage.idxmax()}周 ({weekly_damage.max()}个) - 最低损伤周: 第{weekly_damage.idxmin()}周 ({weekly_damage.min()}个) - 平均每周: {weekly_damage.mean():.1f}个 """ axes[1, 2].text(0.05, 0.95, stats_text, fontsize=11, va='top', linespacing=1.6, bbox=dict(boxstyle="round,pad=0.3", facecolor="lightgray", alpha=0.7)) plt.tight_layout() plt.savefig('detection_comprehensive_report.png', dpi=300, bbox_inches='tight') plt.show() return df def parse_filename(filename): """解析文件名""" try: if '_' in filename and '.' in filename: parts = filename.split('_') if len(parts) >= 2: tree_id = int(parts[0]) fruit_sub_id = int(parts[1].split('.')[0]) return tree_id, fruit_sub_id elif '.' in filename: parts = filename.split('.') if len(parts) >= 3: tree_id = int(parts[0]) fruit_sub_id = int(parts[1]) return tree_id, fruit_sub_id except: pass return 1, 1 def main_fast(): """快速版本的主程序""" print("=" * 60) print("石榴浅层机械损伤检测系统 (快速版本)") print("=" * 60) # 初始化快速检测器和分析器 detector = FastScratchDetector() analyzer = DetectionAnalyzer() # 数据路径 data_dir = "D:/university/shujuwajue/shiyong1/data/attachment1" if not os.path.exists(data_dir): print(f"错误: 数据路径不存在 - {data_dir}") return # 存储最终结果 final_results = [] # 遍历数据 total_processed = 0 total_detected = 0 visualization_count = 0 max_visualizations = 5 # 最多生成5个可视化结果 week_dirs = [d for d in Path(data_dir).iterdir() if d.is_dir() and 'week' in d.name.lower()] for week_dir in sorted(week_dirs): week_match = re.search(r'week_(\d+)_', week_dir.name) if week_match: week = int(week_match.group(1)) else: week = 1 print(f"\n处理第 {week} 周数据...") # 遍历树号文件夹 tree_dirs = [d for d in week_dir.iterdir() if d.is_dir() and d.name.isdigit()] for tree_dir in tree_dirs: tree_id = int(tree_dir.name) print(f" 树号: {tree_id:02d}", end=" - ") # 处理该树的所有图像 image_files = list(tree_dir.glob("*.jpg")) tree_detected = 0 for img_path in image_files: total_processed += 1 # 解析果实编号 parsed_tree_id, fruit_sub_id = parse_filename(img_path.name) fruit_id = int(f"{parsed_tree_id:02d}{fruit_sub_id:02d}") # 分析图像 analysis = detector.analyze_image_fast(str(img_path)) if analysis is not None: has_damage = analysis['has_mechanical_damage'] # 记录到分析器 analyzer.add_result( week, tree_id, fruit_id, has_damage, analysis['line_count'], analysis['contour_count'], analysis['has_disease'] ) # 记录结果 if has_damage: final_results.append({ '周数': week, '果实编号': fruit_id }) total_detected += 1 tree_detected += 1 # 为前几个检测到的损伤生成可视化 if visualization_count < max_visualizations: viz_path = f"detection_visualization_{week}_{tree_id}_{fruit_sub_id}.png" detector.visualize_detection_fast(analysis, viz_path) visualization_count += 1 print(f"检测到 {tree_detected} 个损伤") # 保存最终结果 if final_results: df_results = pd.DataFrame(final_results) df_results = df_results.sort_values(['周数', '果实编号']).drop_duplicates() df_results.to_excel('result4_fast.xlsx', index=False) print(f"\n" + "=" * 60) print("检测完成!") print(f"处理图像总数: {total_processed}") print(f"检测到机械损伤: {total_detected}") print(f"检测率: {total_detected / total_processed * 100:.2f}%") print(f"结果已保存至: result4_fast.xlsx") # 显示检测到的果实信息 print(f"\n检测到的损伤果实分布:") weekly_counts = df_results['周数'].value_counts().sort_index() for week, count in weekly_counts.items(): print(f" 第{week}周: {count}个") # 生成综合分析报告 print(f"\n生成综合分析报告...") analyzer.generate_comprehensive_report(total_processed, total_detected) else: print("\n未检测到任何机械损伤") # 创建空的结果文件 empty_df = pd.DataFrame(columns=['周数', '果实编号']) empty_df.to_excel('result4_fast.xlsx', index=False) if __name__ == "__main__": # 运行快速版本 main_fast()这段代码如何修改可以拿到数据挖掘比赛的高分,给我完整的代码
最新发布
11-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值