//go:build withcv // +build withcv // What it does: // // This example detects motion using a delta threshold from the first frame, // and then finds contours to determine where the object is located. // // Very loosely based on Adrian Rosebrock code located at: // http://www.pyimagesearch.com/2015/06/01/home-surveillance-and-motion-detection-with-the-raspberry-pi-python-and-opencv/ package main import ( "fmt" "image" "image/color" "os" "strconv" "time" "gocv.io/x/gocv" ) const MinimumArea = 1000 func main() { if len(os.Args) < 2 { fmt.Println("How to run:\n\tmotion-detect [camera ID]") return } // parse args deviceID := os.Args[1] minArea, _ := strconv.Atoi(os.Args[2]) webcam, err := gocv.OpenVideoCapture(deviceID) if err != nil { fmt.Printf("Error opening video capture device: %v\n", deviceID) return } defer webcam.Close() window1 := gocv.NewWindow("Motion Window") defer window1.Close() window2 := gocv.NewWindow("Threshold window") defer window2.Close() time.Sleep(2 * time.Second) img := gocv.NewMat() defer img.Close() imgDelta := gocv.NewMat() defer imgDelta.Close() imgThresh := gocv.NewMat() defer imgThresh.Close() mog2 := gocv.NewBackgroundSubtractorMOG2() defer mog2.Close() status := "Ready" fmt.Printf("Start reading device: %v\n", deviceID) for { if ok := webcam.Read(&img); !ok { fmt.Printf("Device closed: %v\n", deviceID) return } if img.Empty() { continue } status = "READY" statusColor := color.RGBA{0, 255, 0, 0} // first phase of cleaning up image, obtain foreground only mog2.Apply(img, &imgDelta) // remaining cleanup of the image to use for finding contours. // first use threshold gocv.Threshold(imgDelta, &imgThresh, 25, 255, gocv.ThresholdBinary) // then dilate kernel := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3)) defer kernel.Close() // Erode gocv.Erode(imgThresh, &imgThresh, kernel) // Dilate gocv.Dilate(imgThresh, &imgThresh, kernel) // now find contours contours := gocv.FindContours(imgThresh, gocv.RetrievalExternal, gocv.ChainApproxSimple) for i := 0; i < contours.Size(); i++ { area := gocv.ContourArea(contours.At(i)) if area < float64(minArea) { continue } status = "MOTION DETECTED" statusColor = color.RGBA{255, 0, 0, 0} //gocv.DrawContours(&img, contours, i, statusColor, 2) rect := gocv.BoundingRect(contours.At(i)) gocv.Rectangle(&img, rect, color.RGBA{0, 0, 255, 0}, 1) } gocv.PutText(&img, status, image.Pt(10, 20), gocv.FontHersheyPlain, 1.2, statusColor, 2) window1.IMShow(img) window2.IMShow(imgThresh) if window1.WaitKey(1) == 27 { break } } }