问题描述:
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions.
D:\Instance\_Segmentation\yolov5\_moguimianju\yolov5-seg-master\venv\Scripts\python.exe D:/Instance\_Segmentation/yolov5\_moguimianju/yolov5-seg-master/scripts/visual\_coco128.py
Traceback (most recent call last):
File "D:/Instance\_Segmentation/yolov5\_moguimianju/yolov5-seg-master/scripts/visual\_coco128.py", line 13, in <module>
mask = np.array(list(map(lambda x\:np.array(x.strip().split()), f.readlines())))
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (8,) + inhomogeneous part.
Process finished with exit code 1
源码如下:
import os, cv2
import numpy as np
img_base_path = '../dataset/coco128-seg/images/train2017'
lab_base_path = '../dataset/coco128-seg/labels/train2017'
label_path_list = [i.split('.')[0] for i in os.listdir(img_base_path)]
for path in label_path_list:
image = cv2.imread(f'{img_base_path}/{path}.jpg')
h, w, c = image.shape
label = np.zeros((h, w), dtype=np.uint8)
with open(f'{lab_base_path}/{path}.txt') as f:
mask = np.array(list(map(lambda x:np.array(x.strip().split()), f.readlines())))
for i in mask:
i = np.array(i, dtype=np.float32)[1:].reshape((-1, 2))
i[:, 0] *= w
i[:, 1] *= h
label = cv2.fillPoly(label, [np.array(i, dtype=np.int32)], color=255)
image = cv2.bitwise_and(image, image, mask=label)
cv2.imshow('Pic', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
问题解答:
❌ 原始错误代码:
mask = np.array(list(map(lambda x:np.array(x.strip().split()), f.readlines())))
❓问题出在哪里?
-
f.readlines()
读取了每一行标签文本。 -
每行使用
.strip().split()
拆分成字符串列表,再用np.array(...)
转为 NumPy 数组。 -
最后外面再包一层
np.array(...)
,想把这些“坐标数组”变成二维数组。
但——
🧨 每一行的长度不同!
比如,COCO格式的 segmentation 标签如下:
0 0.1 0.2 0.3 0.4
0 0.2 0.3 0.4 0.5 0.6 0.7
-
第一行是 5 个元素,第二行是 7 个元素;
-
NumPy 无法将
[array([5元素]), array([7元素])]
拼成一个二维数组,报错:ValueError: setting an array element with a sequence.
✅ 我改了哪一行?
我把这句:
mask = np.array(list(map(lambda x:np.array(x.strip().split()), f.readlines())))
改成了两步:
mask_lines = f.readlines()
mask_list = [list(map(float, line.strip().split())) for line in mask_lines]
✅ 为什么这样就对了?
-
我保留每一行作为一个“单独的 list”(Python 列表),不用 NumPy 去强制拼二维数组;
-
mask_list
是一个 list of lists,每一项仍然保留原始坐标点信息; -
后续你本来就要
for i in mask:
一行一行处理,因此根本 不需要合成二维数组!
🔍 总结一下错误原因:
原写法问题 | 改写后解决方法 |
---|---|
强行将不规则的坐标列表转为 NumPy 2D 数组 | 保留为 list of lists(Python 列表),逐行处理 |
触发 NumPy 的 shape 校验机制(维度不一致) | 避免使用 np.array(...) 合并非等长行 |
修改后的完整代码如下:
import os, cv2
import numpy as np
img_base_path = '../dataset/coco128-seg/images/train2017'
lab_base_path = '../dataset/coco128-seg/labels/train2017'
label_path_list = [i.split('.')[0] for i in os.listdir(img_base_path)]
for path in label_path_list:
image = cv2.imread(f'{img_base_path}/{path}.jpg')
h, w, c = image.shape
label = np.zeros((h, w), dtype=np.uint8)
with open(f'{lab_base_path}/{path}.txt') as f:
mask_lines = f.readlines()
mask_list = [list(map(float, line.strip().split())) for line in mask_lines]
for i in mask_list:
i = np.array(i, dtype=np.float32)[1:].reshape((-1, 2))
i[:, 0] *= w
i[:, 1] *= h
label = cv2.fillPoly(label, [np.array(i, dtype=np.int32)], color=255)
image = cv2.bitwise_and(image, image, mask=label)
cv2.imshow('Pic', image)
cv2.waitKey(0)
cv2.destroyAllWindows()