face

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2021 License: CC0-1.0 Imports: 7 Imported by: 0

README

go-face Build Status GoDoc

go-face implements face recognition for Go using dlib, a popular machine learning toolkit. Read Face recognition with Go article for some background details if you're new to FaceNet concept.

Requirements

To compile go-face you need to have dlib (>= 19.10) and libjpeg development packages installed.

Ubuntu 16.04, Ubuntu 18.04

You may use dlib PPA which contains latest dlib package compiled with Intel MKL support:

sudo add-apt-repository ppa:kagamih/dlib
sudo apt-get update
sudo apt-get install libdlib-dev libjpeg-turbo8-dev
Ubuntu 18.10+, Debian sid

Latest versions of Ubuntu and Debian provide suitable dlib package so just run:

# Ubuntu
sudo apt-get install libdlib-dev libopenblas-dev libjpeg-turbo8-dev
# Debian
sudo apt-get install libdlib-dev libopenblas-dev libjpeg62-turbo-dev

ONLY FOR UBUNTU 18.10+ AND DEBIAN SID:
It won't install pkgconfig metadata file so create one in /usr/local/lib/pkgconfig/dlib-1.pc with the following content:

libdir=/usr/lib/x86_64-linux-gnu
includedir=/usr/include

Name: dlib
Description: Numerical and networking C++ library
Version: 19.10.0
Libs: -L${libdir} -ldlib -lblas -llapack
Cflags: -I${includedir}
Requires:
macOS

Make sure you have Homebrew installed.

brew install pkg-config dlib
sed -i '' 's/^Libs: .*/& -lblas -llapack/' /usr/local/lib/pkgconfig/dlib-1.pc
Windows

Make sure you have MSYS2 installed.

  1. Run MSYS2 MSYS shell from Start menu
  2. Run pacman -Syu and if it asks you to close the shell do that
  3. Run pacman -Syu again
  4. Run pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-dlib mingw-w64-x86_64-pkg-config
    1. If you already have Go and Git installed and available in PATH uncomment set MSYS2_PATH_TYPE=inherit line in msys2_shell.cmd located in MSYS2 installation folder
    2. Otherwise run pacman -S mingw-w64-x86_64-go git
  5. Run MSYS2 MinGW 64-bit shell from Start menu to compile and use go-face
Other systems

Try to install dlib/libjpeg with package manager of your distribution or compile from sources. Note that go-face won't work with old packages of dlib such as libdlib18. Alternatively create issue with the name of your system and someone might help you with the installation process.

Models

Currently shape_predictor_5_face_landmarks.dat, mmod_human_face_detector.dat and dlib_face_recognition_resnet_model_v1.dat are required. You may download them from dlib-models repo:

mkdir models && cd models
wget https://github.com/davisking/dlib-models/raw/master/shape_predictor_5_face_landmarks.dat.bz2
bunzip2 shape_predictor_5_face_landmarks.dat.bz2
wget https://github.com/davisking/dlib-models/raw/master/dlib_face_recognition_resnet_model_v1.dat.bz2
bunzip2 dlib_face_recognition_resnet_model_v1.dat.bz2
wget https://github.com/davisking/dlib-models/raw/master/mmod_human_face_detector.dat.bz2
bunzip2 mmod_human_face_detector.dat.bz2

Usage

To use go-face in your Go code:

import "github.com/Kagami/go-face"

To install go-face in your $GOPATH:

go get github.com/Kagami/go-face

For further details see GoDoc documentation.

Example

package main

import (
	"fmt"
	"log"
	"path/filepath"

	"github.com/Kagami/go-face"
)

// Path to directory with models and test images. Here it's assumed it
// points to the <https://github.com/Kagami/go-face-testdata> clone.
const dataDir = "testdata"

