-
Notifications
You must be signed in to change notification settings - Fork 1
/
redface.go
115 lines (96 loc) · 2.14 KB
/
redface.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package redface
import (
"encoding/json"
"fmt"
"math"
"os"
"time"
"github.com/abihf/redface/capture"
"github.com/abihf/redface/facerec"
)
const (
infraredDevice = "/dev/video2"
dataDir = "/usr/share/redface"
)
type VerifyOption struct {
ModelFile string
Timeout time.Duration
Threshold float64
}
func Verify(rec *facerec.Recognizer, opt *VerifyOption) (bool, error) {
models, err := readModels(opt.ModelFile)
if err != nil {
return false, err
}
result := false
var timeout time.Time
if opt.Timeout > 0 {
timeout = time.Now().Add(opt.Timeout)
}
capOption := &capture.Option{
Device: infraredDevice,
}
noFaceFrames := 0
err = capture.Capture(capOption, func(frame *capture.Frame) (bool, error) {
if opt.Timeout > 0 && time.Now().Sub(timeout) >= 0 {
return false, fmt.Errorf("Timeout %v", opt.Timeout)
}
rgb := grayToRGB(frame.Buffer)
frame.Free()
recStart := time.Now()
faces, err := rec.Recognize(rgb, frame.Width, frame.Height, 0)
recDuration := time.Now().Sub(recStart)
if err != nil {
return false, err
}
if len(faces) == 0 {
noFaceFrames++
return true, nil
}
fmt.Printf("* Found %d faces in %v\n", len(faces), recDuration)
distance := math.MaxFloat64
for i, face := range faces {
fmt.Printf(" - Face [%d]:", i)
for _, model := range models {
d := facerec.GetDistance(model, face.Descriptor)
fmt.Printf(" %.3f", d)
if d < distance {
distance = d
}
}
println()
}
if distance < opt.Threshold {
result = true
return false, nil
}
return true, nil
})
if noFaceFrames > 0 {
fmt.Printf("> Frames without face found: %d\n\n", noFaceFrames)
}
if err != nil {
return false, err
}
return result, nil
}
func readModels(file string) ([]facerec.Descriptor, error) {
var res []facerec.Descriptor
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
err = json.NewDecoder(f).Decode(&res)
return res, err
}
func grayToRGB(gray []byte) []byte {
rgb := make([]byte, len(gray)*3)
for i := 0; i < len(gray); i++ {
offset := i * 3
rgb[offset+0] = gray[i]
rgb[offset+1] = gray[i]
rgb[offset+2] = gray[i]
}
return rgb
}