使用 opencv 和 asyncio 显示图像 Python 3.6

Displaying an image with opencv and asyncio Python 3.6

我是 运行 一个试验,看看我是否可以显示图像并等待 opencv3 作为异步程序中的一个进程的按键。令我震惊的是,这是我想做的事情的核心,我最好先检查一下。所以这是代码:

import asyncio
import cv2
import functools


def load_img(image):
    print(image)
    im = cv2.imread(image, cv2.IMREAD_GRAYSCALE)
    _, inv = cv2.threshold(im, 150, 255, cv2.THRESH_BINARY_INV)
    cv2.GaussianBlur(inv, (3, 3), 0)
    cv2.imshow('Async test', inv)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    return


async def test():
    tiff_img = 'Im1.tiff'
    await loop.run_in_executor(None, functools.partial(load_img, 
                                                       image=tiff_img))

    return


async def numbers():
    for number in range(200):
        await asyncio.sleep(0.5)
        print(number)
    return

if __name__ == '__main__':

    loop = asyncio.get_event_loop()
    single = asyncio.gather(test(), numbers())
    loop.run_until_complete(single)

输出为:

Im1.tiff
2018-01-26 15:22:11.091 python3.6[2784:215235] WARNING: nextEventMatchingMask should only be called from the Main Thread! This will throw an exception in the future.
0
1
2
3
4

看看警告,它可能是不言自明的。

问题是有没有办法达到我的目的??

同样,您的代码在 Windows 上运行完美。看来问题与 macOS 版本的 OpenCV 和谷歌搜索有关 shows 你不仅仅是一个。

我找不到任何通用修复程序,但所有讨论的主要思想是:

the problem is that usually events and graphic function calls must be done in the main thread. So you have no choice here. Put that in the main thread.

我现在能想到的最明显的方法是使用 ProcessPoolExecutor 而不是 run_in_executordefault ThreadPoolExecutor。

像这样更改您的代码:

from concurrent.futures import ProcessPoolExecutor
executor = ProcessPoolExecutor(1)

# ...

async def test():
    tiff_img = 'Im1.tiff'
    await loop.run_in_executor(
        executor, 
        functools.partial(load_img, image=tiff_img)
    )

抱歉,我无法在 macOS 上进行测试,但此版本也适用于 Windows。


P.S。我没有检查如果图像不存在或无法加载会发生什么,以防万一确保你能够在没有异步的情况下完成它。

很明显是 macOS 问题。寻求替代方法,这很有帮助 How to show PIL images on the screen?

出于我的目的,我没有使用 PIL,而是使用了一个评分较低的答案,建议使用 macOS 本机图像查看器。我用

替换了上面的 load_img() 和 test()
def sync_show(image):
    """
    Blocking
    macOS method of displaying image in a preview pane
    """
    os.system("open {}".format(image))
    return


async def test_show(img):
    """use ProcessPoolExecutor"""
    await loop.run_in_executor(executor, sync_show, img)
    return