加速图像上的逐像素操作
Speeding up the pixel by pixel operations on the image
我正在尝试对图像执行逐像素操作,但速度非常慢。一张尺寸(512*512)的图片需要7-8个小时,而我的图片最大为2048*2048。
我也尝试过使用 Numba 对其进行优化,但由于存在大量 pyobjects
而它花费的时间相同,这是根据 this 教程很糟糕,因为 numba 无法将变量转换成它理解的东西,因此无法优化。
以下是我的问题的简短版本,我附上了完整的细节
所以,现在我正在尝试按照 this 使用 cython
教程。
以下是我的代码,我正在尝试对其进行优化-
img = Image.open(path_dir)
pixelMap = img.load()
roi = []
for i in range(img.size[0]):
for j in range(img.size[1]):
if pix[i,j] == 255:
roi.append([i,j])
notroi = img.size[0]*img.size[1] - len(roi)
在这上面,花不了多少时间,我也不需要修改。
def roifun(img,roi,notroi,newmap,pix):
while(notroi):
border_pixels = []
h = img.size[0]
w = img.size[1]
for i in range(0,h): //---1
for j in range(0,w):
if [i,j] not in roi and ([i+1, j] in roi or [i-1, j] in roi or [i, j+1] in roi or [i, j-1] in roi):
border_pixels.append([i,j])
for (each_i,each_j) in border_pixels: //---2
color_sum = 0
count = 1
eight_neighbourhood = [[each_i-1,each_j],[each_i+1,each_j],[each_i,each_j-1],[each_i,each_j+1],[each_i-1,each_j-1],[each_i-1,each_j+1],[each_i+1,each_j-1],[each_i+1,each_j+1]]
for pix_i,pix_j in eight_neighbourhood:
if (pix_i,pix_j) in roi:
color_sum+=pix[pix_i,pix_j]
count+=1
newmap[each_i,each_j]=(color_sum//count)
for (i,j) in border_pixels: //----3
roi.append([i,j])
border_pixels.remove([i,j])
notroi = notroi-1
print(notroi)
现在,我只是将上述代码转换为cython的问题分为3部分(根据他们的for循环),以便于调试。
我把第一个循环转换成下面的方式-
%%cython -a
import cython
cimport numpy as np
# @cython.boundscheck(False)
cpdef border(img,roi):
border_pixels = []
cdef long h,w,i,j
h = img.shape[0]
w = img.shape[1]
for i in range(0,h):
for j in range(0,w):
if [i,j] not in roi and ([i+1, j] in roi or [i-1, j] in roi or [i, j+1] in roi or [i, j-1] in roi):
border_pixels.append([i,j])
我遇到的问题-
1)调用border
函数时得到TypeError: a bytes-like object is required, not 'list'
.
我不知道为什么它希望列表在 byte like object
中以及如何做到这一点。
2)我不知道如何以cython方式转换图像,我尝试将其转换为char[:,:]
但随后出现错误TypeError: a bytes-like object is required, not 'GIFImageFile
。
在第二个循环中,我会遇到同样的问题,但现在我还必须尝试将 pix
转换为 pixel object
.
以防万一,如果你们想知道我想要实现什么,完整的细节在这个问题中。
Expanding the Region of interest of an image
不使用 cython 的任何其他方式也值得赞赏。
我肯定会考虑使用 scikit-image 或至少将 numpy 用于任何需要处理图像像素的地方。在纯 python 中会花费太长时间。
要使用 skimage 重现您的第一段代码,我会这样做:
from skimage import io
img = io.imread(path_dir)
mask = img == 255
这将为您提供一个 True/False 值的 numpy 数组,其中像素等于 255。然后您可以扩大该掩码以获得扩展的感兴趣区域。
我正在尝试对图像执行逐像素操作,但速度非常慢。一张尺寸(512*512)的图片需要7-8个小时,而我的图片最大为2048*2048。
我也尝试过使用 Numba 对其进行优化,但由于存在大量 pyobjects
而它花费的时间相同,这是根据 this 教程很糟糕,因为 numba 无法将变量转换成它理解的东西,因此无法优化。
以下是我的问题的简短版本,我附上了完整的细节 所以,现在我正在尝试按照 this 使用 cython 教程。 以下是我的代码,我正在尝试对其进行优化-
img = Image.open(path_dir)
pixelMap = img.load()
roi = []
for i in range(img.size[0]):
for j in range(img.size[1]):
if pix[i,j] == 255:
roi.append([i,j])
notroi = img.size[0]*img.size[1] - len(roi)
在这上面,花不了多少时间,我也不需要修改。
def roifun(img,roi,notroi,newmap,pix):
while(notroi):
border_pixels = []
h = img.size[0]
w = img.size[1]
for i in range(0,h): //---1
for j in range(0,w):
if [i,j] not in roi and ([i+1, j] in roi or [i-1, j] in roi or [i, j+1] in roi or [i, j-1] in roi):
border_pixels.append([i,j])
for (each_i,each_j) in border_pixels: //---2
color_sum = 0
count = 1
eight_neighbourhood = [[each_i-1,each_j],[each_i+1,each_j],[each_i,each_j-1],[each_i,each_j+1],[each_i-1,each_j-1],[each_i-1,each_j+1],[each_i+1,each_j-1],[each_i+1,each_j+1]]
for pix_i,pix_j in eight_neighbourhood:
if (pix_i,pix_j) in roi:
color_sum+=pix[pix_i,pix_j]
count+=1
newmap[each_i,each_j]=(color_sum//count)
for (i,j) in border_pixels: //----3
roi.append([i,j])
border_pixels.remove([i,j])
notroi = notroi-1
print(notroi)
现在,我只是将上述代码转换为cython的问题分为3部分(根据他们的for循环),以便于调试。
我把第一个循环转换成下面的方式-
%%cython -a
import cython
cimport numpy as np
# @cython.boundscheck(False)
cpdef border(img,roi):
border_pixels = []
cdef long h,w,i,j
h = img.shape[0]
w = img.shape[1]
for i in range(0,h):
for j in range(0,w):
if [i,j] not in roi and ([i+1, j] in roi or [i-1, j] in roi or [i, j+1] in roi or [i, j-1] in roi):
border_pixels.append([i,j])
我遇到的问题-
1)调用border
函数时得到TypeError: a bytes-like object is required, not 'list'
.
我不知道为什么它希望列表在 byte like object
中以及如何做到这一点。
2)我不知道如何以cython方式转换图像,我尝试将其转换为char[:,:]
但随后出现错误TypeError: a bytes-like object is required, not 'GIFImageFile
。
在第二个循环中,我会遇到同样的问题,但现在我还必须尝试将 pix
转换为 pixel object
.
以防万一,如果你们想知道我想要实现什么,完整的细节在这个问题中。
Expanding the Region of interest of an image
不使用 cython 的任何其他方式也值得赞赏。
我肯定会考虑使用 scikit-image 或至少将 numpy 用于任何需要处理图像像素的地方。在纯 python 中会花费太长时间。
要使用 skimage 重现您的第一段代码,我会这样做:
from skimage import io
img = io.imread(path_dir)
mask = img == 255
这将为您提供一个 True/False 值的 numpy 数组,其中像素等于 255。然后您可以扩大该掩码以获得扩展的感兴趣区域。