使用opencv和asyncio Python 3.6显示图像

时间:2018-01-26 15:28:48

标签: python-3.x opencv3.0 python-asyncio

我正在运行试验以查看是否可以显示图像并等待使用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

看一下警告,这可能是自我解释的。

问题是,是否有办法实现我的目标?

2 个答案:

答案 0 :(得分:1)

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

我无法找到任何普遍的解决方案,但所有讨论的主要观点是:

  

问题是通常必须进行事件和图形函数调用   在主线程中完成。所以你别无选择。把它放在   主线。

最明显的做法我现在可以想到的是使用ProcessPoolExecutor而不是run_in_executor default 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。我没有检查如果图像不存在或无法加载会发生什么,以防万一你确保你能够在没有asyncio的情况下做到这一点。

答案 1 :(得分:0)

显然是一个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