feat: added inswapper

This commit is contained in:
kweijack
2024-07-06 07:26:45 +00:00
parent aba1bda45d
commit 7ecb8bdf96
9 changed files with 696 additions and 0 deletions

View File

@@ -84,6 +84,15 @@ This repository contains a suite of face AI models designed for various applicat
<img src="docs/gender_age.jpg" height=200>
### Inswapper
- Model Name: [inswapper_128_fp16](model/inswapper/inswapper.go)
- Description: Swaps the target face with a source face, enabling realistic face replacement in images.
- Download Link: [Download Inswapper Model](https://github.com/facefusion/facefusion-assets/releases/download/models/inswapper_128_fp16.onnx)
| Source | Target | Output |
| :----: | :----: | :----: |
| <img src="docs/inswapper_1.jpg" height=200> | <img src="docs/inswapper_2.jpg" height=200> | <img src="docs/inswapper_3.jpg" height=200> |
### YOLOFace
- Model Name: [yoloface](model/yoloface/yoloface.go)
- Description: Detects face bounding boxes and the 5 key facial landmarks (landmark5) using the YOLO architecture.

BIN
docs/inswapper_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
docs/inswapper_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

BIN
docs/inswapper_3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,41 @@
package inswapper
import (
"github.com/dev6699/face/model"
"gocv.io/x/gocv"
)
type Model struct {
affineMatrix gocv.Mat
}
type Input struct {
CropVisionFrame gocv.Mat
Embedding []float32
}
type Output struct {
CropVisionFrame gocv.Mat
}
type TModel = model.Model[*Input, *Output]
var _ TModel = &Model{}
func NewFactory() func() TModel {
return func() TModel {
return New()
}
}
func New() *Model {
return &Model{}
}
func (m *Model) ModelName() string {
return "inswapper_128_fp16"
}
func (m *Model) ModelVersion() string {
return "1"
}

49
model/inswapper/post.go Normal file
View File

@@ -0,0 +1,49 @@
package inswapper
import (
"math"
"github.com/dev6699/face/model"
"gocv.io/x/gocv"
)
func (m *Model) PostProcess(rawOutputContents [][]byte) (*Output, error) {
// "outputs": [
// {
// "name": "output",
// "datatype": "FP32",
// "shape": [
// 1,
// 3,
// 128,
// 128
// ]
// }
// ]
output, err := model.BytesToFloat32Slice(rawOutputContents[0])
if err != nil {
return nil, err
}
d := make([]uint8, len(output))
j := 0
for i := 0; i < len(output); i += 3 {
d[i+2] = uint8(math.Round(float64(output[j]) * 255.0))
d[i+1] = uint8(math.Round(float64(output[len(d)/3+j]) * 255.0))
d[i] = uint8(math.Round(float64(output[len(d)/3*2+j]) * 255.0))
j++
}
width := 128
height := 128
imgType := gocv.MatTypeCV8UC3
mat, err := gocv.NewMatFromBytes(height, width, imgType, d)
if err != nil {
return nil, err
}
return &Output{
CropVisionFrame: mat,
}, nil
}

79
model/inswapper/pre.go Normal file
View File

@@ -0,0 +1,79 @@
package inswapper
import (
"math"
"github.com/dev6699/face/protobuf"
)
func (m *Model) PreProcess(i *Input) ([]*protobuf.InferTensorContents, error) {
data, _ := i.CropVisionFrame.DataPtrUint8()
d := make([]float32, len(data))
j := 0
for i := 0; i < len(data); i += 3 {
d[j] = float32(data[i+2]) / 255.0
d[len(d)/3+j] = float32(data[i+1]) / 255.0
d[len(d)/3*2+j] = float32(data[i]) / 255.0
j++
}
sourceEmbedding := prepareSourceEmbedding(i.Embedding)
return []*protobuf.InferTensorContents{
{
Fp32Contents: sourceEmbedding,
},
{
Fp32Contents: d,
},
}, nil
}
func prepareSourceEmbedding(embedding []float32) []float32 {
sourceEmbedding := embedding
dot := matrixMultiply([][]float32{sourceEmbedding}, initializer)
normSource := norm(sourceEmbedding)
normalized := scale(dot[0], 1/normSource)
return normalized
}
func matrixMultiply(A, B [][]float32) [][]float32 {
m := len(A)
n := len(A[0])
p := len(B[0])
C := make([][]float32, m)
for i := range C {
C[i] = make([]float32, p)
}
// Perform matrix multiplication
for i := 0; i < m; i++ {
for k := 0; k < p; k++ {
sum := float32(0.0)
for j := 0; j < n; j++ {
sum += A[i][j] * B[j][k]
}
C[i][k] = sum
}
}
return C
}
func norm(vector []float32) float32 {
var norm float32
for _, v := range vector {
norm += v * v
}
return float32(math.Sqrt(float64(norm)))
}
func scale(vector []float32, scalar float32) []float32 {
result := make([]float32, len(vector))
for i, v := range vector {
result[i] = v * scalar
}
return result
}

View File

@@ -0,0 +1,2 @@
name: "inswapper_128_fp16"
platform: "onnxruntime_onnx"