恢复OpenCV中横向全屏的原有比例适配显示行为
问题
我使用Ubuntu 22.04 LTS预装的OpenCV版本,此前通过以下配置设置窗口:
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
该配置可让宽于屏幕的图片按比例缩放,完整适配横向全屏显示。但安装(及重装)PyQt5、PyQt5-sip等包后,窗口变为纵向拉伸图片导致失真。
以下是最小可复现示例(MRE):
import cv2 import numpy as np from screeninfo import get_monitors def get_screen_size(): monitor = get_monitors()[0] return (monitor.width, monitor.height) def write_text(image, text="Hello World"): font = cv2.FONT_HERSHEY_SIMPLEX font_scale = 14 font_thickness = 14 font_color = (255, 255, 255) (text_width, text_height), _ = cv2.getTextSize(text, font, font_scale, font_thickness) x = (image.shape[1] - text_width) // 2 y = (image.shape[0] + text_height) // 2 cv2.putText(image, text, (x, y), font, font_scale, font_color, font_thickness) return image image = np.random.randint(0, 256, (1280, 2560, 3), dtype=np.uint8) # dummy image image = write_text(image) window_name = 'Full Screen Image' cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) # cv2.resizeWindow(window_name, get_screen_size()) # 1920 x 1200 # This is my workaround. But originally this line was not in the code cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) cv2.imshow(window_name, image) cv2.waitKey(0) cv2.destroyAllWindows()
如何恢复原有全屏行为,让图片按比例适配屏幕横向显示且不失真?
解决方案
安装PyQt5后,OpenCV的窗口后端被切换为Qt,导致原有的全屏缩放逻辑失效。可通过以下两种方式恢复按比例缩放的全屏显示:
方法1:强制使用GTK窗口后端
在代码开头添加环境变量设置,让OpenCV回到Ubuntu预装版本默认的GTK后端,恢复自动按比例缩放的行为:
import os # 强制OpenCV使用GTK后端 os.environ['OPENCV_UI_BACKEND'] = 'GTK'
添加后保持原有的窗口配置代码即可,无需额外调整。
方法2:手动计算适配比例(不切换后端)
如果需要保留Qt后端,可手动计算图片与屏幕的适配比例,先调整窗口尺寸再设置全屏:
import cv2 import numpy as np from screeninfo import get_monitors def get_screen_size(): monitor = get_monitors()[0] return (monitor.width, monitor.height) def write_text(image, text="Hello World"): font = cv2.FONT_HERSHEY_SIMPLEX font_scale = 14 font_thickness = 14 font_color = (255, 255, 255) (text_width, text_height), _ = cv2.getTextSize(text, font, font_scale, font_thickness) x = (image.shape[1] - text_width) // 2 y = (image.shape[0] + text_height) // 2 cv2.putText(image, text, (x, y), font, font_scale, font_color, font_thickness) return image image = np.random.randint(0, 256, (1280, 2560, 3), dtype=np.uint8) image = write_text(image) window_name = 'Full Screen Image' # 获取屏幕与图片尺寸 screen_w, screen_h = get_screen_size() img_h, img_w = image.shape[:2] # 计算适配比例,取宽高比例的最小值,确保图片完整显示 scale = min(screen_w / img_w, screen_h / img_h) # 计算缩放后的窗口尺寸(保持图片比例) target_w = int(img_w * scale) target_h = int(img_h * scale) cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) cv2.resizeWindow(window_name, target_w, target_h) cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) cv2.imshow(window_name, image) cv2.waitKey(0) cv2.destroyAllWindows()
原因说明
Ubuntu预装的OpenCV默认使用GTK窗口后端,该后端在设置全屏时会自动按图片比例缩放以适配屏幕;而安装PyQt5后,OpenCV会优先切换到Qt后端,Qt后端的全屏逻辑是直接拉伸窗口填充屏幕,不会保持图片比例,因此导致失真。
内容的提问来源于stack exchange,提问作者ravi
相关产品推荐
相关产品推荐

