Вопрос или проблема
Я использую версию 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
и др., поведение моего окна OpenCV изменилось. Теперь, вместо того чтобы растягивать изображение по горизонтали, окно растягивает его вертикально, что искажает отображение. Вот текущее (нежелательное) поведение:
Ниже представлена 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) # тестовое изображение
image = write_text(image)
window_name="Полноэкранное изображение"
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
# cv2.resizeWindow(window_name, get_screen_size()) # 1920 x 1200 # Это мое обходное решение. Но изначально этой строки не было в коде
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.imshow(window_name, image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Как вернуть оригинальное поведение полноэкранного режима, при котором изображение масштабируется по горизонтали, помещаясь на экран, сохраняя при этом свои пропорции?
Ответ или решение
Для восстановления поведения полноэкранного режима в OpenCV, где изображение масштабируется горизонтально и при этом сохраняет пропорции, необходимо внести изменения в код для более точного управления отображением окна. Основная проблема заключается в том, как OpenCV обрабатывает полноэкранные режимы на системе, особенно после установки дополнительных пакетов, таких как PyQt5.
Вот шаги, которые помогут вам вернуть желаемое поведение:
-
Создание окна с флагом нормально: Используйте
cv2.WINDOW_NORMAL
, как это сделано в вашем коде, чтобы окно могло изменять свой размер. -
Настройка размера окна: Перед установкой полноэкранного режима, необходимо установить размер окна в соответствии с разрешением экрана.
- Использование соотношения сторон: При изменении размера изображения убедитесь, что вы сохраняете его пропорции. Это можно сделать, изменив размеры изображения в зависимости от ширины экрана.
Вот обновлённая версия вашего кода:
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"
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
# Получаем размеры экрана
screen_width, screen_height = get_screen_size()
# Рассчитываем новый размер с сохранением пропорций
aspect_ratio = image.shape[1] / image.shape[0]
new_height = screen_height
new_width = int(aspect_ratio * new_height)
if new_width > screen_width:
new_width = screen_width
new_height = int(new_width / aspect_ratio)
# Устанавливаем размер окна
cv2.resizeWindow(window_name, new_width, new_height)
# Устанавливаем полноэкранный режим
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
# Отображаем изображение
cv2.imshow(window_name, image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Объяснение кода:
- Мы сначала вычисляем размеры экрана с помощью
get_screen_size()
. - Затем, в зависимости от исходного соотношения сторон изображения, мы вычисляем новые размеры, чтобы изображение вписалось в экран, не искажая при этом пропорции.
- Функция
cv2.resizeWindow
используется для установки размера окна перед тем, как оно будет переведено в полноэкранный режим.
Этот подход должен восстановить ваше прежнее поведение окна OpenCV, при этом сохраняя подходящий вид изображения на экране.