我正在运行试验以查看是否可以显示图像并等待使用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
看一下警告,这可能是自我解释的。
问题是,是否有办法实现我的目标?
答案 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