picam

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2020 License: MIT Imports: 8 Imported by: 0

README

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.

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)
	}
}

Documentation

Overview

Package picam is a Go API that uses raspiyuv that continuously reads the latests frame from a Raspberry Pi Camera.

Example
package main

import (
	"fmt"
	"log"

	"github.com/cgxeiji/picam"
)

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

	nFrames := 5
	fmt.Println("Reading", nFrames, "frames:")

	for i := 0; i < nFrames; i++ {
		// Get an image.Image
		img := cam.Read()

		/* do something with img */
		fmt.Println("got", img.Bounds().Size())

		// Or get a raw []uint8 slice
		raw := cam.ReadUint8()

		/* do something with img */
		fmt.Println("read", len(raw), "bytes")
	}

}
Output:

Reading 5 frames:
got (640,480)
read 460800 bytes
got (640,480)
read 460800 bytes
got (640,480)
read 460800 bytes
got (640,480)
read 460800 bytes
got (640,480)
read 460800 bytes
Example (Save)
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)
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Camera

type Camera struct {

	// Width sets the width of the image
	// Height sets the height of the image
	Width, Height int
	// contains filtered or unexported fields
}

Camera is a struct that stores camera information.

func New

func New(width, height int, format Format) (*Camera, error)

New initializes and starts a raspiyuv process to capture RGB frames.

func (*Camera) Close

func (c *Camera) Close()

Close closes picam.

func (*Camera) Read

func (c *Camera) Read() (img image.Image)

Read returns an image.Image interface of the last frame.

cam, _ := picam.New(width, height, format)
img := cam.Read()

The type returned depends on the format passed at picam.New():

format        type(img)
----------    ---------------
picam.YUV  -> image.YCbCr 420
picam.RGB  -> image.NRGBA
picam.Gray -> image.Gray

func (*Camera) ReadUint8

func (c *Camera) ReadUint8() (img []uint8)

ReadUint8 returns the raw uint8 values of the last frame.

cam, _ := picam.New(width, height, format)
raw := cam.ReadUint8()

The size of the slice returned depends on the format and dimensions passed at picam.New():

format        len(raw)
----------    ----------------------------------------------------------
picam.YUV  -> roundUpMultiple32(width) * roundUpMultiple16(height) * 1.5
picam.RGB  -> (width * height) * 3
picam.Gray -> width * height

type Format

type Format uint8

Format is the type of image that picam will output.

const (
	// YUV 420 color format.
	YUV Format = iota
	// RGB color format.
	RGB
	// Gray color format.
	Gray
)

func (Format) String

func (i Format) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL