OpenCV imshow显示视频未按原始尺寸展示的解决方法
问题根因
OpenCV默认创建的显示窗口未开启高DPI适配,当Windows/macOS系统开启了全局显示缩放(高分屏设备常见默认125%/150%缩放)时,系统会自动对窗口内容做位图缩放,最终显示的画面尺寸和视频原始帧尺寸不一致。该缩放仅发生在窗口渲染层,不会改变cap.read()读取到的帧本身的像素值和尺寸,但会导致手动选取ROI时,窗口点击坐标和帧数组实际索引不匹配。
修复方案
- 显式创建显示窗口,指定严格匹配帧尺寸的窗口标志,禁止OpenCV自动缩放画面
- Windows平台额外开启进程高DPI感知,屏蔽系统对窗口的强制缩放
- 修正原代码中释放窗口的参数错误
修正后可直接运行的代码
import cv2 # Windows平台需执行以下逻辑开启高DPI感知,非Windows平台可跳过这段 try: import ctypes # Win10/11 新接口 ctypes.windll.shcore.SetProcessDpiAwareness(2) except Exception: try: # 旧版Windows兼容接口 ctypes.windll.user32.SetProcessDPIAware() except Exception: pass cap = cv2.VideoCapture("video_link") # 显式创建窗口,强制窗口尺寸和帧尺寸1:1匹配 cv2.namedWindow("frame", cv2.WINDOW_AUTOSIZE) # 可选校验:打印读取到的原始帧尺寸,确认视频源读取无异常 ret, test_frame = cap.read() if ret: frame_h, frame_w = test_frame.shape[:2] print(f"视频原始帧尺寸:宽度{frame_w}px,高度{frame_h}px") # 把读出来的测试帧放回播放队列,不影响后续循环播放 cap.set(cv2.CAP_PROP_POS_FRAMES, 0) while True: ret, frame = cap.read() if not ret: break cv2.imshow("frame", frame) key = cv2.waitKey(1) # 按ESC键退出 if key == 27: break cap.release() cv2.destroyAllWindows()
注意事项
- 不要使用
cv2.WINDOW_NORMAL标志创建窗口,该标志允许自由拖拽调整窗口大小,OpenCV会自动拉伸画面适配窗口尺寸,无法保证1:1原始像素显示。 - 配置完成后弹出的播放窗口会严格匹配视频原始像素尺寸,此时在窗口上选取的ROI坐标可以直接对应帧数组的索引,不会出现定位偏移。
内容的提问来源于stack exchange,提问作者Luqman Hakim
相关产品推荐
相关产品推荐

