基于OpenCV与Python实现视频下方CSV表格同步显示的问题求助
问题与解决方案
问题描述
我正在开发一个项目,需要在视频下方以表格形式展示CSV文件的对应数据。现有代码可读取视频与CSV文件并在窗口中显示视频,同时应在视频下方展示CSV数据表格,且表格数据需随视频进度更新或滚动以匹配时序。但目前代码存在问题:视频播放不流畅,表格行尺寸过大无法正常查看。
需求
- 确保视频流畅播放无卡顿或缓冲;
- 调整表格尺寸使其缩小并适配窗口;
- 实现表格数据随视频时序滚动的功能。
原代码
import cv2 import pandas as pd import numpy as np # Function to display video with CSV data in tabular format below the video def display_video_with_csv(video_path, csv_path): cap = cv2.VideoCapture(video_path) df = pd.read_csv(csv_path) # Set up the display window cv2.namedWindow('Video with CSV', cv2.WINDOW_NORMAL) # Read the first frame to get video dimensions ret, frame = cap.read() height, width, _ = frame.shape # Calculate the height for the table display table_height = int(height * 0.8) # Initialize the scrolling position and scrolling step size scroll_pos = 0 scroll_step = int(table_height / 10) # Adjust the step size as needed while True: # Read the next frame from the video ret, frame = cap.read() if not ret: break # Get the frame number and corresponding data from the CSV file frame_number = int(cap.get(cv2.CAP_PROP_POS_FRAMES)) data = df.iloc[frame_number - 1] # Create a table to display the CSV data table = pd.DataFrame(data).transpose() # Create a blank image to display the table data table_image = 255 * np.ones((table_height, width, 3), dtype=np.uint8) # Add the table text to the table image font = cv2.FONT_HERSHEY_DUPLEX font_scale = 0.5 font_thickness = 1 text_color = (0, 0, 0) # Black color y_offset = scroll_step for i, (col_name, val) in enumerate(table.items()): cv2.putText( table_image, f"{col_name}: {val.values[0]}", (10, y_offset), font, font_scale, text_color, font_thickness, cv2.LINE_AA ) y_offset += scroll_step # Display the video frame cv2.imshow('Video with CSV', frame) # Create a combined image with the video frame and table image combined_image = np.vstack((frame, table_image)) # Display the combined image in the window cv2.imshow('Video with CSV', combined_image) # Scroll the table if needed if frame_number % 30 == 0: # Adjust the scroll frequency as needed scroll_pos += 1 # Check for user interrupt (press 'q' to exit) if cv2.waitKey(1) & 0xFF == ord('q'): break # Release the video stream and close the display window cap.release() cv2.destroyAllWindows() # Provide the paths to the video and CSV file video_path = r"Main.mp4" csv_path = r"Test_1.csv" # Call the function to display the video with CSV data display_video_with_csv(video_path, csv_path)
修改后的代码与解决方案
1. 解决视频卡顿问题
- 移除重复的
cv2.imshow调用,只显示最终的合并图像; - 根据视频帧率设置
waitKey的延迟时间,避免固定1ms导致的过快或卡顿; - 预先将CSV数据转换为字典列表,避免每次循环创建DataFrame的开销。
2. 调整表格尺寸适配窗口
- 缩小表格高度比例(改为视频高度的30%),避免占用过多空间;
- 根据字体大小计算合适的行高,确保每行内容紧凑且清晰;
- 限制表格内文本的显示长度,避免内容溢出。
3. 实现时序滚动功能
- 根据当前帧对应的CSV行索引,计算滚动偏移量,让当前帧的数据始终显示在表格的顶部区域;
- 限制滚动范围,避免超出CSV数据的上下边界。
import cv2 import pandas as pd import numpy as np def display_video_with_csv(video_path, csv_path): cap = cv2.VideoCapture(video_path) df = pd.read_csv(csv_path) # 预先转换为字典列表,提升访问速度 csv_data = df.to_dict('records') total_frames = len(csv_data) # 获取视频帧率,用于设置waitKey延迟 fps = cap.get(cv2.CAP_PROP_FPS) wait_delay = int(1000 / fps) if fps > 0 else 1 # 读取第一帧获取尺寸 ret, frame = cap.read() if not ret: print("无法读取视频") return height, width, _ = frame.shape # 调整表格高度为视频高度的30% table_height = int(height * 0.3) # 计算每行的高度(基于字体大小) font = cv2.FONT_HERSHEY_DUPLEX font_scale = 0.4 font_thickness = 1 # 获取字体行高 (text_width, text_height), _ = cv2.getTextSize("Test", font, font_scale, font_thickness) row_height = text_height + 8 # 增加少量间距 # 表格可显示的最大行数 max_display_rows = table_height // row_height cv2.namedWindow('Video with CSV', cv2.WINDOW_NORMAL) while True: ret, frame = cap.read() if not ret: break # 获取当前帧索引(确保不超出CSV数据范围) frame_idx = min(int(cap.get(cv2.CAP_PROP_POS_FRAMES)) - 1, total_frames - 1) current_data = csv_data[frame_idx] # 创建表格背景 table_image = 255 * np.ones((table_height, width, 3), dtype=np.uint8) # 计算滚动位置:让当前数据行显示在表格顶部附近,超出范围则滚动 scroll_start = max(0, frame_idx - (max_display_rows // 2)) scroll_end = min(total_frames, scroll_start + max_display_rows) # 绘制表格内容 y_offset = row_height for row_idx in range(scroll_start, scroll_end): row_data = csv_data[row_idx] # 拼接该行的所有列内容(可根据需求调整显示格式) text_parts = [f"{k}: {v}" for k, v in row_data.items()] # 限制单行长度,避免超出窗口 text = ", ".join(text_parts[:5]) + ("..." if len(text_parts) >5 else "") # 高亮当前帧对应的行 color = (0, 0, 255) if row_idx == frame_idx else (0, 0, 0) cv2.putText( table_image, text, (10, y_offset), font, font_scale, color, font_thickness, cv2.LINE_AA ) y_offset += row_height if y_offset > table_height: break # 合并视频帧和表格 combined_image = np.vstack((frame, table_image)) cv2.imshow('Video with CSV', combined_image) # 处理退出和延迟 if cv2.waitKey(wait_delay) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() # 路径设置 video_path = r"Main.mp4" csv_path = r"Test_1.csv" display_video_with_csv(video_path, csv_path)
关键修改说明
- 流畅播放:通过匹配视频帧率设置
waitKey延迟,移除冗余的imshow调用,预先处理CSV数据减少循环内计算; - 表格适配:缩小表格高度,根据字体自动计算行高,限制单行显示内容避免溢出;
- 时序滚动:基于当前帧索引计算滚动起始位置,让对应数据始终处于可视区域,同时高亮当前行提升辨识度。
内容的提问来源于stack exchange,提问作者RSK Rao
相关产品推荐
相关产品推荐

