import cv2
import numpy as np
import openpyxl
from openpyxl.utils import get_column_letter
def process_image(image, wb, sheet, frame_count, scale_percent=0.35):
try:
# 图像预处理
height, width = image.shape[:2]
new_width = int(width * scale_percent)
new_height = int(height * scale_percent)
resized = cv2.resize(image, (new_width, new_height), cv2.INTER_AREA)
# HSV颜色空间转换
hsv = cv2.cvtColor(resized, cv2.COLOR_BGR2HSV)
# 改进的红色检测范围
lower_red1 = np.array([0, 150, 100]) # 提高饱和度下限
upper_red1 = np.array([8, 255, 255])
lower_red2 = np.array([172, 150, 100]) # 缩小第二个范围
upper_red2 = np.array([180, 255, 255])
# 创建优化掩膜
mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
mask = cv2.bitwise_or(mask1, mask2)
# 改进的形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=2)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
# 轮廓检测优化
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
# 筛选有效轮廓(面积>100)
valid_contours = [c for c in contours if cv2.contourArea(c) > 100]
if not valid_contours:
return
max_contour = max(valid_contours, key=cv2.contourArea)
# 精确质心计算
M = cv2.moments(max_contour)
if M["m00"] != 0:
center_x = int(M["m10"] / M["m00"])
center_y = int(M["m01"] / M["m00"])
else:
x, y, w, h = cv2.boundingRect(max_contour)
center_x = x + w // 2
center_y = y + h // 2
# 亚像素级优化
gray_mask = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.01)
corners = cv2.goodFeaturesToTrack(gray_mask, 1, 0.01, 10)
if corners is not None:
corners = cv2.cornerSubPix(gray_mask, corners, (3, 3), (-1, -1), criteria)
center_x, center_y = int(corners[0][0][0]), int(corners[0][0][1])
# 数据记录
sheet.cell(row=frame_count + 2, column=1).value = frame_count
sheet.cell(row=frame_count + 2, column=2).value = center_x
sheet.cell(row=frame_count + 2, column=3).value = center_y
# 可视化增强
cv2.drawContours(resized, [max_contour], -1, (0, 255, 0), 2)
cv2.circle(resized, (center_x, center_y), 5, (0, 0, 255), -1)
cv2.putText(resized, f"({center_x}, {center_y})", (center_x + 10, center_y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
cv2.imshow('Precision Tracking', resized)
cv2.waitKey(1)
except Exception as e:
print(f"Frame {frame_count} error: {str(e)}")
def process_video(video_path, scale_percent=0.35):
cap = cv2.VideoCapture(video_path)
frame_count = 0
# 创建Excel文件并优化列宽
wb = openpyxl.Workbook()
sheet = wb.active
sheet.title = "Precision Tracking"
headers = ["Frame", "Center X", "Center Y"]
for col, header in enumerate(headers, 1):
sheet.cell(row=1, column=col).value = header
sheet.column_dimensions[get_column_letter(col)].width = 15
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
process_image(frame, wb, sheet, frame_count, scale_percent)
frame_count += 1
if frame_count % 50 == 0:
print(f"Processed {frame_count} frames")
# 保存优化
wb.save("precision_coordinates.xlsx")
cap.release()
cv2.destroyAllWindows()
print(f"Total processed frames: {frame_count}")
# 使用示例
if __name__ == "__main__":
video_path = "1-4.mp4"
process_video(video_path)无法捕捉到视频中的中心坐标