在 python 中使用 for 循环将 skimage.filters.threshold_otsu() 应用于 image/array 中的段列表时遇到问题
Facing problem while using for loop in python for applying skimage.filters.threshold_otsu() to a list of segments in an image/array
我的问题在下面解释得很清楚:
import numpy as np
from skimage.util.shape import view_as_blocks
from skimage.filters import threshold_otsu
我读取了一个灰度图像作为数组"arr",其形状是:
>>arr.shape
(10000, 15200)
我将该图像分割成 25*38 块。其中,每个块中有 400*400 像素,使用:
>>img= view_as_blocks(arr, block_shape=(400,400))
>>img.shape
(25, 38, 400, 400)
现在,当我使用 threshold_otsu() 分别查找每个段的阈值时,我得到这些值:
print(threshold_otsu(img[11,6],16))
-14.606459
print(threshold_otsu(img[11,7],16))
-15.792943
print(threshold_otsu(img[11,11],16))
-15.547393
print(threshold_otsu(img[12,16],16))
-16.170353
但是当我使用 for 循环 一次获取所有阈值时,我得到了不同的值。
>>crdf
array([[11, 6],
[11, 7],
[11, 11],
[12, 16],
[10, 9],
[21, 26],
[15, 15],
[12, 17],
[12, 12],
[14, 10],
[20, 26]], dtype=int64)
>>for i in range(0,4):
>>print(threshold_otsu(img[crdf[i]],16))
-14.187654
-14.187654
-14.187654
-13.238304
我在 for 循环中做错了吗?如果不是,为什么当我对每个段单独执行时以及当我使用 for 循环对相同的相应段进行迭代时,我得到不同的阈值。
当您使用一个 Numpy 数组索引到另一个 Numpy 数组时,您会触发 advanced indexing,它的工作方式与基本索引不同,因此会产生您意想不到的结果。
为了使用基本索引,您需要确保使用逗号分隔的整数或标准 Python 元组进行索引。
因此,快速解决方法是将索引转换为元组:
img[tuple(crdf[i])]
但最好不要将 Numpy 数组用于索引列表。如果您不对索引批量执行数学运算,或者您的索引列表很短,那么通过将其设为数组,您将无法获得任何性能提升,甚至可能会因为创建初始数组并将其转换回元组的开销而损失一些性能稍后。
尝试索引对的简单列表,其中索引对本身是元组:
crdf = [
(11, 6),
(11, 7),
(11, 11),
(12, 16),
(10, 9),
(21, 26),
(15, 15),
(12, 17),
(12, 12),
(14, 10),
(20, 26)
]
# then you can iterate and index directly, without conversion:
for i in range(0, 4):
print(threshold_otsu(img[crdf[i]], 16))
# or even like this, which is usually more idiomatic and easier to read:
for pair in crdf[:4]:
print(threshold_otsu(img[pair], 16))
如果您收到 crdf
作为其他处理的结果,并且它已经是一个 Numpy 数组,您也可以先将其一次性转换为元组列表:
crdf = [tuple(pair) for pair in crdf]
我的问题在下面解释得很清楚:
import numpy as np
from skimage.util.shape import view_as_blocks
from skimage.filters import threshold_otsu
我读取了一个灰度图像作为数组"arr",其形状是:
>>arr.shape
(10000, 15200)
我将该图像分割成 25*38 块。其中,每个块中有 400*400 像素,使用:
>>img= view_as_blocks(arr, block_shape=(400,400))
>>img.shape
(25, 38, 400, 400)
现在,当我使用 threshold_otsu() 分别查找每个段的阈值时,我得到这些值:
print(threshold_otsu(img[11,6],16))
-14.606459
print(threshold_otsu(img[11,7],16))
-15.792943
print(threshold_otsu(img[11,11],16))
-15.547393
print(threshold_otsu(img[12,16],16))
-16.170353
但是当我使用 for 循环 一次获取所有阈值时,我得到了不同的值。
>>crdf
array([[11, 6],
[11, 7],
[11, 11],
[12, 16],
[10, 9],
[21, 26],
[15, 15],
[12, 17],
[12, 12],
[14, 10],
[20, 26]], dtype=int64)
>>for i in range(0,4):
>>print(threshold_otsu(img[crdf[i]],16))
-14.187654
-14.187654
-14.187654
-13.238304
我在 for 循环中做错了吗?如果不是,为什么当我对每个段单独执行时以及当我使用 for 循环对相同的相应段进行迭代时,我得到不同的阈值。
当您使用一个 Numpy 数组索引到另一个 Numpy 数组时,您会触发 advanced indexing,它的工作方式与基本索引不同,因此会产生您意想不到的结果。
为了使用基本索引,您需要确保使用逗号分隔的整数或标准 Python 元组进行索引。
因此,快速解决方法是将索引转换为元组:
img[tuple(crdf[i])]
但最好不要将 Numpy 数组用于索引列表。如果您不对索引批量执行数学运算,或者您的索引列表很短,那么通过将其设为数组,您将无法获得任何性能提升,甚至可能会因为创建初始数组并将其转换回元组的开销而损失一些性能稍后。
尝试索引对的简单列表,其中索引对本身是元组:
crdf = [
(11, 6),
(11, 7),
(11, 11),
(12, 16),
(10, 9),
(21, 26),
(15, 15),
(12, 17),
(12, 12),
(14, 10),
(20, 26)
]
# then you can iterate and index directly, without conversion:
for i in range(0, 4):
print(threshold_otsu(img[crdf[i]], 16))
# or even like this, which is usually more idiomatic and easier to read:
for pair in crdf[:4]:
print(threshold_otsu(img[pair], 16))
如果您收到 crdf
作为其他处理的结果,并且它已经是一个 Numpy 数组,您也可以先将其一次性转换为元组列表:
crdf = [tuple(pair) for pair in crdf]