用Cython still循环像素

2020-12-04 16:48:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我在这里没有发现普通python代码的速度差异。它说瓶颈是html文件中的最后两行代码。有什么办法吗?在

我要做的是循环遍历像素,并将rgb值低于210的坐标添加到列表中。在

from PIL import Image
import numpy as np
import time
import cython
import cv2

filename = "/home/user/PycharmProjects/Testing/files/file001.png"
image = Image.open(filename)
size = width, height = image.size
image_data = np.asarray(image)

cdef list list_text = []

@cython.boundscheck(False)
cpdef get_image_data():
    cdef int y, x
    for y in range(1683):
        for x in range(1240):
            if image_data[y, x] < 210:
                list_text.append([x, y])
3条回答
网友
1楼 ·

我建议使用Numpy的argwhere()函数,如下所示:

import numpy as np

# Create a starting image
im = np.arange(0,255,16).reshape(4,4)                                                      

看起来像这样:

^{pr2}$

现在找到小于210的所有元素的坐标:

np.argwhere(im<210)  

看起来像这样:

array([[0, 0],
       [0, 1],
       [0, 2],
       [0, 3],
       [1, 0],
       [1, 1],
       [1, 2],
       [1, 3],
       [2, 0],
       [2, 1],
       [2, 2],
       [2, 3],
       [3, 0],
       [3, 1]])
网友
2楼 ·

好吧,所以我已经修好了。现在我要知道如何将这些像素坐标保存到二维数组中。因为如果我附加python样式,会减慢整个过程。有什么建议吗?我也不想再次返回image_数据。在

顺便说一句,有趣的是,这段代码比python快28000倍!我希望速度提高100倍,不是这么多。在

@cython.boundscheck(False)
cpdef const unsigned char[:, :] get_image_data(const unsigned char[:, :] image_data):

cdef int x, y
cdef list list_text = []

for y in range(1683):
    for x in range(1240):
        if image_data[y, x] < 210:
            pass
return image_data
网友
3楼 ·

循环没有任何问题,但是将列表附加到列表中非常慢。为了避免这种情况,您可以为数据分配一个足够大的数组,然后再收缩它(或者将数据复制到具有所需大小的数组中),或者使用std:vector实现函数。在

在这个答案中,我使用Numba,因为我在性能Cython编码方面没有那么丰富的经验,但是Cython的实现应该是直接的。Numba对list和tuples也有有限的内部表示,但我不知道Cython中是否也有同样的表示。在

示例

import numpy as np
import numba as nb

@nb.njit()
def get_image_data_arr(image_data):
  array_text = np.empty((image_data.shape[0]*image_data.shape[1],2),dtype=np.int64)
  ii=0
  for y in range(image_data.shape[0]):
    for x in range(image_data.shape[1]):
      if image_data[y, x] < 210:
        array_text[ii,0]=x
        array_text[ii,1]=y
        ii+=1
  return array_text[:ii,:]

@nb.njit()
def get_image_data(image_data):
  list_text = []
  for y in range(image_data.shape[0]):
    for x in range(image_data.shape[1]):
      if image_data[y, x] < 210:
         #appending lists
         list_text.append([x, y])
         #appending tuples
         #list_text.append((x, y))
  return list_text

计时

所有计时都没有编译开销(对函数的第一次调用从计时中排除)。在

^{pr2}$

相关问题