一种更快的方法来删除近似像素

时间:2018-03-24 17:10:10

标签: python numpy

我的图像有一个粗线像素,下面有一行。我想

  1. 删除底线
  2. 细粗线
  3. 所以我使用了这个循环:

    N = 1000
    im = (np.random.random((N, N)) - 0.5)
    
    xx,yy =  np.where(im > 0)
    for x,y in zip(xx,yy):
        for i in range(xmin,xmax):  # I played with the limits so they would fit my specific image
            # if inner loop already broke
            if im[x][y] == False:
                break
            for j in range(ymin,ymax):  # here again
                if im[x-i][y+j]:
                    im[x][y] = False
                    break   
    

    这非常适合(大约95%的不需要的像素被移除)但它非常慢......我每张图片花费大约1秒钟,其中像np.where, np.argmax这样的操作需要< 0.01秒

    如何使用numpy(我猜numpy最适合)来加快速度呢?

    编辑: 使用@numba.jit按照@jmd_dk的建议非常有用,但它似乎仍然比普通numpy方法慢

    为了澄清,我不仅要找到np.where(im > 0)提供的正像素的位置,还要查找在其下方/上方有正像素的像素的位置...

    所以,如果我有这个矩阵:

    0 | 0 | 0 | 1 | 1 | 1 | 0
    0 | 0 | 0 | 0 | 0 | 0 | 1
    0 | 1 | 0 | 1 | 0 | 1 | 1
    0 | 0 | 0 | 1 | 1 | 0 | 1
    0 | 0 | 0 | 0 | 0 | 0 | 1
    0 | 1 | 0 | 1 | 1 | 1 | 1
    

    我想找到所有'1'像素,其上方有'1'并删除它们 - 获取此矩阵:

    0 | 0 | 0 | 1 | 1 | 1 | 0
    0 | 0 | 0 | 0 | 0 | 0 | 1
    0 | 1 | 0 | * | 0 | * | *
    0 | 0 | 0 | * | * | 0 | *
    0 | 0 | 0 | 0 | 0 | 0 | *
    0 | * | 0 | * | * | * | *
    

    我将1替换为*所以它会突然出现......

1 个答案:

答案 0 :(得分:1)

这是Numba真正闪耀的情况。没有任何实际工作,我立即获得~115x的加速(次数,而不是百分比!)。我没有你的整个代码,但请考虑这个例子:

import numpy as np
import numba
from time import time

@numba.jit
def fun():
    # Added just to make the code run
    t0 = time()
    N = 1000
    im = (np.random.random((N, N)) - 0.5)
    xmin = ymin = 0
    xmax = ymax = N
    # Your code
    xx,yy =  np.where(im > 0)[0], np.where(im > 0)[1]
    for x,y in zip(xx,yy):
        for i in range(xmin,xmax):
            if im[x][y] == False:
                break
            for j in range(ymin,ymax):
                if im[x-i][y+j]:
                    im[x][y] = False
                    break
    t1 = time()
    print('took', t1 - t0, 's')

fun() 
fun()

在我的机器上,我得到了

  

取0.18608522415161133 s

     

花了0.0416417121887207 s

现在删除numba.jit装饰器,我得到

  

采取了4.783859491348267 s

     

采取了4.796429872512817 s

获取Numba包的最简单方法是使用Anaconda Python发行版。

然后,您应该为每个图像调用一次函数(此处为fun())。第一次调用该函数时,Numba会将其编译为快速代码,这就是为什么第一次调用比第二次调用慢得多(尽管仍然比普通的非Numba版本快得多)。