特征光流法实时窗口
import cv2
import numpy as np
import matplotlib.pyplot as plt
video_path="5-6-1mm.avi"
cap = cv2.VideoCapture(video_path)
# 参数设置
lk_params = dict(winSize=(15, 15), maxLevel=3, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.007))
feature_params = dict(maxCorners=1, qualityLevel=0.7, minDistance=1, blockSize=7)
# 读取第一帧作为初始帧
ret, old_frame = cap.read()
if old_frame is None:
print("Error: Input frame is empty")
else:
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 使用 goodFeaturesToTrack 检测特征点
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
# # ORB 特征点检测器
# orb = cv2.ORB_create()
# 检测特征点
#p0, _ = orb.detectAndCompute(old_gray, None)
# 存储每个特征点的坐标变化
point_history = [[] for _ in range(p0.shape[0])]
while True:
# 读取当前帧
ret, frame = cap.read()
if not ret: # 视频读取完毕
break
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 使用 calcOpticalFlowPyrLK 计算光流
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
# 保留好的特征点和匹配的特征点
good_new = p1[st == 1]
good_old = p0[st == 1]
# 绘制追踪线和特征点
for i, (new, old) in enumerate(zip(good_new, good_old)):
a, b = new.ravel()
c, d = old.ravel()
cv2.line(frame, (int(a), int(b)), (int(c), int(d)), (0, 255, 0), 2)
cv2.circle(frame, (int(a), int(b)), 5, (0, 0, 255), -1)
# 存储坐标变化
point_history[i].append((a, b))
# 显示当前帧
cv2.imshow("Frame", frame)
# 获取当前帧号
current_frame = cap.get(cv2.CAP_PROP_POS_FRAMES)
# 提取特征点的位移沿x方向的数据
x_data = [[] for _ in range(len(point_history))]
y_data = [[] for _ in range(len(point_history))]
for i, points in enumerate(point_history):
for j in range(1, len(points)):
x_data[i].append(points[j][0] - points[i][0]) # 计算横x位移
y_data[i].append(points[j][1] - points[i][1]) # 计算竖y位移
# 可视化特征点的位移与时间的关系
plt.clf() # 清空之前的图像
for i, (x_values, y_values) in enumerate(zip(x_data, y_data)):
t = np.arange(len(x_values))
# 绘制x位移图像
plt.subplot(2, 1, 1)
plt.plot(t, x_values, label=f"Point {i + 1}", linestyle="-")
plt.ylabel("X Displacement (pixels)")
# 绘制y位移图像
plt.subplot(2, 1, 2)
plt.plot(t, y_values, label=f"Point {i + 1}", linestyle="-")
plt.xlabel("Frame Number")
plt.ylabel("Y Displacement (pixels)")
plt.title("X Displacement of Feature Points over Time")
plt.legend()
plt.text(0.05, 0.95, f"Frame: {int(current_frame)}", transform=plt.gca().transAxes, color='white') # 在图上标记当前帧号
plt.pause(0.001) # 暂停一小段时间,以更新图像
# 退出循环的条件
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 更新上一帧的图像和特征点
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1, 1, 2)
# 关闭视频和文件
cap.release()
cv2.destroyAllWindows()
for i, (x_values, y_values) in enumerate(zip(x_data, y_data)):
t = np.arange(len(x_values))
# 绘制x位移图像
plt.subplot(2, 1, 1)
plt.plot(t, x_values, label=f"Point {i + 1}", linestyle="-")
plt.ylabel("X Displacement (pixels)")
# 绘制y位移图像
plt.subplot(2, 1, 2)
plt.plot(t, y_values, label=f"Point {i + 1}", linestyle="-")
plt.xlabel("Frame Number")
plt.ylabel("Y Displacement (pixels)")
plt.title("X Displacement of Feature Points over Time")
plt.legend()
plt.show()