func MultiScale(im image.Image, tmpls map[string]*detect.FeatTmpl, opts detect.MultiScaleOpts) ([]Det, error) { if len(tmpls) == 0 { return nil, nil } scales := imgpyr.Scales(im.Bounds().Size(), minDims(tmpls), opts.MaxScale, opts.PyrStep).Elems() ims := imgpyr.NewGenerator(im, scales, opts.Interp) pyr := featpyr.NewGenerator(ims, opts.Transform, opts.Pad) var dets []Det l, err := pyr.First() if err != nil { return nil, err } for l != nil { for key, tmpl := range tmpls { pts := detect.Points(l.Feat, tmpl.Image, tmpl.Bias, opts.DetFilter.LocalMax, opts.DetFilter.MinScore) // Convert to scored rectangles in the image. for _, pt := range pts { rect := pyr.ToImageRect(l.Image.Index, pt.Point, tmpl.Interior) dets = append(dets, Det{detect.Det{pt.Score + tmpl.Bias, rect}, key}) } } var err error l, err = pyr.Next(l) if err != nil { return nil, err } } Sort(dets) inds := detect.SuppressIndex(DetSlice(dets), opts.SupprFilter.MaxNum, opts.SupprFilter.Overlap) dets = detsSubset(dets, inds) return dets, nil }
// MultiScale searches an image at multiple scales and performs non-max suppression. // // At each level, the image is rescaled using Interp, // then padded using Pad before calling Transform.Apply(). // The levels are geometrically spaced at intervals of PyrStep. // Detections are filtered using DetFilter and then non-max suppression // is performed using the OverlapFunc test. func MultiScale(im image.Image, scorer slide.Scorer, shape PadRect, opts MultiScaleOpts) ([]Det, MultiScaleDuration, error) { scales := imgpyr.Scales(im.Bounds().Size(), scorer.Size(), opts.MaxScale, opts.PyrStep).Elems() ims := imgpyr.NewGenerator(im, scales, opts.Interp) pyr := featpyr.NewGenerator(ims, opts.Transform, opts.Pad) var dets []Det l, err := pyr.First() if err != nil { return nil, MultiScaleDuration{}, err } var dur MultiScaleDuration for l != nil { t := time.Now() pts, err := Points(l.Feat, scorer, opts.DetFilter.LocalMax, opts.DetFilter.MinScore) if err != nil { return nil, MultiScaleDuration{}, err } dur.Slide += time.Since(t) // Convert to scored rectangles in the image. for _, pt := range pts { rect := pyr.ToImageRect(l.Image.Index, pt.Point, shape.Int) dets = append(dets, Det{pt.Score, rect}) } l, err = pyr.Next(l) if err != nil { return nil, MultiScaleDuration{}, err } } dur.Resize = pyr.DurResize dur.Feat = pyr.DurFeat t := time.Now() Sort(dets) dets = Suppress(dets, opts.SupprFilter.MaxNum, opts.SupprFilter.Overlap) dur.Suppr = time.Since(t) return dets, dur, nil }