mirror of
https://github.com/dev6699/face.git
synced 2025-12-24 11:51:07 +08:00
docs: examples
This commit is contained in:
37
README.md
37
README.md
@@ -1,4 +1,9 @@
|
||||
# face
|
||||
|
||||
[](https://pkg.go.dev/github.com/dev6699/face)
|
||||
[](https://goreportcard.com/report/github.com/dev6699/face)
|
||||
[](LICENSE)
|
||||
|
||||
A comprehensive collection of face AI models with integrated pre and post-processing steps, utilizing NVIDIA Triton Inference Server for seamless inference. This repository aims to provide easy-to-use face detection, recognition, and analysis tools.
|
||||
|
||||
## Table of Contents
|
||||
@@ -21,28 +26,34 @@ This repository contains a suite of face AI models designed for various applicat
|
||||
- <b>Easy-to-Use Interface:</b> Simple API for quick integration into various applications.
|
||||
|
||||
## Installation
|
||||
1. Clone the Repository:
|
||||
- ### Use `go get` to install this package:
|
||||
|
||||
```bash
|
||||
go get github.com/dev6699/face
|
||||
```
|
||||
|
||||
- ### Clone the Repository:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/dev6699/face.git
|
||||
cd face
|
||||
```
|
||||
|
||||
2. Open the repository in vscode devcontainer.
|
||||
### Download and Prepare Models:
|
||||
- Navigate to the [Available Models](#available-models) section to find the download links for each model.
|
||||
- Download each model and rename the file to `model.onnx`.
|
||||
- Place each `model.onnx` file into its respective directory within the model_repository folder.
|
||||
- Example: Setting up the YOLOFace model:
|
||||
|
||||
3. Download and Prepare Models:
|
||||
- Navigate to the [Available Models](#available-models) section to find the download links for each model.
|
||||
- Download each model and rename the file to `model.onnx`.
|
||||
- Place each `model.onnx` file into its respective directory within the model_repository folder.
|
||||
- Example: Setting up the YOLOFace model:
|
||||
|
||||
```bash
|
||||
mkdir -p model_repository/yoloface/1
|
||||
wget -O model_repository/yoloface/1/model.onnx <model_url>
|
||||
```
|
||||
Ensure to replace <model_url> with the actual URL provided in the [Available Models](#available-models) section.
|
||||
```bash
|
||||
mkdir -p model_repository/yoloface/1
|
||||
wget -O model_repository/yoloface/1/model.onnx <model_url>
|
||||
```
|
||||
Ensure to replace <model_url> with the actual URL provided in the [Available Models](#available-models) section.
|
||||
|
||||
## Usage
|
||||
Please refer to the [examples](examples) folder for more information on how to use the models and run various tasks.
|
||||
|
||||
1. Start Triton Inference Server:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -15,3 +15,7 @@ services:
|
||||
reservations:
|
||||
devices:
|
||||
- capabilities: [gpu]
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: face_devcontainer_default
|
||||
46
examples/2dfan4/main.go
Normal file
46
examples/2dfan4/main.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/dev6699/face/client"
|
||||
"github.com/dev6699/face/examples"
|
||||
"github.com/dev6699/face/model"
|
||||
_2dfan4 "github.com/dev6699/face/model/2dfan4"
|
||||
"github.com/dev6699/face/model/yoloface"
|
||||
"gocv.io/x/gocv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
faceDetectorScore := float32(0.5)
|
||||
iouThreshold := 0.4
|
||||
yolofaceFactory := yoloface.NewFactory(faceDetectorScore, iouThreshold)
|
||||
_2dfan4Factory := _2dfan4.NewFactory()
|
||||
err := client.Init(
|
||||
"tritonserver:8001",
|
||||
[]model.ModelMeta{
|
||||
yolofaceFactory(),
|
||||
_2dfan4Factory(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
img := gocv.IMRead("../image.jpg", gocv.IMReadColor)
|
||||
yoloFaceOutput, err := client.Infer(yolofaceFactory, &yoloface.Input{Img: img})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, d := range yoloFaceOutput.Detections {
|
||||
fanOutput, err := client.Infer(_2dfan4Factory, &_2dfan4.Input{Img: img, BoundingBox: d.BoundingBox})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
examples.DrawPoints(&img, fanOutput.FaceLandmark68.Data, examples.Red, 2)
|
||||
}
|
||||
|
||||
gocv.IMWrite("output.jpg", img)
|
||||
}
|
||||
52
examples/arcface/main.go
Normal file
52
examples/arcface/main.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/dev6699/face/client"
|
||||
"github.com/dev6699/face/model"
|
||||
"github.com/dev6699/face/model/arcface"
|
||||
"github.com/dev6699/face/model/yoloface"
|
||||
"gocv.io/x/gocv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
faceDetectorScore := float32(0.5)
|
||||
iouThreshold := 0.4
|
||||
yolofaceFactory := yoloface.NewFactory(faceDetectorScore, iouThreshold)
|
||||
arcfaceFactory := arcface.NewFactory()
|
||||
err := client.Init(
|
||||
"tritonserver:8001",
|
||||
[]model.ModelMeta{
|
||||
yolofaceFactory(),
|
||||
arcfaceFactory(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
img := gocv.IMRead("../image.jpg", gocv.IMReadColor)
|
||||
yoloFaceOutput, err := client.Infer(yolofaceFactory, &yoloface.Input{Img: img})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
faceEmbeddings := [][]float32{}
|
||||
for _, d := range yoloFaceOutput.Detections {
|
||||
arcfaceOutput, err := client.Infer(arcfaceFactory, &arcface.Input{Img: img, FaceLandmark5: d.FaceLandmark5})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
faceEmbeddings = append(faceEmbeddings, arcfaceOutput.NormedEmbedding)
|
||||
}
|
||||
|
||||
similarDistance := 0.6
|
||||
for i, f1 := range faceEmbeddings {
|
||||
for j, f2 := range faceEmbeddings {
|
||||
faceDistance := model.CalcFaceDistance(f1, f2)
|
||||
isSimilar := faceDistance < similarDistance
|
||||
fmt.Printf("Face %d & %d: %.2f %v\n", i, j, faceDistance, isSimilar)
|
||||
}
|
||||
}
|
||||
}
|
||||
51
examples/genderage/main.go
Normal file
51
examples/genderage/main.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/dev6699/face/client"
|
||||
"github.com/dev6699/face/examples"
|
||||
"github.com/dev6699/face/model"
|
||||
"github.com/dev6699/face/model/genderage"
|
||||
"github.com/dev6699/face/model/yoloface"
|
||||
"gocv.io/x/gocv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
faceDetectorScore := float32(0.5)
|
||||
iouThreshold := 0.4
|
||||
yolofaceFactory := yoloface.NewFactory(faceDetectorScore, iouThreshold)
|
||||
genderAgeFactory := genderage.NewFactory()
|
||||
err := client.Init(
|
||||
"tritonserver:8001",
|
||||
[]model.ModelMeta{
|
||||
yolofaceFactory(),
|
||||
genderAgeFactory(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
img := gocv.IMRead("../image.jpg", gocv.IMReadColor)
|
||||
yoloFaceOutput, err := client.Infer(yolofaceFactory, &yoloface.Input{Img: img})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, d := range yoloFaceOutput.Detections {
|
||||
genderAgeOutput, err := client.Infer(genderAgeFactory, &genderage.Input{Img: img, BoundingBox: d.BoundingBox})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
genderString := "M"
|
||||
if genderAgeOutput.Gender == 0 {
|
||||
genderString = "F"
|
||||
}
|
||||
examples.DrawBoundingBoxes(&img, d.BoundingBox, fmt.Sprintf("%s %d", genderString, genderAgeOutput.Age), examples.Green, examples.Red)
|
||||
}
|
||||
|
||||
gocv.IMWrite("output.jpg", img)
|
||||
}
|
||||
43
examples/gfpgan/main.go
Normal file
43
examples/gfpgan/main.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/dev6699/face/client"
|
||||
"github.com/dev6699/face/model"
|
||||
"github.com/dev6699/face/model/gfpgan"
|
||||
"github.com/dev6699/face/model/yoloface"
|
||||
"gocv.io/x/gocv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
faceDetectorScore := float32(0.5)
|
||||
iouThreshold := 0.4
|
||||
yolofaceFactory := yoloface.NewFactory(faceDetectorScore, iouThreshold)
|
||||
gfpganFactory := gfpgan.NewFactory(80.0)
|
||||
err := client.Init(
|
||||
"tritonserver:8001",
|
||||
[]model.ModelMeta{
|
||||
yolofaceFactory(),
|
||||
gfpganFactory(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
img := gocv.IMRead("../image.jpg", gocv.IMReadColor)
|
||||
yoloFaceOutput, err := client.Infer(yolofaceFactory, &yoloface.Input{Img: img})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for i, d := range yoloFaceOutput.Detections {
|
||||
gfpganOutput, err := client.Infer(gfpganFactory, &gfpgan.Input{Img: img, FaceLandmark5: d.FaceLandmark5})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
gocv.IMWrite(fmt.Sprintf("output%d.jpg", i+1), gfpganOutput.OutFrame)
|
||||
}
|
||||
}
|
||||
BIN
examples/image.jpg
Normal file
BIN
examples/image.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
26
examples/util.go
Normal file
26
examples/util.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package examples
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"github.com/dev6699/face/model"
|
||||
"gocv.io/x/gocv"
|
||||
)
|
||||
|
||||
var (
|
||||
Red = color.RGBA{R: 255, G: 0, B: 0, A: 255}
|
||||
Green = color.RGBA{R: 0, G: 255, B: 0, A: 255}
|
||||
Blue = color.RGBA{R: 0, G: 0, B: 255, A: 255}
|
||||
)
|
||||
|
||||
func DrawBoundingBoxes(img *gocv.Mat, box model.BoundingBox, text string, boxColor, textColor color.RGBA) {
|
||||
gocv.Rectangle(img, image.Rectangle{Min: image.Point{X: int(box.X1), Y: int(box.Y1)}, Max: image.Point{X: int(box.X2), Y: int(box.Y2)}}, boxColor, 2)
|
||||
gocv.PutText(img, text, image.Point{X: int(box.X1), Y: int(box.Y1) - 5}, gocv.FontHersheySimplex, 0.5, textColor, 2)
|
||||
}
|
||||
|
||||
func DrawPoints(img *gocv.Mat, points []gocv.Point2f, col color.RGBA, radius int) {
|
||||
for _, pt := range points {
|
||||
gocv.Circle(img, image.Pt(int(pt.X), int(pt.Y)), radius, col, -1)
|
||||
}
|
||||
}
|
||||
40
examples/yoloface/main.go
Normal file
40
examples/yoloface/main.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/dev6699/face/client"
|
||||
"github.com/dev6699/face/examples"
|
||||
"github.com/dev6699/face/model"
|
||||
"github.com/dev6699/face/model/yoloface"
|
||||
"gocv.io/x/gocv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
faceDetectorScore := float32(0.5)
|
||||
iouThreshold := 0.4
|
||||
yolofaceFactory := yoloface.NewFactory(faceDetectorScore, iouThreshold)
|
||||
err := client.Init(
|
||||
"tritonserver:8001",
|
||||
[]model.ModelMeta{
|
||||
yolofaceFactory(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
img := gocv.IMRead("../image.jpg", gocv.IMReadColor)
|
||||
yoloFaceOutput, err := client.Infer(yolofaceFactory, &yoloface.Input{Img: img})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, d := range yoloFaceOutput.Detections {
|
||||
examples.DrawBoundingBoxes(&img, d.BoundingBox, fmt.Sprintf("Score: %.2f", d.Confidence), examples.Green, examples.Green)
|
||||
examples.DrawPoints(&img, d.FaceLandmark5, examples.Red, 3)
|
||||
}
|
||||
|
||||
gocv.IMWrite("output.jpg", img)
|
||||
}
|
||||
@@ -287,3 +287,25 @@ func getInverseVisionFrame(cropVisionFrame gocv.Mat, inverseMatrix gocv.Mat, tem
|
||||
inverseVisionFrame.ConvertTo(&inverseVisionFrame, gocv.MatTypeCV64F)
|
||||
return inverseVisionFrame
|
||||
}
|
||||
|
||||
// CalcFaceDistance to calculate the distance between two face embeddings
|
||||
func CalcFaceDistance(faceEmbedding, referenceFaceEmbedding []float32) float64 {
|
||||
if len(faceEmbedding) == 0 || len(referenceFaceEmbedding) == 0 || len(faceEmbedding) != len(referenceFaceEmbedding) {
|
||||
return 0
|
||||
}
|
||||
|
||||
dotProduct := dotProduct(faceEmbedding, referenceFaceEmbedding)
|
||||
return 1.0 - float64(dotProduct)
|
||||
}
|
||||
|
||||
func dotProduct(v1, v2 []float32) float32 {
|
||||
if len(v1) != len(v2) {
|
||||
return 0
|
||||
}
|
||||
|
||||
var result float32
|
||||
for i := 0; i < len(v1); i++ {
|
||||
result += v1[i] * v2[i]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user