Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2k屏幕电脑,在使用HDMI接口外接显示屏之后,点击截图键会出现蓝色的颜色块,影响截图 #279

Closed
lzh1043060917 opened this issue Dec 22, 2023 · 10 comments

Comments

@lzh1043060917
Copy link

Snipaste_2023-12-22_14-55-33 我的电脑是天选4,屏幕2k屏,在使用HDMI接口外接显示屏之后,点击截图键会出现蓝色的颜色块,导致无法正常截图;但是我换了个1080p屏幕的笔记本电脑,外接显示屏之后,点击截图键就没有这个问题了。两种版本的umi-ocr都出现了这样的问题,不知道有人知道啥原因么?
@lzh1043060917
Copy link
Author

我的天选4是win11系统,cpu是amd,屏幕刷新率较高,但是外接显示屏只有60hz,我不太清楚和这个有没有关系。另一台没问题的电脑屏幕是1080p,60hz刷新率,win10系统,cpu是英特尔,除此之外想不到有啥差别了......

@lzh1043060917
Copy link
Author

补充一下,我的2k屏的笔记本电脑,如果不外接显示器,直接用截图功能,就不会出现蓝色的块。只有在使用HDMI外接显示器之后才会出现这个情况。

@hiroi-sora
Copy link
Owner

试下关闭硬件加速

image

@lzh1043060917
Copy link
Author

试下关闭硬件加速

image

试了,没效果

@hiroi-sora
Copy link
Owner

hiroi-sora commented Dec 27, 2023

请尝试下列操作:

  1. 打开 UmiOCR-data\py_src\image_controller\image_provider.py ,将30行的requestPixmap函数替换为:
    def requestPixmap(self, path, size=None, resSize=None):
        if "/" in path:
            compID, imgID = path.split("/", 1)
            self._delCompCache(compID)  # 先清缓存
            if imgID in self.pixmapDict:
                self.compDict[compID] = imgID  # 记录缓存
                return self.pixmapDict[imgID]
            print(f"[Error] imgID {imgID} not in pixmapDict")
        else:  # 清空一个组件的缓存
            self._delCompCache(path)
        return self._getNoneImg()  # 返回占位符
  1. 打开 UmiOCR-data\py_src\image_controller\screenshot_controller.py ,将第16行的getScreenshot函数替换为:
    def getScreenshot(self, wait=0):
        if wait > 0:
            time.sleep(wait)
        try:
            grabList = []
            screensList = QGuiApplication.screens()
            for screen in screensList:
                pixmap = screen.grabWindow(0)  # 截图
                imgID = PixmapProvider.addPixmap(pixmap)  # 存入提供器,获取imgID
                grabList.append(
                    {
                        "imgID": imgID,
                        "screenName": screen.name(),
                    }
                )
                print(imgID)
                print(screen.name())
                print(screen.devicePixelRatio())
                print(screen.virtualGeometry())
                print(screen.geometry())
            return grabList
        except Exception as e:
            return [f"[Error] Screenshot: {e}"]

然后,在命令行中运行Umi-OCR,也可以直接运行 UmiOCR-data\RUN_CLI.bat 。截图,如果出现异常颜色块的话,将命令行输出的内容粘上来给我看看。

@lzh1043060917
Copy link
Author

请尝试下列操作:

  1. 打开 UmiOCR-data\py_src\image_controller\image_provider.py ,将30行的requestPixmap函数替换为:
    def requestPixmap(self, path, size=None, resSize=None):
        if "/" in path:
            compID, imgID = path.split("/", 1)
            self._delCompCache(compID)  # 先清缓存
            if imgID in self.pixmapDict:
                self.compDict[compID] = imgID  # 记录缓存
                return self.pixmapDict[imgID]
            print(f"[Error] imgID {imgID} not in pixmapDict")
        else:  # 清空一个组件的缓存
            self._delCompCache(path)
        return self._getNoneImg()  # 返回占位符
  1. 打开 UmiOCR-data\py_src\image_controller\screenshot_controller.py ,将第16行的getScreenshot函数替换为:
    def getScreenshot(self, wait=0):
        if wait > 0:
            time.sleep(wait)
        try:
            grabList = []
            screensList = QGuiApplication.screens()
            for screen in screensList:
                pixmap = screen.grabWindow(0)  # 截图
                imgID = PixmapProvider.addPixmap(pixmap)  # 存入提供器,获取imgID
                grabList.append(
                    {
                        "imgID": imgID,
                        "screenName": screen.name(),
                    }
                )
                print(imgID)
                print(screen.name())
                print(screen.devicePixelRatio())
                print(screen.virtualGeometry())
                print(screen.geometry())
            return grabList
        except Exception as e:
            return [f"[Error] Screenshot: {e}"]

然后,在命令行中运行Umi-OCR,也可以直接运行 UmiOCR-data\RUN_CLI.bat 。截图,如果出现异常颜色块的话,将命令行输出的内容粘上来给我看看。

Snipaste_2023-12-29_09-37-11

@hiroi-sora
Copy link
Owner

啊??太玄学了,截图对象已经缓存到字典里了怎么会莫名其妙的消失了呢……

麻烦再改一下,UmiOCR-data\py_src\image_controller\image_provider.py

requestPixmap函数改为:

    def requestPixmap(self, path, size=None, resSize=None):
        print(f"request: {path}")
        print("   ", list(k[-6:] for k in self.pixmapDict.keys()))
        if "/" in path:
            compID, imgID = path.split("/", 1)
            self._delCompCache(compID)  # 先清缓存
            if imgID in self.pixmapDict:
                self.compDict[compID] = imgID  # 记录缓存
                return self.pixmapDict[imgID]
            print(f"[Error] imgID {imgID} not in pixmapDict!")
        else:  # 清空一个组件的缓存
            self._delCompCache(path)
        return self._getNoneImg()  # 返回占位符

