mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 00:34:13 +01:00
AI: Adjust face recognition config defaults #5167
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
@@ -17,19 +17,19 @@ var (
|
||||
// ScoreThreshold is the base minimum face score accepted by the detector.
|
||||
ScoreThreshold = 9.0
|
||||
// ClusterScoreThreshold is the minimum score required for faces that contribute to automatic clustering.
|
||||
ClusterScoreThreshold = 15
|
||||
ClusterScoreThreshold = 20
|
||||
// SizeThreshold is the minimum detected face size, in pixels.
|
||||
SizeThreshold = 25
|
||||
// ClusterSizeThreshold is the minimum face size, in pixels, for faces considered when forming clusters.
|
||||
ClusterSizeThreshold = 50
|
||||
ClusterSizeThreshold = 60
|
||||
// ClusterDist is the similarity distance threshold that defines the cluster core.
|
||||
ClusterDist = 0.64
|
||||
// ClusterRadius is the maximum normalized distance for cluster samples.
|
||||
ClusterRadius = 0.42
|
||||
// MatchDist is the distance offset threshold used to match new faces with existing clusters.
|
||||
MatchDist = 0.42
|
||||
MatchDist = 0.4
|
||||
// CollisionDist is the minimum distance under which embeddings cannot be distinguished.
|
||||
CollisionDist = 0.1
|
||||
CollisionDist = 0.05
|
||||
// ClusterCore is the minimum number of faces required to seed a cluster core.
|
||||
ClusterCore = 4
|
||||
// SampleThreshold is the number of faces required before automatic clustering begins.
|
||||
@@ -37,7 +37,7 @@ var (
|
||||
// Epsilon is the numeric tolerance used during cluster comparisons.
|
||||
Epsilon = 0.01
|
||||
// SkipChildren controls whether the clustering step omits faces from child samples by default.
|
||||
SkipChildren = true
|
||||
SkipChildren = false
|
||||
// IgnoreBackground determines whether background faces are ignored when generating matches.
|
||||
IgnoreBackground = true
|
||||
)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -15,6 +15,14 @@ func TestRandomDist(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRandomEmbeddings(t *testing.T) {
|
||||
skipChildren := SkipChildren
|
||||
ignoreBackground := IgnoreBackground
|
||||
t.Cleanup(func() {
|
||||
SkipChildren = skipChildren
|
||||
IgnoreBackground = ignoreBackground
|
||||
})
|
||||
SkipChildren = true
|
||||
IgnoreBackground = true
|
||||
t.Run("Regular", func(t *testing.T) {
|
||||
e := RandomEmbeddings(2, RegularFace)
|
||||
for i := range e {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -364,8 +364,8 @@ func (c *Config) Propagate() {
|
||||
face.ClusterRadius = c.FaceClusterRadius()
|
||||
face.ClusterDist = c.FaceClusterDist()
|
||||
face.MatchDist = c.FaceMatchDist()
|
||||
face.SkipChildren = !c.FaceMatchChildren()
|
||||
face.IgnoreBackground = !c.FaceMatchBackground()
|
||||
face.SkipChildren = c.FaceSkipChildren()
|
||||
face.IgnoreBackground = !c.FaceAllowBackground()
|
||||
face.DetectionAngles = c.FaceAngles()
|
||||
if err := face.ConfigureEngine(face.EngineSettings{
|
||||
Name: c.FaceEngine(),
|
||||
|
||||
@@ -260,22 +260,22 @@ func (c *Config) FaceMatchDist() float64 {
|
||||
return c.options.FaceMatchDist
|
||||
}
|
||||
|
||||
// FaceMatchChildren reports whether child embeddings should be matched automatically.
|
||||
func (c *Config) FaceMatchChildren() bool {
|
||||
// FaceSkipChildren reports whether child embeddings should be skipped when matching.
|
||||
func (c *Config) FaceSkipChildren() bool {
|
||||
if c == nil {
|
||||
return false
|
||||
return face.SkipChildren
|
||||
}
|
||||
|
||||
return c.options.FaceMatchChildren
|
||||
return c.options.FaceSkipChildren
|
||||
}
|
||||
|
||||
// FaceMatchBackground reports whether background embeddings should be matched.
|
||||
func (c *Config) FaceMatchBackground() bool {
|
||||
// FaceAllowBackground reports whether background embeddings should not be ignored.
|
||||
func (c *Config) FaceAllowBackground() bool {
|
||||
if c == nil {
|
||||
return false
|
||||
return !face.IgnoreBackground
|
||||
}
|
||||
|
||||
return c.options.FaceMatchBackground
|
||||
return c.options.FaceAllowBackground
|
||||
}
|
||||
|
||||
// FaceAngles returns the set of detection angles in radians.
|
||||
|
||||
@@ -288,18 +288,18 @@ func TestConfig_FaceMatchDist(t *testing.T) {
|
||||
assert.Equal(t, face.MatchDist, c.FaceMatchDist())
|
||||
}
|
||||
|
||||
func TestConfig_FaceMatchChildren(t *testing.T) {
|
||||
func TestConfig_FaceSkipChildren(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
assert.False(t, c.FaceMatchChildren())
|
||||
c.options.FaceMatchChildren = true
|
||||
assert.True(t, c.FaceMatchChildren())
|
||||
assert.False(t, c.FaceSkipChildren())
|
||||
c.options.FaceSkipChildren = true
|
||||
assert.True(t, c.FaceSkipChildren())
|
||||
}
|
||||
|
||||
func TestConfig_FaceMatchBackground(t *testing.T) {
|
||||
func TestConfig_FaceAllowBackground(t *testing.T) {
|
||||
c := NewConfig(CliTestContext())
|
||||
assert.False(t, c.FaceMatchBackground())
|
||||
c.options.FaceMatchBackground = true
|
||||
assert.True(t, c.FaceMatchBackground())
|
||||
assert.False(t, c.FaceAllowBackground())
|
||||
c.options.FaceAllowBackground = true
|
||||
assert.True(t, c.FaceAllowBackground())
|
||||
}
|
||||
|
||||
func TestConfig_FaceAngles(t *testing.T) {
|
||||
|
||||
@@ -1252,14 +1252,14 @@ var Flags = CliFlags{
|
||||
EnvVars: EnvVars("FACE_MATCH_DIST"),
|
||||
}}, {
|
||||
Flag: &cli.BoolFlag{
|
||||
Name: "face-match-children",
|
||||
Usage: "enable automatic matching for child face embeddings",
|
||||
EnvVars: EnvVars("FACE_MATCH_CHILDREN"),
|
||||
Name: "face-skip-children",
|
||||
Usage: "skips automatic matching of child face embeddings",
|
||||
EnvVars: EnvVars("FACE_SKIP_CHILDREN"),
|
||||
}}, {
|
||||
Flag: &cli.BoolFlag{
|
||||
Name: "face-match-background",
|
||||
Usage: "enable automatic matching for background embeddings",
|
||||
EnvVars: EnvVars("FACE_MATCH_BACKGROUND"),
|
||||
Name: "face-allow-background",
|
||||
Usage: "allows matching of probable background embeddings",
|
||||
EnvVars: EnvVars("FACE_ALLOW_BACKGROUND"),
|
||||
}}, {
|
||||
Flag: &cli.StringFlag{
|
||||
Name: "pid-filename",
|
||||
|
||||
@@ -246,8 +246,8 @@ type Options struct {
|
||||
FaceCollisionDist float64 `yaml:"-" json:"-" flag:"face-collision-dist"`
|
||||
FaceEpsilonDist float64 `yaml:"-" json:"-" flag:"face-epsilon-dist"`
|
||||
FaceMatchDist float64 `yaml:"-" json:"-" flag:"face-match-dist"`
|
||||
FaceMatchChildren bool `yaml:"-" json:"-" flag:"face-match-children"`
|
||||
FaceMatchBackground bool `yaml:"-" json:"-" flag:"face-match-background"`
|
||||
FaceSkipChildren bool `yaml:"-" json:"-" flag:"face-skip-children"`
|
||||
FaceAllowBackground bool `yaml:"-" json:"-" flag:"face-allow-background"`
|
||||
PIDFilename string `yaml:"PIDFilename" json:"-" flag:"pid-filename"`
|
||||
LogFilename string `yaml:"LogFilename" json:"-" flag:"log-filename"`
|
||||
DetachServer bool `yaml:"DetachServer" json:"-" flag:"detach-server"`
|
||||
|
||||
@@ -327,8 +327,8 @@ func (c *Config) Report() (rows [][]string, cols []string) {
|
||||
{"face-collision-dist", fmt.Sprintf("%f", c.FaceCollisionDist())},
|
||||
{"face-epsilon-dist", fmt.Sprintf("%f", c.FaceEpsilonDist())},
|
||||
{"face-match-dist", fmt.Sprintf("%f", c.FaceMatchDist())},
|
||||
{"face-match-children", fmt.Sprintf("%t", c.FaceMatchChildren())},
|
||||
{"face-match-background", fmt.Sprintf("%t", c.FaceMatchBackground())},
|
||||
{"face-skip-children", fmt.Sprintf("%t", c.FaceSkipChildren())},
|
||||
{"face-allow-background", fmt.Sprintf("%t", c.FaceAllowBackground())},
|
||||
|
||||
// Daemon Mode.
|
||||
{"pid-filename", c.PIDFilename()},
|
||||
|
||||
@@ -35,10 +35,10 @@ func TestBuildFaceCandidates(t *testing.T) {
|
||||
regular := entity.NewFace("", entity.SrcAuto, face.RandomEmbeddings(3, face.RegularFace))
|
||||
require.NotNil(t, regular)
|
||||
|
||||
children := entity.NewFace("", entity.SrcAuto, face.RandomEmbeddings(3, face.ChildrenFace))
|
||||
require.NotNil(t, children)
|
||||
background := entity.NewFace("", entity.SrcAuto, face.RandomEmbeddings(3, face.BackgroundFace))
|
||||
require.NotNil(t, background)
|
||||
|
||||
faces := entity.Faces{*regular, *children}
|
||||
faces := entity.Faces{*regular, *background}
|
||||
|
||||
index := buildFaceIndex(faces)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user