单发多框检测(SSD) 讨论区


#124

自己蠢了,0.05*10=0.5 就是第一个像素的中心点。


#125

按照教程的思路,那用smooth l1+ focal loss训练SSD,只需要正样本输入,不需要产生负样本。即使有负样本,算损失时也自动忽略????


#126

这种皮卡丘的人工数据是怎么生成的?不能是PS吧?


#127

能不能提供一下原始数据呢?


#128

这两天一直在弄SSD算法的原理,现在我有一问题,沐神在教程里面讲解的SSD最后输出三个结果,
Output achors: (1, 5444, 4)
Output class predictions: (1, 5444, 3)
Output box predictions: (1, 21776)
achors和box prediction有什么区别,他们的四个坐标都是代表什么物理含义,哪位大神可以给我解答一下?


#129

Output achors: (1, 5444, 4) – 1张图片, 5444个锚框(包含了不同的feature map的锚框),每个框4个坐标(两个对角顶点)
Output class predictions: (1, 5444, 3) – 1张图片, 5444个锚框,2类别+一个背景
Output box predictions: (1, 21776) – 1张图片, 每个锚框对应4个偏移量,一共是5444*4=21776

坐标是 Xmin,Ymin,Xmax,Ymax吧


#130

把 代码里root_url改为 root_url = (‘https://apache-mxnet.s3.cn-north-1.amazonaws.com.cn/
‘gluon/dataset/pikachu/’) 就可以下载了


#131

你好,我遇到了与你一样的问题,请问你解决这个问题了吗?


#132
    print('Epoch %2d,  cls_acc %s, box_acc %s" , time %.1f sec' %(
            epoch, cls_metric.get()[1], box_metric.get()[1], time.time() - tic ))

#133

跪求合成人工数据的方法,最近写论文用到,我的QQ邮箱1939752448@qq.com


#134

多谢大佬启示


#135

我运行了train_ssd.py . 但是发现速度比mxnet 原版慢了40%左右. 我判断是原来数据是rec格式,而现在是原始数据。但现在用image.ImageDetIter 载入 rec 文件,似乎没法用SSD的数据增强。应该如何使用 rec 文件?


#136


这一部分一直没有理解。假设总共有m个锚框,num_classes个物体类别,最后应该生成的通道数是m*(num_classes+1)。

假设图中所说的a从1开始计算,那么以(i,j)为中心的通道数范围就是 num_classes+1 ~~~ num_classes+1+1+num_classes ----> (num_classes+1, 2*num_classes+2), 明显的这个通道数范围长度为num_classes+2,而且第前面的通道数,即num_classes+1之前的通道数都是没用的吗?如果a是最后一个锚框,很明显其最后一个通道数为 m * (num_classes+1) + 1 + num_classes, 超过了图像本身的通道数大小。

我如果理解错的话,锚框个数从0开始计算,那算出来结果也不对,假设a为0,通道0是背景,通道num_classes+1是第num_classes物体的分数,还是不对。求各位大神指教.
@mli @astonzhang


#137

数据载入问题中的anchors:
train_loader = gdata.DetectionDataLoader(
train_dataset.transform(SSDDefaultTrainTransform(width, height, anchors)),
batch_size, True, last_batch=‘rollover’, num_workers=num_workers)

我在 SSDDefaultTrainTransform 的实现中没有看到 anchors 的作用?
class SSDDefaultTrainTransform(object):
“”"Default SSD training transform which includes tons of image augmentations.

Parameters
----------
width : int
    Image width.
height : int
    Image height.
mean : array-like of size 3
    Mean pixel values to be subtracted from image tensor. Default is [0.485, 0.456, 0.406].
std : array-like of size 3
    Standard deviation to be divided from image. Default is [0.229, 0.224, 0.225].

"""
def __init__(self, width, height, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)):
    self._width = width
    self._height = height
    self._mean = mean
    self._std = std

def __call__(self, src, label):
    # random color jittering
    img = experimental.image.random_color_distort(src)

    # random expansion with prob 0.5
    if np.random.uniform(0, 1) > 0.5:
        img, expand = timage.random_expand(img, fill=[m * 255 for m in self._mean])
        bbox = tbbox.translate(label, x_offset=expand[0], y_offset=expand[1])
    else:
        img, bbox = img, label

    # random cropping
    h, w, _ = img.shape
    bbox, crop = experimental.bbox.random_crop_with_constraints(bbox, (w, h))
    x0, y0, w, h = crop
    img = mx.image.fixed_crop(img, x0, y0, w, h)

    # resize with random interpolation
    h, w, _ = img.shape
    interp = np.random.randint(0, 5)
    img = timage.imresize(img, self._width, self._height, interp=interp)
    bbox = tbbox.resize(bbox, (w, h), (self._width, self._height))

    # random horizontal flip
    h, w, _ = img.shape
    img, flips = timage.random_flip(img, px=0.5)
    bbox = tbbox.flip(bbox, (w, h), flip_x=flips[0])

    # to tensor
    img = mx.nd.image.to_tensor(img)
    img = mx.nd.image.normalize(img, mean=self._mean, std=self._std)
    return img, bbox.astype('float32')

#138

在我理解,nn.Sequential()里面的模型按照输入(add)的顺序依次连接起来。
但是您在def toy_ssd_model(num_anchors, num_classes):当中写到:
for _ in range(3):
downsamplers.add(down_sample(128))
这不就把三个down_sample黏在一起了吗?
正确的顺序应该是:
body()
class_predictor box_predictor 并列并同时使用body()的输出
怎么样能够同时使用body()的输出呢?
我虽然不知道应该怎么做,但是我感觉不应该把三个down_sample先黏在一起。


#139
model = nn.Sequential()
model.add(body(), downsamplers, class_predictors, box_predictors)

这里在暗示系统,body()的输出给downsamplers,然后输出给class_predictors,然后给box_predictors。
然后,您在def toy_ssd_forward(x, model, sizes, ratios, verbose=False)
里面,通过连接输入和输出,等于是重新定义了网络之间的链接结构。
这样两次重复定义,会不会把计算机弄糊涂呢?计算机会按照最后toy_ssd_forward里面定义的链接顺序计算吗?


#140

而且我个人认为,我们使用的网络并不复杂,没必要使用循环定义层。
一旦循环了,就容易糊涂。
一层一层清爽的写出来多好呀!


#141

改ratios啊


#142

实际运行一下以后,发现如果在toy_ssd_model里面使用list来存储block的时候,初始化(net.initialize(verbose = True))过程就会收到提示。
“ToySSD.downsamplers” is a container with Blocks. Note that Blocks inside the list, tuple or dict will not be registered automatically. Make sure to register them using register_child() or switching to nn.Sequential/nn.HybridSequential instead.
大意是如果这样存储有些block就不会被注册,可以手工注册或者使用nn.Sequential/nn.HybridSequential
这里的问题是,如果像作者那样使用nn.Sequential/nn.HybridSequential的话有什么副作用吗?


#143

生成n个正方形基础框 + i-n个变化框,一共有n + m -1个框。您的ratios个数太少,基础框就够了n + m -1,来不及生成变化框了。