繁体   English   中英

阈值图像数组和渲染的有效方法 - Python / NumPy / OpenCV

[英]Efficient way to threshold image array and render - Python / NumPy / OpenCV

我有一台相机正在将图像数据发送到我的电脑。 从那里我的 python 脚本将 8 位颜色信息(黑色和白色;范围从 0 - 黑色 - 到 255 - 白色)放入一个 numpy 数组中。 该阵列是二维的,第一维高达 384,第二维高达 288 使用 openCV 窗口显示它效果很好,实时视频超过 24fps。

我现在的目标是操纵图像,以便实时视频将任何低于 200 的颜色值显示为 0(全黑),将任何高于 200 的颜色值显示为 255(全白)。 然而,我的代码现在只给我大约 3fps。

我的代码正在执行以下操作:

  • 将来自相机的图像保存在 numpy 数组中
  • 打开第一个for循环以遍历 x 值
  • 在第一个for循环中,使用 y 值遍历第二个for循环
  • 检查每个像素的每个颜色值并检查它是否高于 200
  • 根据if子句使颜色值为 0 或 255
  • 显示新图像

这是代码中的决定性部分:

processedImage = frame
i = 0
for i in range(0, displayedWidth):
    ii = 0
    for ii in range(0, displayedHeight):
        if frame[ii, i] > 200:
            processedImage[ii, i] = 255
        else: 
            processedImage[ii, i] = 0
cv2.imshow("LiveVideo", processedImage)

在这里读到for循环比while循环更快,但它并没有显着提高代码的速度,这就是为什么我假设重写processedImage花费的时间太长。

有没有办法让整个过程更快?

感谢您的任何回答!

试试这个:

frame[frame > 200] = 255
frame[frame <= 200] = 0
cv2.imshow("LiveVideo", frame)

np.where()也可以使用:

processed_frame = np.where(frame >= 200, 255, 0)

例如

>>> im = (np.random.rand(5, 5) * 255).round()
>>> im
array([[ 45.,  92.,  74., 207., 211.],
       [206., 184.,  31., 117., 119.],
       [ 88.,  82., 203.,  34.,   5.],
       [157.,  99., 154., 251.,  54.],
       [160., 177.,  14., 206., 234.]])
>>> np.where(im >= 200, 255, 0)
array([[  0,   0,   0, 255, 255],
       [255,   0,   0,   0,   0],
       [  0,   0, 255,   0,   0],
       [  0,   0,   0, 255,   0],
       [  0,   0,   0, 255, 255]])
>>>

继续使用 NumPy,似乎最快的是 -

(frame>200)*np.uint8(255)

因为,您已经在使用 OpenCV,更快的方法是使用cv2.threshold -

cv2.threshold(frame,200,255,cv2.THRESH_BINARY)[1]

样本运行以验证结果并获取1024X1024图像的时间 -

In [2]: np.random.seed(0)
   ...: frame = np.random.randint(0,256,(1024,1024)).astype(np.uint8)

In [3]: %timeit (frame>200)*np.uint8(255)
253 µs ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [4]: %timeit cv2.threshold(frame,200,255,cv2.THRESH_BINARY)[1]
58.2 µs ± 437 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)    

In [7]: out1 = (frame>200)*np.uint8(255)

In [8]: out2 = cv2.threshold(frame,200,255,cv2.THRESH_BINARY)[1]

In [9]: np.allclose(out1, out2)
Out[9]: True

与其他解决方案对相同数据的计时 -

# @AKX's soln
In [10]: %timeit np.where(frame >= 200, 255, 0)
3.73 ms ± 22.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

# @Seb's soln
In [11]: %%timeit
    ...: frame[frame > 200] = 255
    ...: frame[frame <= 200] = 0
10.2 ms ± 15.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

带有cv2.threshold的 OpenCV 版本似乎是其他版本中最快的。

使用 Seb 的解决方案是一个很大的改进,但似乎使用numpy.where更快:

%%timeit
frame1 = frame.copy()
frame1[frame1 > 200] = 255
frame1[frame1 <= 200] = 0

974 µs ± 19.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

对比

%%timeit
frame2 = frame.copy()
frame2 = np.where(frame2 > 200, 255, 0)

385 µs ± 7.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> np.alltrue(frame1 == frame2)
True

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM