Files
dashboard/extract_frequency_response.py
T
yangy 90aec37461 Add initial files for Audio Dashboard Management System
- Created .env.example for environment variable configuration.
- Added docker-compose.yml for service orchestration.
- Implemented frequency response extraction in extract_frequency_response.py and convert_to_frequency_db.py.
- Generated output files: frequency_response_detailed.json, frequency_response_points.json, frequency_response.csv, and frequency_response_curve.png.
- Included sample measurement data for FiiO FA19 in CSV format.
2026-03-17 14:20:08 +08:00

121 lines
3.8 KiB
Python

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("未找到频响曲线")