为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Cython 循环遍历像素仍然很慢

使用 Cython 循环遍历像素仍然很慢

海绵宝宝撒 2021-09-14 09:54:09
我在常规 python 代码之间没有速度差异。它说瓶颈是 html 文件中的最后两行代码。有没有办法解决?我想要做的是遍历像素并将 rgb 值低于 210 的坐标添加到列表中。from PIL import Imageimport numpy as npimport timeimport cythonimport cv2filename = "/home/user/PycharmProjects/Testing/files/file001.png"image = Image.open(filename)size = width, height = image.sizeimage_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])
查看完整描述

2 回答

?
白板的微信

TA贡献1883条经验 获得超3个赞

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


在这个答案中我使用,Numba因为我在高性能 Cython 编码方面没有经验,但 Cython 实现应该是直接的。Numba 也有一个有限的列表和元组内部表示,但我不知道 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

时间安排


所有时间都没有编译开销(第一次调用函数被排除在时间之外)。


#Create some data

image_data=np.random.rand(1683*1240).reshape(1683,1240)*255

image_data=image_data.astype(np.uint8)



get_image_data (Pure Python)                   : 3.4s

get_image_data (naive Numba, appending lists)  : 1.1s

get_image_data (naive Numba, appending tuples) : 0.3s

get_image_data_arr:                            : 0.012s

np.argwhere(image_data<210)                    : 0.035s


查看完整回答
反对 回复 2021-09-14
?
HUWWW

TA贡献1874条经验 获得超12个赞

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


import numpy as np


# Create a starting image

im = np.arange(0,255,16).reshape(4,4)                                                      

看起来像这样:


array([[  0,  16,  32,  48],

       [ 64,  80,  96, 112],

       [128, 144, 160, 176],

       [192, 208, 224, 240]])

现在找到所有小于 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]])


查看完整回答
反对 回复 2021-09-14
  • 2 回答
  • 0 关注
  • 214 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号