// This example shows the basic usage of the package: create an
// recognizer, recognize faces, classify them using few known ones.
func main() {
	// Init the recognizer.
	rec, err := face.NewRecognizer(dataDir)
	if err != nil {
		log.Fatalf("Can't init face recognizer: %v", err)
	}
	// Free the resources when you're finished.
	defer rec.Close()

	// Test image with 10 faces.
	testImagePristin := filepath.Join(dataDir, "pristin.jpg")
	// Recognize faces on that image.
	faces, err := rec.RecognizeFile(testImagePristin)
	if err != nil {
		log.Fatalf("Can't recognize: %v", err)
	}
	if len(faces) != 10 {
		log.Fatalf("Wrong number of faces")
	}

	// Fill known samples. In the real world you would use a lot of images
	// for each person to get better classification results but in our
	// example we just get them from one big image.
	var samples []face.Descriptor
	var cats []int32
	for i, f := range faces {
		samples = append(samples, f.Descriptor)
		// Each face is unique on that image so goes to its own category.
		cats = append(cats, int32(i))
	}
	// Name the categories, i.e. people on the image.
	labels := []string{
		"Sungyeon", "Yehana", "Roa", "Eunwoo", "Xiyeon",
		"Kyulkyung", "Nayoung", "Rena", "Kyla", "Yuha",
	}
	// Pass samples to the recognizer.
	rec.SetSamples(samples, cats)

	// Now let's try to classify some not yet known image.
	testImageNayoung := filepath.Join(dataDir, "nayoung.jpg")
	nayoungFace, err := rec.RecognizeSingleFile(testImageNayoung)
	if err != nil {
		log.Fatalf("Can't recognize: %v", err)
	}
	if nayoungFace == nil {
		log.Fatalf("Not a single face on the image")
	}
	catID := rec.Classify(nayoungFace.Descriptor)
	if catID < 0 {
		log.Fatalf("Can't classify")
	}
	// Finally print the classified label. It should be "Nayoung".
	fmt.Println(labels[catID])
}

Run with:

mkdir -p ~/go && cd ~/go  # Or cd to your $GOPATH
mkdir -p src/go-face-example && cd src/go-face-example
git clone https://github.com/Kagami/go-face-testdata testdata
edit main.go  # Paste example code
go get && go run main.go

Test

To fetch test data and run tests:

make test

FAQ

How to improve recognition accuracy

There are few suggestions:

  • Try CNN recognizing
  • Try different tolerance values of ClassifyThreshold
  • Try different size/padding/jittering values of NewRecognizerWithConfig
  • Provide more samples of each category to SetSamples if possible
  • Implement better classify heuristics (see classify.cc)
  • Train network (dlib_face_recognition_resnet_model_v1.dat) on your own test data

License

go-face is licensed under CC0.

Documentation

Overview

Package face implements face recognition for Go using dlib, a popular machine learning toolkit.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SquaredEuclideanDistance

func SquaredEuclideanDistance(d1 Descriptor, d2 Descriptor) (sum float64)

Types

type Descriptor

type Descriptor [128]float32

Descriptor holds 128-dimensional feature vector.

type Face

type Face struct {
	Rectangle  image.Rectangle
	Descriptor Descriptor
	Shapes     []image.Point
	Gender     Gender
	Age        int
	// contains filtered or unexported fields
}

Face holds coordinates and descriptor of the human face.

func New

func New(r image.Rectangle, d Descriptor) Face

New creates new face with the provided parameters.

func NewWithShape

func NewWithShape(r image.Rectangle, s []image.Point, d Descriptor) Face

func (*Face) Close

func (f *Face) Close()

type Gender

type Gender int
const (
	Female Gender = iota
	Male
)

func (Gender) String

func (g Gender) String() string

type ImageLoadError

type ImageLoadError string

An ImageLoadError is returned when provided image file is corrupted.

func (ImageLoadError) Error

func (e ImageLoadError) Error() string

type Recognizer

type Recognizer struct {
	// contains filtered or unexported fields
}

A Recognizer creates face descriptors for provided images and classifies them into categories.

func NewRecognizer

func NewRecognizer() (rec *Recognizer, err error)

NewRecognizer returns a new recognizer interface. modelDir points to directory with shape_predictor_5_face_landmarks.dat and dlib_face_recognition_resnet_model_v1.dat files.

func (*Recognizer) Classify

func (rec *Recognizer) Classify(testSample Descriptor) int

Classify returns class ID for the given descriptor. Negative index is returned if no match. Thread-safe.

func (*Recognizer) ClassifyThreshold

func (rec *Recognizer) ClassifyThreshold(testSample Descriptor, tolerance float32) int

