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

我在常规 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])


海绵宝宝撒
浏览 215回答 2
2回答

白板的微信

循环没有任何问题,但将列表附加到列表非常慢。为了避免这种情况,您可以为数据分配一个足够大的数组并在之后缩小它(或将数据复制到具有您需要的确切大小的数组中),或者您可以使用std:vector.在这个答案中我使用,Numba因为我在高性能 Cython 编码方面没有经验,但 Cython 实现应该是直接的。Numba 也有一个有限的列表和元组内部表示,但我不知道 Cython 中是否可用。例子import numpy as npimport numba as nb@nb.njit()def get_image_data_arr(image_data):&nbsp; array_text = np.empty((image_data.shape[0]*image_data.shape[1],2),dtype=np.int64)&nbsp; ii=0&nbsp; for y in range(image_data.shape[0]):&nbsp; &nbsp; for x in range(image_data.shape[1]):&nbsp; &nbsp; &nbsp; if image_data[y, x] < 210:&nbsp; &nbsp; &nbsp; &nbsp; array_text[ii,0]=x&nbsp; &nbsp; &nbsp; &nbsp; array_text[ii,1]=y&nbsp; &nbsp; &nbsp; &nbsp; ii+=1&nbsp; return array_text[:ii,:]@nb.njit()def get_image_data(image_data):&nbsp; list_text = []&nbsp; for y in range(image_data.shape[0]):&nbsp; &nbsp; for x in range(image_data.shape[1]):&nbsp; &nbsp; &nbsp; if image_data[y, x] < 210:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#appending lists&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list_text.append([x, y])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#appending tuples&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#list_text.append((x, y))&nbsp; return list_text时间安排所有时间都没有编译开销(第一次调用函数被排除在时间之外)。#Create some dataimage_data=np.random.rand(1683*1240).reshape(1683,1240)*255image_data=image_data.astype(np.uint8)get_image_data (Pure Python)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: 3.4sget_image_data (naive Numba, appending lists)&nbsp; : 1.1sget_image_data (naive Numba, appending tuples) : 0.3sget_image_data_arr:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : 0.012snp.argwhere(image_data<210)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : 0.035s

HUWWW

我建议使用 Numpy 的argwhere()函数如下:import numpy as np# Create a starting imageim = np.arange(0,255,16).reshape(4,4)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;看起来像这样:array([[&nbsp; 0,&nbsp; 16,&nbsp; 32,&nbsp; 48],&nbsp; &nbsp; &nbsp; &nbsp;[ 64,&nbsp; 80,&nbsp; 96, 112],&nbsp; &nbsp; &nbsp; &nbsp;[128, 144, 160, 176],&nbsp; &nbsp; &nbsp; &nbsp;[192, 208, 224, 240]])现在找到所有小于 210 的元素的坐标:np.argwhere(im<210)&nbsp;&nbsp;看起来像这样:array([[0, 0],&nbsp; &nbsp; &nbsp; &nbsp;[0, 1],&nbsp; &nbsp; &nbsp; &nbsp;[0, 2],&nbsp; &nbsp; &nbsp; &nbsp;[0, 3],&nbsp; &nbsp; &nbsp; &nbsp;[1, 0],&nbsp; &nbsp; &nbsp; &nbsp;[1, 1],&nbsp; &nbsp; &nbsp; &nbsp;[1, 2],&nbsp; &nbsp; &nbsp; &nbsp;[1, 3],&nbsp; &nbsp; &nbsp; &nbsp;[2, 0],&nbsp; &nbsp; &nbsp; &nbsp;[2, 1],&nbsp; &nbsp; &nbsp; &nbsp;[2, 2],&nbsp; &nbsp; &nbsp; &nbsp;[2, 3],&nbsp; &nbsp; &nbsp; &nbsp;[3, 0],&nbsp; &nbsp; &nbsp; &nbsp;[3, 1]])
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python