func dendriteCam(deltaE chan float32, config Configuration) {
	camera := C.cvCaptureFromCAM(-1)

	// Shutdown dendrite if no camera detected.
	if camera == nil {
		fmt.Printf("WARNING: No camera detected. Shutting down DendriteCam\n")
		return
	}

	C.cvSetCaptureProperty(camera, C.CV_CAP_PROP_FRAME_WIDTH, 160)
	C.cvSetCaptureProperty(camera, C.CV_CAP_PROP_FRAME_HEIGHT, 120)

	// Capture original frame.
	prev := C.cvCloneImage(C.cvQueryFrame(camera))

	// Save out the first frame for debuging purposes.
	file := C.CString("frame.png")
	C.cvSaveImage(file, unsafe.Pointer(prev), nil)
	C.free(unsafe.Pointer(file))

	flow := C.cvCreateImage(C.cvSize(prev.width, prev.height), C.IPL_DEPTH_32F, 2)
	prevG := C.cvCreateImage(C.cvSize(prev.width, prev.height), C.IPL_DEPTH_8U, 1)
	nextG := C.cvCreateImage(C.cvSize(prev.width, prev.height), C.IPL_DEPTH_8U, 1)
	C.cvConvertImage(unsafe.Pointer(prev), unsafe.Pointer(prevG), 0)

	for {
		C.cvGrabFrame(camera)

		// Capture the new frame and convert it to grayscale.
		next := C.cvCloneImage(C.cvQueryFrame(camera))
		C.cvConvertImage(unsafe.Pointer(prev), unsafe.Pointer(prevG), 0)
		C.cvConvertImage(unsafe.Pointer(next), unsafe.Pointer(nextG), 0)

		C.cvCalcOpticalFlowFarneback(unsafe.Pointer(prevG), unsafe.Pointer(nextG), unsafe.Pointer(flow), 0.5, 2, 5, 2, 5, 1.1, 0)
		deltaE <- float32(calcDeltaEnergy(flow, &config))

		C.cvReleaseImage(&prev)
		prev = next
	}

	// Never reached - but here in comments for completeness.
	//C.cvReleaseImage(&prev)
	//C.cvReleaseImage(&nextG)
	//C.cvReleaseImage(&prevG)
	//C.cvReleaseImage(&flow)
	//C.cvReleaseCapture(&camera)
}
Beispiel #2
0
/* grab a frame, return 1 on success, 0 on fail.
this function is thought to be fast               */
func (capture *Capture) GrabFrame() bool {
	rv := C.cvGrabFrame((*C.CvCapture)(capture))
	return (rv != C.int(0))
}
Beispiel #3
0
func measure(deltaC chan Command, videoFile string, debug bool, config Configuration) {
	camera, err := getVideoSource(videoFile)
	if err != nil {
		// No valid video source. Abort measuring.
		log.Printf("ERROR: Unable to get video source")
		log.Print(err)
		return
	}
	defer C.cvReleaseCapture(&camera)

	// Make sure we release the camera when the operating system crushes us.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		log.Printf("INFO: The OS shut down the scout.")
		C.cvReleaseCapture(&camera)
		return
	}()

	scene := initScene()

	// Build the calibration frame from disk.
	var calibrationFrame *C.IplImage
	if _, err := os.Stat("calibrationFrame.jpg"); err == nil {
		file := C.CString("calibrationFrame.jpg")

		calibrationFrame = C.cvLoadImage(file, C.CV_LOAD_IMAGE_COLOR)
		defer C.cvReleaseImage(&calibrationFrame)

		C.free(unsafe.Pointer(file))
	} else {
		log.Printf("ERROR: Unable to measure, missing calibration frame")
		log.Print(err)
		return
	}

	// Create a frame to hold the foreground mask results.
	mask := C.cvCreateImage(C.cvSize(calibrationFrame.width, calibrationFrame.height), C.IPL_DEPTH_8U, 1)
	defer C.cvReleaseImage(&mask)

	// Push the initial calibration frame into the MOG2 image subtractor.
	C.initMOG2(C.int(config.MogHistoryLength), C.double(config.MogThreshold), C.int(config.MogDetectShadows))
	C.applyMOG2(unsafe.Pointer(calibrationFrame), unsafe.Pointer(mask))

	// Current frame counter.
	frame := int64(0)
	measuring := true

	// Start monitoring from the camera.
	for measuring && C.cvGrabFrame(camera) != 0 {
		// See if there are any new commands on the deltaC channel.
		select {
		case c := <-deltaC:
			switch {
			case c == STOP_MEASURE:
				log.Printf("INFO: Stopping measure")
				measuring = false
			}

		default:
			// Procceed with measuring.
		}

		// Subtract the calibration frame from the current frame.
		nextFrame := C.cvRetrieveFrame(camera, 0)
		C.applyMOG2(unsafe.Pointer(nextFrame), unsafe.Pointer(mask))

		// Filter the foreground mask to clean up any noise or holes (morphological-closing).
		C.cvSmooth(unsafe.Pointer(mask), unsafe.Pointer(mask), C.CV_GAUSSIAN, C.int(config.GaussianSmooth), 0, 0.0, 0.0)
		C.cvThreshold(unsafe.Pointer(mask), unsafe.Pointer(mask), C.double(config.ForegroundThresh), 255, 0)
		C.cvDilate(unsafe.Pointer(mask), unsafe.Pointer(mask), nil, C.int(config.DilationIterations))

		// Detect contours in filtered foreground mask
		storage := C.cvCreateMemStorage(0)
		contours := C.cvCreateSeq(0, C.size_t(unsafe.Sizeof(C.CvSeq{})), C.size_t(unsafe.Sizeof(C.CvPoint{})), storage)
		offset := C.cvPoint(C.int(0), C.int(0))
		num := int(C.cvFindContours(unsafe.Pointer(mask), storage, &contours, C.int(unsafe.Sizeof(C.CvContour{})),
			C.CV_RETR_LIST, C.CV_CHAIN_APPROX_SIMPLE, offset))

		var detectedObjects []Waypoint

		// Track each of the detected contours.
		for contours != nil {
			area := float64(C.cvContourArea(unsafe.Pointer(contours), C.cvSlice(0, 0x3fffffff), 0))

			// Only track large objects.
			if area > config.MinArea {
				boundingBox := C.cvBoundingRect(unsafe.Pointer(contours), 0)
				w := int(boundingBox.width / 2)
				h := int(boundingBox.height / 2)
				x := int(boundingBox.x) + w
				y := int(boundingBox.y) + h

				detectedObjects = append(detectedObjects, Waypoint{x, y, w, h, 0.0})

				if debug {
					// DEBUG -- Render contours and bounding boxes around detected objects.
					pt1 := C.cvPoint(boundingBox.x, boundingBox.y)
					pt2 := C.cvPoint(boundingBox.x+boundingBox.width, boundingBox.y+boundingBox.height)
					C.cvDrawContours(unsafe.Pointer(nextFrame), contours, C.cvScalar(12.0, 212.0, 250.0, 255), C.cvScalar(0, 0, 0, 0), 2, 1, 8, offset)
					C.cvRectangle(unsafe.Pointer(nextFrame), pt1, pt2, C.cvScalar(16.0, 8.0, 186.0, 255), C.int(5), C.int(8), C.int(0))
				}
			} else {
				num--
			}

			contours = contours.h_next
		}

		scene.update(detectedObjects, debug, config)
		C.cvClearMemStorage(storage)
		C.cvReleaseMemStorage(&storage)

		if debug {
			var font C.CvFont
			C.cvInitFont(&font, C.CV_FONT_HERSHEY_SIMPLEX, C.double(0.5), C.double(0.5), C.double(1.0), C.int(2), C.CV_AA)
			txt := C.CString("Hello friend.")
			C.cvPutText(unsafe.Pointer(nextFrame), txt, C.cvPoint(2, 2), &font, C.cvScalar(255.0, 255.0, 255.0, 255))
			C.free(unsafe.Pointer(txt))

			// DEBUG -- render current interaction path for detected objects.
			for _, i := range scene.Interactions {
				for _, w := range i.Path {
					pt1 := C.cvPoint(C.int(w.XPixels), C.int(w.YPixels))
					C.cvCircle(unsafe.Pointer(nextFrame), pt1, C.int(10), C.cvScalar(109.0, 46.0, 0.0, 255), C.int(2), C.int(8), C.int(0))
				}

				w := i.lastWaypoint()
				txt := C.CString(fmt.Sprintf("%01d", i.SceneID))
				C.cvPutText(unsafe.Pointer(nextFrame), txt, C.cvPoint(C.int(w.XPixels+10), C.int(w.YPixels+10)), &font, C.cvScalar(255.0, 255.0, 255.0, 255))
				C.free(unsafe.Pointer(txt))
			}

			for _, i := range scene.idleInteractions {
				w := i.lastWaypoint()
				pt1 := C.cvPoint(C.int(w.XPixels-w.HalfWidthPixels+5), C.int(w.YPixels-w.HalfHeightPixels+5))
				pt2 := C.cvPoint(C.int(w.XPixels+w.HalfWidthPixels-5), C.int(w.YPixels+w.HalfHeightPixels-5))
				C.cvRectangle(unsafe.Pointer(nextFrame), pt1, pt2, C.cvScalar(16.0, 186.0, 8.0, 255), C.int(5), C.int(8), C.int(0))

				txt := C.CString("i:" + fmt.Sprintf("%01d", i.SceneID))
				C.cvPutText(unsafe.Pointer(nextFrame), txt, C.cvPoint(C.int(w.XPixels+10), C.int(w.YPixels+10)), &font, C.cvScalar(255.0, 255.0, 255.0, 255))
				C.free(unsafe.Pointer(txt))
			}

			file := C.CString("f" + fmt.Sprintf("%03d", frame) + "-detected.png")
			C.cvSaveImage(file, unsafe.Pointer(nextFrame), nil)
			C.free(unsafe.Pointer(file))
			frame++

		}
	}

	log.Printf("INFO: Finished measure")
	scene.close(debug, config)
}