Same as Classify but allows to specify max distance between faces to consider it a match. Start with 0.6 if not sure.

func (*Recognizer) Close

func (rec *Recognizer) Close()

Close frees resources taken by the Recognizer. Safe to call multiple times. Don't use Recognizer after close call.

func (*Recognizer) DetectFromBuffer

func (rec *Recognizer) DetectFromBuffer(imgData []byte) (faces []Face, err error)

Detect returns all faces found on the provided image, sorted from left to right. Empty list is returned if there are no faces, error is returned if there was some error while decoding/processing image. Only JPEG format is currently supported. Thread-safe.

func (*Recognizer) DetectFromBufferCNN

func (rec *Recognizer) DetectFromBufferCNN(imgData []byte) (faces []Face, err error)

func (*Recognizer) DetectFromBufferCustom

func (rec *Recognizer) DetectFromBufferCustom(imgData []byte) (faces []Face, err error)

func (*Recognizer) DetectFromFile

func (rec *Recognizer) DetectFromFile(imgPath string) (faces []Face, err error)

Same as Recognize but accepts image path instead.

func (*Recognizer) DetectFromFileCNN

func (rec *Recognizer) DetectFromFileCNN(imgPath string) (faces []Face, err error)

func (*Recognizer) DetectFromFileCustom

func (rec *Recognizer) DetectFromFileCustom(imgPath string) (faces []Face, err error)

func (*Recognizer) GetAge

func (rec *Recognizer) GetAge(face *Face)

func (*Recognizer) GetGender

func (rec *Recognizer) GetGender(face *Face)

func (*Recognizer) Recognize

func (rec *Recognizer) Recognize(face *Face) error

func (*Recognizer) SetAgeModel

func (rec *Recognizer) SetAgeModel(agePath string) (err error)

func (*Recognizer) SetCNNModel

func (rec *Recognizer) SetCNNModel(cnnResnetPath string) (err error)

func (*Recognizer) SetCustomModel

func (rec *Recognizer) SetCustomModel(cnnResnetPath string) (err error)

func (*Recognizer) SetDescriptorModel

func (rec *Recognizer) SetDescriptorModel(resnetPath string) (err error)

func (*Recognizer) SetGenderModel

func (rec *Recognizer) SetGenderModel(genderPath string) (err error)

func (*Recognizer) SetJittering

func (rec *Recognizer) SetJittering(jittering int)

func (*Recognizer) SetMinImageSize

func (rec *Recognizer) SetMinImageSize(minImageSize int)

func (*Recognizer) SetPadding

func (rec *Recognizer) SetPadding(padding float32)

func (*Recognizer) SetSamples

func (rec *Recognizer) SetSamples(samples []Descriptor, cats []int32)

SetSamples sets known descriptors so you can classify the new ones. Thread-safe.

func (*Recognizer) SetShapeModel

func (rec *Recognizer) SetShapeModel(shapePredictorPath string) (err error)

func (*Recognizer) SetSize

func (rec *Recognizer) SetSize(size int)

type SerializationError

type SerializationError string

An SerializationError is returned when provided model is corrupted.

func (SerializationError) Error

func (e SerializationError) Error() string

type Tracker

type Tracker struct {
	// contains filtered or unexported fields
}

func NewTracker

func NewTracker() (tracker *Tracker, err error)

func (*Tracker) Close

func (tracker *Tracker) Close()

func (*Tracker) Position

func (tracker *Tracker) Position() (rect image.Rectangle, err error)

func (*Tracker) StartBuffer

func (tracker *Tracker) StartBuffer(imgData []byte, rect image.Rectangle) (err error)

func (*Tracker) StartFile

func (tracker *Tracker) StartFile(file string, rect image.Rectangle) (err error)

func (*Tracker) UpdateBuffer

func (tracker *Tracker) UpdateBuffer(imgData []byte) (confidence float32, err error)

func (*Tracker) UpdateFile

func (tracker *Tracker) UpdateFile(file string) (confidence float32, err error)

type UnknownError

type UnknownError string

An UnknownError represents some nonclassified error.

func (UnknownError) Error

func (e UnknownError) Error() string

Jump to

Keyboard shortcuts

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