python opencv 与PIL库对于semantic label的最近邻插值对比

事情是这样的:因为要做分割图的缩放,但是segmentation map中的label的id的数值没有数值意义,就是表示第几类,所以对于label缩放的时候都是要用最近邻插值的,这样才有意义,否则插出来一个不知道的类别也没啥用。比如advent中的数据读取链接就是用PIL,然后对于Image对象进行resize的,链接

有些数据集并不像cityscapes那么规范,比如synthia,这个数据集的label如作者给的readme中的描述:

  • GT/LABELS: folder containing png files (one per image). Annotations are given in two channels. The first channel contains the class of that pixel (see the table below). The second channel contains the unique ID of the instance for those objects that are dynamic (cars, pedestrians, etc.).

是的,作者用了两个channel来表示图片的类别,一个是唯一的一个id,一个是instance id,对于semantic segmentation而言,第二个instance id没有啥用。但是PIL又取不出来两通道的png,所以只能借助opencv来取,如下所示:

label = cv2.imread(datafiles['label'], cv2.IMREAD_UNCHANGED)[:,:,2]

取出来对应的带有semantic label id的二维数组,理论上可以直接用opencv的cv2.resize直接进行缩放

cv2.resize(label_copy, (1212, 720), cv2.INTER_NEAREST)

虽然选用的还是最近邻插值INTER_NEAREST,但是实际山缩放出来的结果进行可视化,发现有些地方的边缘并不是那么的clean

看之前的方法都是用PIL中的Imge进行缩放,所以,换成了先转换成PIL的Image这个类,然后再进行缩放,最后转换成numpy

   image = cv2.imread(i, cv2.IMREAD_UNCHANGED)
   c3 = image[:,:,2]
   label = c3
   
   id_to_trainid = {2:0, 7:1, 9:2, 1:3, 10:4, 8:5}
   label_copy = 255 * np.ones(label.shape, dtype=np.float32)
   for k, v in id_to_trainid.items():
       label_copy[label == k] = v
   label_copy2 = Image.fromarray(label_copy)
   label_copy2 = label_copy2.resize((1212, 720), Image.NEAREST)
   label_copy3 = np.asarray(label_copy2)

这样操作出来的图片可视化发现效果是正常的,在边缘地方也没有产生其他类别

总结一下,大概率是opencv的最近邻插值存在问题的,也可能是opencv的版本不对,所以在最近邻插值的时候才会出现问题。
之前的分割数据集的dataloader大都用PIL中的Image这个类也不是没有缘由的,所以为了安全起见,以后还是用PIL中的Image这个类来进行semantic label的缩放插值

posted on 2021-08-08 15:59  YongjieShi  阅读(163)  评论(0编辑  收藏  举报

导航