我正在尝试使用keras中的SegNet实现来理解图像分割。我使用Conv和Deconv架构阅读了原始论文,并使用了Dilated conv层。但是,我无法理解像素的标签是如何工作的。
我正在考虑以下实施: https://github.com/nicolov/segmentation_keras
此处使用pascal数据集属性:
21课程:
# 0=background
# 1=aeroplane, 2=bicycle, 3=bird, 4=boat, 5=bottle
# 6=bus, 7=car, 8=cat, 9=chair, 10=cow
# 11=diningtable, 12=dog, 13=horse, 14=motorbike, 15=person
# 16=potted plant, 17=sheep, 18=sofa, 19=train, 20=tv/monitor
这些类由:
表示pascal_nclasses = 21
pascal_palette = np.array([(0, 0, 0)
, (128, 0, 0), (0, 128, 0), (128, 128, 0), (0, 0, 128), (128, 0, 128)
, (0, 128, 128), (128, 128, 128), (64, 0, 0), (192, 0, 0), (64, 128, 0)
, (192, 128, 0), (64, 0, 128), (192, 0, 128), (64, 128, 128), (192, 128, 128)
, (0, 64, 0), (128, 64, 0), (0, 192, 0), (128, 192, 0), (0, 64, 128)], dtype=np.uint8)
我试图打开猫和船的标记图像,因为猫只在R空间中,而船只在蓝色中。我用以下来显示标记的图像:
对于船:
label = cv2.imread("2008_000120.png")
label = np.multiply(label, 100)
cv2.imshow("kk", label[:,:,2])
cv2.waitKey(0)
对于猫:
label = cv2.imread("2008_000056.png")
label = np.multiply(label, 100)
cv2.imshow("kk", label[:,:,0])
cv2.waitKey(0)
然而,无论我选择哪个空间都无关紧要,两个图像总能给出相同的结果。即以下代码也给出了相同的结果
对于船:
label = cv2.imread("2008_000120.png")
label = np.multiply(label, 100)
cv2.imshow("kk", label[:,:,1]) # changed to Green space
cv2.waitKey(0)
对于猫:
label = cv2.imread("2008_000056.png")
label = np.multiply(label, 100)
cv2.imshow("kk", label[:,:,1]) # changed to Green space
cv2.waitKey(0)
我的假设是,我只能在红色空间看到猫,而只能看到蓝色的船。但是,在所有情况下的输出:
我现在很困惑这些像素是如何被标记的,以及它们如何在创建logits的过程中被读取并唯一地用于与类别配对。
如果有人可以解释或提供一些相关链接来理解这个过程,那将会很棒。我试图搜索,但大多数教程只讨论CNN架构,而不是标签过程或CNN中如何使用这些标签。
答案 0 :(得分:1)
标签只是二进制图像掩码,因此是单通道图像。标签图像每个位置的像素值会根据每个像素上的类别而变化。因此,如果像素上没有对象,则值为0,值为1-20,具体取决于类别。
语义分割是一项分类任务,因此您尝试使用类对每个像素进行分类(在本例中为类标签0-20)。
您的模型将生成输出图像,并且您希望在每个输出图像像素和每个标签图像像素之间执行softmax交叉熵。
在具有K类的多类情况下(如此处K = 21),每个像素将具有K个通道,并且您在每个像素的通道上执行softmax交叉熵。为什么每个班级都有一个频道?考虑在分类中,我们为K类生成一个长度为K的向量,并将其与一个长度为K的热向量进行比较。