地面真值图像到一个热编码阵列(语义分割)
Ground Truth Image to One Hot Encoded Array (Semantic Segmentation)
我正在为人物和街道分割创建自己的数据集。在下方,您会看到一个标记为 Ground Truth (GT) 的图像。
以前我做过简单的模型输出和GT Image的Regression(以前只用Streets)。现在我读到,交叉熵损失在这种情况下更为常见。因为,我的 GT 和模型输出图像具有与输入图像相同的宽度 w 和高度 h,所以我必须创建一个数组大小 h x w x c,其中 c 是classes 的数量(在我的例子中是 3,背景,街道,人)。我想,这叫做 One-Hot-Encoded Array。
我按如下方式解决了这个问题:
for height in range(len(img_as_np_array)):
for width in range(len(img_as_np_array[0])):
temp = np.zeros(classes)
if get_class(img_as_np_array[height,width]) == 1:
temp[1] = 1
one_hot_label[height,width] = temp
if get_class(img_as_np_array[height,width]) == 2:
temp[2] = 1
one_hot_label[height,width] = temp
其中 get_class(channels) 方法通过像素的颜色决定像素 class。
def get_class(channels):
threshold = 40
# Class 1 corresponds to streets, roads
if channels[0] in np.arange(243-threshold,243+threshold,1) and \
channels[1] in np.arange(169-threshold,169+threshold,1) and \
channels[2] in np.arange(0,threshold,1):
return 1
# Class 2 corresponds to people
if channels[0] in np.arange(0,threshold,1) and \
channels[1] in np.arange(163-threshold,163+threshold,1) and \
channels[2] in np.arange(232-threshold,232+threshold,1):
return 2
# Class 0 corresponds to background respectively other things
return 0
我有两个问题:
我的方法很慢(全高清图像大约需要 3 分钟),有没有办法加快速度?
我注意到颜色在通道值的意义上有所不同。例如,橙色应该是 [243,169,0] (RGB),但我发现像这样的条目 [206,172,8] 甚至 [207,176,24] 会发生这种情况,因为我将标签存储为 jpg?有没有比我上面用阈值的想法更好的方法来找到橙色和蓝色像素?
编辑:
我自己解决了第一个问题。全高清图像需要 2 或 3 秒:
threshold = 40
class_1_shape_cond_1 = (img_as_array[:, :, 0] >= 243 - threshold) * (img_as_array[:, :, 0] <= 243 + threshold)
class_1_shape_cond_2 = (img_as_array[:, :, 1] >= 171 - threshold) * (img_as_array[:, :, 1] <= 171 + threshold)
class_1_shape_cond_3 = (img_as_array[:, :, 2] >= 0) * (img_as_array[:, :, 2] <= threshold)
class_1_shape = (class_1_shape_cond_1 * class_1_shape_cond_2 * class_1_shape_cond_3)
然后我对 class 2 和 class 3 做同样的事情(其他所有)我可以做:
class_3_shape = 1 - (class_1_shape + class_2_shape)
之后我必须调整类型:
class_1_shape = class_1_shape.astype(np.uint8)
class_2_shape = class_2_shape.astype(np.uint8)
class_3_shape = class_3_shape.astype(np.uint8)
问题 2 仍未解决。
请勿将标签保存为 JPEG 图片!
jpeg 是一种 lossy compression 方法 - 也就是说,它旨在使用更少的位来保存图像,即使它改变了一点像素值,只要它对人类观察者“看起来不错”。
对于存储为图像的训练标签,情况并非如此!您不能承受标签中的错误。您必须使用 lossless compression method, e.g., png.
更好的是,首先将标签存储为 indexed RGB 图像,这样就省去了从 RGB 值推断离散标签的所有麻烦。
对于第一个问题
如果你使用的是Tensorflow框架,tf提供了快速生成one-hot矩阵的功能。
tf.one_hot(
indices,#your image with label
depth, #the number of classes
on_value=None,
off_value=None,
axis=None,
dtype=None,
name=None
)
有关详细信息,请参阅 (https://www.tensorflow.org/api_docs/python/tf/one_hot?version=stable)
我正在为人物和街道分割创建自己的数据集。在下方,您会看到一个标记为 Ground Truth (GT) 的图像。
以前我做过简单的模型输出和GT Image的Regression(以前只用Streets)。现在我读到,交叉熵损失在这种情况下更为常见。因为,我的 GT 和模型输出图像具有与输入图像相同的宽度 w 和高度 h,所以我必须创建一个数组大小 h x w x c,其中 c 是classes 的数量(在我的例子中是 3,背景,街道,人)。我想,这叫做 One-Hot-Encoded Array。
我按如下方式解决了这个问题:
for height in range(len(img_as_np_array)):
for width in range(len(img_as_np_array[0])):
temp = np.zeros(classes)
if get_class(img_as_np_array[height,width]) == 1:
temp[1] = 1
one_hot_label[height,width] = temp
if get_class(img_as_np_array[height,width]) == 2:
temp[2] = 1
one_hot_label[height,width] = temp
其中 get_class(channels) 方法通过像素的颜色决定像素 class。
def get_class(channels):
threshold = 40
# Class 1 corresponds to streets, roads
if channels[0] in np.arange(243-threshold,243+threshold,1) and \
channels[1] in np.arange(169-threshold,169+threshold,1) and \
channels[2] in np.arange(0,threshold,1):
return 1
# Class 2 corresponds to people
if channels[0] in np.arange(0,threshold,1) and \
channels[1] in np.arange(163-threshold,163+threshold,1) and \
channels[2] in np.arange(232-threshold,232+threshold,1):
return 2
# Class 0 corresponds to background respectively other things
return 0
我有两个问题:
我的方法很慢(全高清图像大约需要 3 分钟),有没有办法加快速度?
我注意到颜色在通道值的意义上有所不同。例如,橙色应该是 [243,169,0] (RGB),但我发现像这样的条目 [206,172,8] 甚至 [207,176,24] 会发生这种情况,因为我将标签存储为 jpg?有没有比我上面用阈值的想法更好的方法来找到橙色和蓝色像素?
编辑:
我自己解决了第一个问题。全高清图像需要 2 或 3 秒:
threshold = 40
class_1_shape_cond_1 = (img_as_array[:, :, 0] >= 243 - threshold) * (img_as_array[:, :, 0] <= 243 + threshold)
class_1_shape_cond_2 = (img_as_array[:, :, 1] >= 171 - threshold) * (img_as_array[:, :, 1] <= 171 + threshold)
class_1_shape_cond_3 = (img_as_array[:, :, 2] >= 0) * (img_as_array[:, :, 2] <= threshold)
class_1_shape = (class_1_shape_cond_1 * class_1_shape_cond_2 * class_1_shape_cond_3)
然后我对 class 2 和 class 3 做同样的事情(其他所有)我可以做:
class_3_shape = 1 - (class_1_shape + class_2_shape)
之后我必须调整类型:
class_1_shape = class_1_shape.astype(np.uint8)
class_2_shape = class_2_shape.astype(np.uint8)
class_3_shape = class_3_shape.astype(np.uint8)
问题 2 仍未解决。
请勿将标签保存为 JPEG 图片!
jpeg 是一种 lossy compression 方法 - 也就是说,它旨在使用更少的位来保存图像,即使它改变了一点像素值,只要它对人类观察者“看起来不错”。
对于存储为图像的训练标签,情况并非如此!您不能承受标签中的错误。您必须使用 lossless compression method, e.g., png.
更好的是,首先将标签存储为 indexed RGB 图像,这样就省去了从 RGB 值推断离散标签的所有麻烦。
对于第一个问题 如果你使用的是Tensorflow框架,tf提供了快速生成one-hot矩阵的功能。
tf.one_hot(
indices,#your image with label
depth, #the number of classes
on_value=None,
off_value=None,
axis=None,
dtype=None,
name=None
)
有关详细信息,请参阅 (https://www.tensorflow.org/api_docs/python/tf/one_hot?version=stable)