File size: 1,815 Bytes
ca7217f | 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 | package detector
import (
"image"
pigo "github.com/esimov/pigo/core"
"github.com/metatube-community/metatube-sdk-go/common/cluster"
"github.com/metatube-community/metatube-sdk-go/detector/internal/position"
)
const (
// tolerance defines the max distance between
// two vectors to be considered as the same.
tolerance = 0.05
)
func computeFaceWeight(face pigo.Detection) float64 {
// face size (scale) * quality factor.
return float64(face.Scale) * float64(face.Q)
}
func extractFaceVector(img image.Image, face pigo.Detection) position.Vector {
var (
width = img.Bounds().Dx()
height = img.Bounds().Dy()
)
return position.NewVector(
position.Position(float64(face.Col)/float64(width)), // X
position.Position(float64(face.Row)/float64(height)), // Y
)
}
func dominantAxisByRatio(img image.Image, ratio float64) int {
var (
width = img.Bounds().Dx()
height = img.Bounds().Dy()
)
if int(float64(height)*ratio) < width {
return 0 // X
} else {
return 1 // Y
}
}
func clusterFaceVectors(img image.Image, faces []pigo.Detection, dims ...int) []cluster.Group[position.WeightedVector, float64] {
vecs := make([]position.WeightedVector, len(faces))
for i, face := range faces {
vec := extractFaceVector(img, face)
vecs[i] = position.NewWeightedVector(
// select vector dimensions:
// X:(0), Y:(1), XY:(0,1).
vec.Select(dims...),
computeFaceWeight(face),
)
}
return cluster.GroupByDistance(vecs, tolerance)
}
func getDominantVector(groups []cluster.Group[position.WeightedVector, float64]) (position.Vector, bool) {
if len(groups) == 0 {
return position.Vector{}, false
}
// sort weighted vector groups.
cluster.SortGroupsByWeight(groups)
// calculate the average vector.
vec := position.WeightedAverageVector(groups[0].Items)
return vec, true
}
|