调整存储在数组中的所有图像的大小
Resize all images stored in array
我将通过 cv2.imread
读取的图像存储在数组 masks
中。数组的形状是(10, 5248, 7936, 3) (10 images, image height, image width, 3 channels)
.
我现在正在尝试复制此数组,但每个图像的大小都已调整为值 monitor_h
和 monitor_w
。这是我拥有的:
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
for i in range(masks.shape[0]):
resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))
但我从 cv2.imshow
获得的图像是黑白的。频道一定发生了什么事。有线索吗?
所以我找到了解决问题的方法,但我仍然想知道是什么导致图像变成黑白的。
这是我想出的:
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
resized_masks = list(resized_masks)
for i in range(len(resized_masks)):
resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))
resized_masks = np.asarray(resized_masks)
要了解为什么您的图像会变成黑白,让我们逐句查看代码。
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
此行默认创建类型为 np.float
的数组。
resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))
这一行将 cv2.resize
的结果分配给 resized_masks
.
的一片
您的原始图像以及 cv2.resize
的结果可能属于 np.uint8
类型。赋值将值转换为 float
s 以将它们放入缓冲区。转换本身很好:5
转换为 5.0
,255
转换为 255.0
。问题是 float
值被解释为被裁剪到范围 [0.0, 1.0]
,而不是 [0.0, 255.0]
。因此,您最终得到的图像实际上全是 0 和 1,即使它们包含看起来正确的值。
您可以通过显示
来验证这些值是否正确
resized_masks.astype(masks.dtype)
这不是真正的修复。真正的解决方法是从正确的输出类型开始:
resized_masks = np.empty((masks.shape[0], monitor_h, monitor_w, masks.shape[3]), dtype=masks.dtype)
请注意,通常将元组用于形状而不是列表,但这在功能上无关紧要。
现在让我们看看为什么您的 有效。
resized_masks = list(resized_masks)
这会创建一个 Python 每个子数组的引用列表。因为你真的在切片,它们仍然会指向引擎盖下的一个连续缓冲区,但重要的是每个 resized_masks[i]
都是一个单独的引用,而不是同一个数组对象的切片。
resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))
由于 resized_masks
是一个包含引用的列表,现在将 cv2.resize
的结果分配给第 i
个列表元素,而不是将内容分配到适当大小的切片中。这里不需要 list
包装器,因为它引入了不必要的维度。
resized_masks = np.asarray(resized_masks)
这只是将列表重新组合成一个数组,因为所有元素的大小都正确(尽管您会看到一个额外的单位维度,如上所述)。正如您所想象的那样,此解决方案效率极低。除了要往返于列表并分配多个不必要的缓冲区这一事实之外,您还丢弃了原始 np.empty
数组而不使用它。
你的补丁大致相当于做
resized_masks = np.array([cv2.resize(np.copy(mask), (monitor_w, monitor_h)) for mask in masks])
我不建议这样做。
我将通过 cv2.imread
读取的图像存储在数组 masks
中。数组的形状是(10, 5248, 7936, 3) (10 images, image height, image width, 3 channels)
.
我现在正在尝试复制此数组,但每个图像的大小都已调整为值 monitor_h
和 monitor_w
。这是我拥有的:
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
for i in range(masks.shape[0]):
resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))
但我从 cv2.imshow
获得的图像是黑白的。频道一定发生了什么事。有线索吗?
所以我找到了解决问题的方法,但我仍然想知道是什么导致图像变成黑白的。
这是我想出的:
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
resized_masks = list(resized_masks)
for i in range(len(resized_masks)):
resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))
resized_masks = np.asarray(resized_masks)
要了解为什么您的图像会变成黑白,让我们逐句查看代码。
resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
此行默认创建类型为 np.float
的数组。
resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))
这一行将 cv2.resize
的结果分配给 resized_masks
.
您的原始图像以及 cv2.resize
的结果可能属于 np.uint8
类型。赋值将值转换为 float
s 以将它们放入缓冲区。转换本身很好:5
转换为 5.0
,255
转换为 255.0
。问题是 float
值被解释为被裁剪到范围 [0.0, 1.0]
,而不是 [0.0, 255.0]
。因此,您最终得到的图像实际上全是 0 和 1,即使它们包含看起来正确的值。
您可以通过显示
来验证这些值是否正确resized_masks.astype(masks.dtype)
这不是真正的修复。真正的解决方法是从正确的输出类型开始:
resized_masks = np.empty((masks.shape[0], monitor_h, monitor_w, masks.shape[3]), dtype=masks.dtype)
请注意,通常将元组用于形状而不是列表,但这在功能上无关紧要。
现在让我们看看为什么您的
resized_masks = list(resized_masks)
这会创建一个 Python 每个子数组的引用列表。因为你真的在切片,它们仍然会指向引擎盖下的一个连续缓冲区,但重要的是每个 resized_masks[i]
都是一个单独的引用,而不是同一个数组对象的切片。
resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))
由于 resized_masks
是一个包含引用的列表,现在将 cv2.resize
的结果分配给第 i
个列表元素,而不是将内容分配到适当大小的切片中。这里不需要 list
包装器,因为它引入了不必要的维度。
resized_masks = np.asarray(resized_masks)
这只是将列表重新组合成一个数组,因为所有元素的大小都正确(尽管您会看到一个额外的单位维度,如上所述)。正如您所想象的那样,此解决方案效率极低。除了要往返于列表并分配多个不必要的缓冲区这一事实之外,您还丢弃了原始 np.empty
数组而不使用它。
你的补丁大致相当于做
resized_masks = np.array([cv2.resize(np.copy(mask), (monitor_w, monitor_h)) for mask in masks])
我不建议这样做。