Skip to content
/ picam Public

Go library for getting the last frame from a pi-camera on a Raspberry Pi

License

Notifications You must be signed in to change notification settings

cgxeiji/picam

Repository files navigation

PiCam

Version PkgGoDev License Go version

PiCam is a Go wrapper to raspiyuv to get []uint8 and image.Image data of the latests frame captured by the Raspberry Pi camera.

Under the hood, it executes:

$ raspiyuv --timeout 0 --timelapse 0

to get raw frames.

Currently, three image formats are available:

  • picam.YUV
  • picam.RGB
  • picam.Gray

The time between frames, measured on a Raspberry Pi Zero W, is between 180ms to 210ms for a 640x480 pixels image.

If you want to test the speed in your system, run:

$ cd $(go env GOPATH)/src/github.com/cgxeiji/picam
$ go test -bench . -benchtime=10x

This will take 10 frames and output the average time between each frame. Change -benchtime=10x to 100x or Nx to change the number of frames to test.

Why this library?

I wanted to avoid the dependency on GoCV to access the camera on a Raspberry Pi to do real-time face detection.

Example code

package main

import (
	"image/png"
	"log"
	"os"

	"github.com/cgxeiji/picam"
)

func main() {
	cam, err := picam.New(640, 480, picam.YUV)
	if err != nil {
		log.Fatal(err)
	}
	defer cam.Close()

	img := cam.Read()

	f, err := os.Create("./image.png")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	err = png.Encode(f, img)
	if err != nil {
		log.Fatal(err)
	}
}

Example real-time face detection

Using the pigo libray from esimov, it is possible to do real-time face detection on a Raspberry Pi without depending on OpenCV.

package main

import (
	"fmt"
	"io/ioutil"
	"log"

	"github.com/cgxeiji/picam"
	pigo "github.com/esimov/pigo/core"
)

func main() {
	cam, err := picam.New(640, 480, picam.Gray)
	if err != nil {
		log.Fatal(err)
	}
	defer cam.Close()

	cParams := pigo.CascadeParams{
		MinSize:     90,
		MaxSize:     200,
		ShiftFactor: 0.1,
		ScaleFactor: 1.1,
		ImageParams: pigo.ImageParams{
			Rows: cam.Height,
			Cols: cam.Width,
			Dim:  cam.Width,
		},
	}

	classifierFile, err := ioutil.ReadFile("./facefinder")
	if err != nil {
		log.Fatal(err)
	}

	p := pigo.NewPigo()
	classifier, err := p.Unpack(classifierFile)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Starting face detection")
	fmt.Println("Press Ctrl+C to stop")
	for {
		cParams.Pixels = cam.ReadUint8()
		faces := classifier.RunCascade(cParams, 0.0) // 0.0 is the angle
		faces = classifier.ClusterDetections(faces, 0.1)

		// Get the face with the highest confidence level
		var maxQ float32
		index := 0
		for i, face := range faces {
			if face.Q > maxQ {
				maxQ = face.Q
				index = i
			}
		}

		face := pigo.Detection{}
		if index < len(faces) {
			face = faces[index]
		}

		if face.Scale == 0 {
			// no face detected
			fmt.Printf("\rno face detected                                                 ")
			continue
		}

		x := face.Col - cam.Width/2
		y := -face.Row + cam.Height/2 // y is flipped

		fmt.Printf("\rface is (%d, %d) pixels from the center", x, y)
	}
}

About

Go library for getting the last frame from a pi-camera on a Raspberry Pi

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages