从Python中的二进制蒙版检索轮廓蒙版的快速方法 [英] Fast method to retrieve contour mask from a binary mask in Python

查看:149
本文介绍了从Python中的二进制蒙版检索轮廓蒙版的快速方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个实时应用程序,其中涉及查找二进制掩码的边缘.我需要快速的东西,如果可能的话,没有GPU,希望每个图像的运行时间低于0.0005秒,并且大小为(1000,1000).我将使用下面的二进制图像示例,其大小为(1000,1000).

I want to make a realtime application, which involves finding the edges of a binary mask. I need something fast, without GPU if possible, that runs hopefully below 0.0005 secs per image, with size (1000,1000). I will be using the following example of a binary image ,with size (1000,1000).

(要复制的代码:)

import numpy as np
im=np.zeros((1000,1000),dtype=np.uint8)
im[400:600,400:600]=255

图片

快速执行操作的第一种逻辑方法是使用OpenCV库:

The first logical way to do things fast was to use the OpenCV library:

import cv2
timeit.timeit(lambda:cv2.Laplacian(im,cv2.CV_8U),number=100)/100
0.0011617112159729003

如预期的那样导致: 拉普拉斯语

which as expected resulted in: laplacian

我发现这种方式非常耗时.之后,我尝试了findContours:

I found this way very time consuming. After this I tried findContours:

 def usingcontours(im):
    points=np.transpose(cv2.findContours(im,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[1][0])
    tmp=np.zeros_like(im)
    tmp[tuple(points)]=255
    return tmp 
timeit.timeit(lambda:usingcontours(im),number=100)/100
0.0009052801132202148

给出与上面相同的结果. 这样比较好,但仍然不如我想要的好.我继续使用numpy,最后使用梯度近似拉普拉斯算子,尽管我知道情况会更糟:

which gave the same result as above. This is better, but still not as good as I would like. I moved on with usage of numpy, to approximate laplacian using gradient, as last resort, although I knew it would be worse:

def usinggradient(im):
    tmp=np.gradient(im)
    return ((tmp[0]+tmp[1])>0).astype(np.uint8)
timeit.timeit(lambda:usinggradient(im),number=100)/100
0.018681130409240722

那么,对于我如何加速算法,还有其他人有进一步的想法吗?我强调我希望将此算法用于二进制图像,因此我想必须有一个更好的实现.

So, has anyone any further idea on how I can accelerate my algorithm? I emphasize that I want this algorithm to be used for binary images, so I guess there must be a better implementation.

推荐答案

我使用cv2.findContours选择了最快的速度来加快速度.在其中,我们可以用简单的

I picked the fastest one with cv2.findContours to speed that up. In it, we could replace those expensive transpose and converting to tuple parts with simple slicing, like so -

idx = cv2.findContours(im,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[1][0]
out = np.zeros_like(im)
out[idx[:,0,0],idx[:,0,1]] = 255

运行时测试-

In [114]: # Inputs
     ...: im=np.zeros((1000,1000),dtype=np.uint8)
     ...: im[400:600,400:600]=255
     ...: idx = cv2.findContours(im,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[1][0]
     ...: 

In [115]: def original_app(im, idx):
     ...:     points=np.transpose(idx)
     ...:     tmp=np.zeros_like(im)
     ...:     tmp[tuple(points)]=255
     ...:     return tmp
     ...: 
     ...: def proposed_app(im, idx):
     ...:     out = np.zeros_like(im)
     ...:     out[idx[:,0,0],idx[:,0,1]] = 255
     ...:     return out
     ...: 

In [120]: %timeit original_app(im, idx)
10000 loops, best of 3: 108 µs per loop

In [121]: %timeit proposed_app(im, idx)
10000 loops, best of 3: 101 µs per loop

In [122]: %timeit cv2.findContours(im,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
1000 loops, best of 3: 1.55 ms per loop

因此,所提出的方法在此方面有一些改进,但与轮廓查找本身相比,可以忽略不计.

So, there's some marginal improvement there with the proposed method, but that seems negligible compared to the contour-finding itself.

我查看了 scikit-image's version 并进行了快速测试,似乎比OpenCV版本要慢得多.

I looked into scikit-image's version and ran a quick test and seems like it's much slower than OpenCV version.

这篇关于从Python中的二进制蒙版检索轮廓蒙版的快速方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