You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV getWindowImageRect返回尺寸与实际分辨率不符的原因及解决方法

问题分析与解决:OpenCV getWindowImageRect返回错误的窗口坐标

问题描述

使用OpenCV获取窗口屏幕位置时,执行以下代码:

cv2.imshow('test', img)
print(cv2.getWindowImageRect('test'))

将窗口移动到屏幕右下角后,输出为(1484, 895, 500, 500),但实际屏幕分辨率为2240x1400,函数识别的等效分辨率约为1500x900,与实际不符。

问题原因

该问题源于Windows系统的显示缩放与布局设置(此处为150%):
OpenCV的HighGUI模块在Windows平台默认未启用DPI(每英寸点数)感知,导致getWindowImageRect()返回的是系统缩放后的逻辑像素坐标,而非屏幕实际的物理像素坐标。系统缩放会将物理像素按比例转换为逻辑像素,OpenCV未适配这一机制,因此返回的坐标被“缩小”了缩放比例的倍数(比如150%缩放时,逻辑像素 = 物理像素 / 1.5)。

解决方法

1. 启用程序的DPI感知(推荐)

通过调用Windows API让Python程序开启DPI感知,使OpenCV能直接获取真实物理坐标:

import ctypes
import cv2
import numpy as np

# 适配Windows 10及以上的Per-Monitor DPI感知,兼容旧系统
try:
    # PROCESS_PER_MONITOR_DPI_AWARE = 2
    ctypes.windll.shcore.SetProcessDpiAwareness(2)
except AttributeError:
    # 兼容Windows 7/8,启用系统级DPI感知
    ctypes.windll.user32.SetProcessDPIAware()

# 测试代码
img = np.zeros((500, 500, 3), dtype=np.uint8)
cv2.imshow('test', img)
print("真实物理坐标:", cv2.getWindowImageRect('test'))
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 手动转换逻辑坐标为物理坐标

如果无法修改程序的DPI感知设置,可以先获取系统缩放比例,再对返回的坐标进行换算:

import ctypes
import cv2
import numpy as np

def get_system_scaling():
    """获取当前系统的显示缩放比例"""
    user32 = ctypes.windll.user32
    user32.SetProcessDPIAware()
    # 96是默认DPI(对应100%缩放),当前DPI除以96得到缩放比例
    return user32.GetDpiForSystem() / 96

scaling = get_system_scaling()
img = np.zeros((500, 500, 3), dtype=np.uint8)
cv2.imshow('test', img)
logic_rect = cv2.getWindowImageRect('test')
# 转换为物理坐标
physical_rect = (
    int(logic_rect[0] * scaling),
    int(logic_rect[1] * scaling),
    int(logic_rect[2] * scaling),
    int(logic_rect[3] * scaling)
)
print("逻辑坐标:", logic_rect)
print("真实物理坐标:", physical_rect)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 临时调整系统缩放(不推荐)

将Windows显示缩放设置改为100%,但此方法会影响系统整体显示效果,仅适合临时测试。


内容的提问来源于stack exchange,提问作者SzymonO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 09:35:33