后面的 _delCompCache 函数改为:

    def _delCompCache(self, compID):
        if compID in self.compDict:
            last = self.compDict[compID]
            if last in self.pixmapDict:
                print(f"___del: {compID} {last}")
                del self.pixmapDict[last]
            del self.compDict[compID]

@lzh1043060917
Copy link
Author

啊??太玄学了,截图对象已经缓存到字典里了怎么会莫名其妙的消失了呢……

麻烦再改一下,UmiOCR-data\py_src\image_controller\image_provider.py

requestPixmap函数改为:

    def requestPixmap(self, path, size=None, resSize=None):
        print(f"request: {path}")
        print("   ", list(k[-6:] for k in self.pixmapDict.keys()))
        if "/" in path:
            compID, imgID = path.split("/", 1)
            self._delCompCache(compID)  # 先清缓存
            if imgID in self.pixmapDict:
                self.compDict[compID] = imgID  # 记录缓存
                return self.pixmapDict[imgID]
            print(f"[Error] imgID {imgID} not in pixmapDict!")
        else:  # 清空一个组件的缓存
            self._delCompCache(path)
        return self._getNoneImg()  # 返回占位符

后面的 _delCompCache 函数改为:

    def _delCompCache(self, compID):
        if compID in self.compDict:
            last = self.compDict[compID]
            if last in self.pixmapDict:
                print(f"___del: {compID} {last}")
                del self.pixmapDict[last]
            del self.compDict[compID]
Snipaste_2024-01-02_09-20-45 而且有个很迷的问题,在我用HDMI外接显示屏的时候会出现这问题,但是拔掉HDMI,只用笔记本电脑的屏幕,就没有异常颜色块。。。

@hiroi-sora
Copy link
Owner

Umi进行一次截图的流程是:

1. ScreenshotManager.qml 调用 screenshot 函数,开始截图流程
2. screenshot_controller.py 调用 getScreenshot 函数,返回所有N个屏幕的截图
3. ScreenshotManager.qml 生成N个 ScreenshotWindowComp 窗口,覆盖在N个屏幕上
4. 用户鼠标划选区域
5. ScreenshotManager.qml 调用 ssEnd 函数,销毁N个窗口,删除图片缓存
6. 裁切指定范围的图片,结束截图流程

而在你的截图日志中,看到这一行出现了两次:
request:Image__QMLTYPE_160(0x253586402b0)/……cf517c
这是一个异常情况。在第3步,图片组件 0x253586402b0 重复请求 了编号为……cf517c的缓存。第二次请求时,按照我的缓存自动清理机制,……cf517c已经被清理了,已经不存在了。所以只能返回红-蓝-红的缺省图片。(这个颜色是人为设定的缺省图片)。

按理说,图片组件是不会重复请求id相同的缓存的。不知道为什么在你的设备上出现了重复的情况。

不过,既然知道问题发生的直接原因,咱们就能想办法绕开它。请打开UmiOCR-data\py_src\image_controller\image_provider.py,大约34行,原本是这样的:

            compID, imgID = path.split("/", 1)
            self._delCompCache(compID)  # 先清缓存

现在改动self._delCompCache这句,加个限制条件,防止重复请求时删除缓存:

            compID, imgID = path.split("/", 1)
            if compID in self.compDict and self.compDict[compID] != imgID: # 判断不是重复请求
                self._delCompCache(compID)  # 再清缓存

改动后,你的电脑上应该能正常使用双屏截图了。

@lzh1043060917
Copy link
Author

lzh1043060917 commented Jan 3, 2024

Umi进行一次截图的流程是:

1. ScreenshotManager.qml 调用 screenshot 函数,开始截图流程
2. screenshot_controller.py 调用 getScreenshot 函数,返回所有N个屏幕的截图
3. ScreenshotManager.qml 生成N个 ScreenshotWindowComp 窗口,覆盖在N个屏幕上
4. 用户鼠标划选区域
5. ScreenshotManager.qml 调用 ssEnd 函数,销毁N个窗口,删除图片缓存
6. 裁切指定范围的图片,结束截图流程

而在你的截图日志中,看到这一行出现了两次: request:Image__QMLTYPE_160(0x253586402b0)/……cf517c 这是一个异常情况。在第3步,图片组件 0x253586402b0 重复请求 了编号为……cf517c的缓存。第二次请求时,按照我的缓存自动清理机制,……cf517c已经被清理了,已经不存在了。所以只能返回红-蓝-红的缺省图片。(这个颜色是人为设定的缺省图片)。

按理说,图片组件是不会重复请求id相同的缓存的。不知道为什么在你的设备上出现了重复的情况。

不过,既然知道问题发生的直接原因,咱们就能想办法绕开它。请打开UmiOCR-data\py_src\image_controller\image_provider.py,大约34行,原本是这样的:

            compID, imgID = path.split("/", 1)
            self._delCompCache(compID)  # 先清缓存

现在改动self._delCompCache这句,加个限制条件,防止重复请求时删除缓存:

            compID, imgID = path.split("/", 1)
            if compID in self.compDict and self.compDict[compID] != imgID: # 判断不是重复请求
                self._delCompCache(compID)  # 再清缓存

改动后,你的电脑上应该能正常使用双屏截图了。

差不多能用了,不过还是有点小bug,我刚刚在截图的时候,外接屏幕的内容覆盖了一部分当前屏幕的内容。只能在笔记本电脑自身的屏幕这边截图,不能在外接屏幕那边截图。搞不好是设备哪里有问题,估计很难排查。如果太难搞就算了。谢谢了。现在也不是不能用
Snipaste_2024-01-03_09-22-24

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants