import cv2 import numpy as np import matplotlib.pyplot as plt import json # 读取图片 img_path = r"C:\Users\yangy\.cursor\projects\h-soft-projects-luxsin-dashboard/assets/c__Users_yangy_AppData_Roaming_Cursor_User_workspaceStorage_b134a9df77916b35c1e5b1ece8dc14fe_images_Arcona-avg-0b78da44-4aaa-465b-9b2b-fba051a28742.png" img = cv2.imread(img_path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_copy = img.copy() gray = cv2.cvtColor(img_copy, cv2.COLOR_RGB2GRAY) print(f"图片尺寸:{img_copy.shape}") height, width = gray.shape # 定义图表区域(排除顶部标题和底部图例) # 根据图片估算:顶部约 5%,底部约 8% chart_top = int(height * 0.05) chart_bottom = int(height * 0.92) chart_left = int(width * 0.02) chart_right = int(width * 0.98) # 裁剪出图表区域 chart_roi = gray[chart_top:chart_bottom, chart_left:chart_right] # 使用阈值提取白色线条 _, thresh = cv2.threshold(chart_roi, 200, 255, cv2.THRESH_BINARY) # 形态学操作,连接断开的线条 kernel = np.ones((3,3), np.uint8) dilated_thresh = cv2.dilate(thresh, kernel, iterations=2) eroded_thresh = cv2.erode(dilated_thresh, kernel, iterations=1) # 查找轮廓 contours, _ = cv2.findContours(eroded_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 找到最大的连续轮廓(应该是频响曲线) largest_contour = None max_area = 0 for contour in contours: area = cv2.contourArea(contour) if area > max_area: max_area = area largest_contour = contour print(f"最大轮廓面积:{max_area}") # 提取频响曲线上的点 frequency_points = [] if largest_contour is not None: # 对于每个 x 坐标,找到对应的 y 坐标(取平均值) x_coords = {} for point in largest_contour: x, y = point[0] # 转换回原图坐标 global_x = int(x) + chart_left global_y = int(y) + chart_top if global_x not in x_coords: x_coords[global_x] = [] x_coords[global_x].append(global_y) # 对每个 x,计算平均 y 值 for x in sorted(x_coords.keys()): y_values = x_coords[x] avg_y = sum(y_values) // len(y_values) frequency_points.append([int(x), int(avg_y)]) print(f"提取的频响曲线点数:{len(frequency_points)}") # 创建可视化结果 result = img_copy.copy() # 绘制检测到的点 for i, (x, y) in enumerate(frequency_points): cv2.circle(result, (x, y), 1, (255, 0, 0), -1) # 显示结果 plt.figure(figsize=(20, 10)) plt.imshow(result) plt.title(f'Extracted Frequency Response Curve ({len(frequency_points)} points)') plt.axis('off') plt.tight_layout() plt.show() # 保存点到 JSON 文件 output_data = { "frequency_points": frequency_points, "chart_area": { "top": int(chart_top), "bottom": int(chart_bottom), "left": int(chart_left), "right": int(chart_right) }, "image_size": { "width": int(width), "height": int(height) } } with open('frequency_response_points.json', 'w', encoding='utf-8') as f: json.dump(output_data, f, ensure_ascii=False, indent=2) print(f"\n频响点位已保存到 frequency_response_points.json") print(f"\n前 50 个点的坐标 (x, y):") for i, point in enumerate(frequency_points[:50]): print(f"{i+1}: {point}") # 也保存为 CSV 格式,方便查看 with open('frequency_response_points.csv', 'w', encoding='utf-8') as f: f.write("index,x,y\n") for i, point in enumerate(frequency_points): f.write(f"{i+1},{point[0]},{point[1]}\n") print(f"\n点位也已保存到 frequency_response_points.csv") else: print("未找到频响曲线")