func (t OverlapTest) Overlap(a, b image.Rectangle) bool { if detect.Cover(a, b) >= t.MaxCover { return true } if detect.IOU(a, b) >= t.MaxIOU { return true } if detect.Cover(a, b) >= t.MaxCoverBoth && detect.Cover(b, a) >= t.MaxCoverBoth { return true } return false }
// Runs a single detector across a single image and returns results. func detectImage(tmpl *detect.FeatTmpl, im image.Image, margin int, step float64, sbin int, localmax bool, maxiou float64) []detect.Det { // Construct pyramid. // Get range of scales. scales := imgpyr.Scales(im.Bounds().Size(), tmpl.Size, step) // Define feature transform. phi := hog.Transform{hog.FGMRConfig(sbin)} // Define amount and type of padding. pad := feat.Pad{feat.Margin{margin, margin, margin, margin}, imsamp.Continue} pyr := featpyr.NewPad(imgpyr.New(im, scales), phi, pad) // Search feature pyramid. // Options for running detector on each level. detopts := detect.DetFilter{LocalMax: localmax, MinScore: math.Inf(-1)} // Use intersection-over-union criteria for non-max suppression. overlap := func(a, b image.Rectangle) bool { return detect.IOU(a, b) > maxiou } // Options for non-max suppression. suppropts := detect.SupprFilter{MaxNum: 0, Overlap: overlap} dets := detect.Pyramid(pyr, tmpl, detopts, suppropts) return dets }
func main() { var ( // Dataset options. name = flag.String("dataset", "usatest", "Dataset identifier.") dir = flag.String("dir", "", "Location of dataset. Empty means working dir.") // Detection options. pyrStep = flag.Float64("pyr-step", 1.2, "Geometric scale steps in image pyramid.") maxScale = flag.Float64("max-scale", 1, "Maximum amount to scale image. Greater than 1 is upsampling.") maxIOU = flag.Float64("max-iou", 0.3, "Maximum IOU that two detections can have before NMS.") margin = flag.Int("margin", 0, "Spatial bin parameter to HOG.") // Validation options. minValIOU = flag.Float64("min-val-iou", 0.5, "Minimum IOU for a detection to be validated.") minIgnoreCover = flag.Float64("min-ignore-cover", 0, "Minimum that a detection must be covered by an ignore region to be ignored.") // Display options. numShow = flag.Int("num-show", 4, "Number of detections to show per image") ) flag.Parse() if flag.NArg() != 2 { flag.Usage() os.Exit(1) } var ( tmplFile = flag.Arg(0) transformFile = flag.Arg(1) ) // Get dataset from name. dataset, err := datasetByName(*name) if err != nil { log.Fatalln(err) } // Load template from file. var tmpl *detect.FeatTmpl if err := fileutil.LoadExt(tmplFile, &tmpl); err != nil { log.Fatalln("load template:", err) } // Load transform from file. var transform *feat.Marshaler if err := fileutil.LoadJSON(transformFile, &transform); err != nil { log.Fatalln("load transform:", err) } overlap := func(a, b image.Rectangle) bool { return detect.IOU(a, b) > *maxIOU } opts := detect.MultiScaleOpts{ MaxScale: *maxScale, PyrStep: *pyrStep, Interp: resize.Bicubic, Transform: transform, Pad: feat.Pad{feat.UniformMargin(*margin), imsamp.Continue}, DetFilter: detect.DetFilter{LocalMax: true, MinScore: math.Inf(-1)}, SupprFilter: detect.SupprFilter{MaxNum: 0, Overlap: overlap}, } var val *detect.ValSet err = fileutil.Cache(&val, "val-set.json", func() (*detect.ValSet, error) { return testAll(dataset, *dir, tmpl, opts, *minValIOU, *minIgnoreCover, *numShow) }) if err != nil { log.Fatal(err) } }
func main() { var ( sbin = flag.Int("sbin", 4, "Spatial binning parameter to HOG") margin = flag.Int("margin", 0, "Margin to add around images before computing features") step = flag.Float64("pyr-step", 1.1, "Geometric step to use in image pyramid") maxinter = flag.Float64("max-intersect", 0.5, "Maximum overlap of detections. Zero means detections can't overlap at all, one means they can overlap entirely.") localmax = flag.Bool("local-max", true, "Detections cannot score less than a neighbor") ) flag.Usage = usage flag.Parse() if flag.NArg() != 3 { flag.Usage() os.Exit(1) } var ( tmplFile = flag.Arg(0) imFile = flag.Arg(1) detsFile = flag.Arg(2) ) // Load image. im, err := loadImage(imFile) if err != nil { log.Fatal(err) } // Construct pyramid. scales := imgpyr.Scales(im.Bounds().Size(), image.Pt(24, 24), *step) phi := hog.Transform{hog.FGMRConfig(*sbin)} pad := feat.Pad{feat.Margin{*margin, *margin, *margin, *margin}, imsamp.Continue} pyr := featpyr.NewPad(imgpyr.New(im, scales), phi, pad) // Load template. var tmpl *detect.FeatTmpl if err := loadGob(tmplFile, &tmpl); err != nil { log.Fatal(err) } detopts := detect.DetFilter{ LocalMax: *localmax, MinScore: math.Inf(-1), } // Use intersection-over-union criteria for non-max suppression. overlap := func(a, b image.Rectangle) bool { return detect.IOU(a, b) > *maxinter } suppropts := detect.SupprFilter{ MaxNum: 0, Overlap: overlap, } dets := detect.Pyramid(pyr, tmpl, detopts, suppropts) if err := saveJSON(detsFile, dets); err != nil { log.Fatal(err) } for i, det := range dets { r := det.Rect cmd := fmt.Sprintf("rectangle %d,%d %d,%d", r.Min.X, r.Min.Y, r.Max.X, r.Max.Y) fmt.Printf("convert %s -fill none -stroke white -draw '%s' det_%06d.jpg\n", imFile, cmd, i) } }