People: Remove face embeddings and landmarks from JSON response #22

Improves performance by reducing response size.
This commit is contained in:
Michael Mayer 2021-08-16 01:45:36 +02:00
parent 94adc2f106
commit 003982afe0
8 changed files with 84 additions and 83 deletions

View file

@ -15,16 +15,16 @@ type Faces []Face
// Face represents the face of a Subject.
type Face struct {
ID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false;" json:"ID" yaml:"ID"`
FaceSrc string `gorm:"type:VARBINARY(8);" json:"Src" yaml:"Src,omitempty"`
SubjectUID string `gorm:"type:VARBINARY(42);index;" json:"SubjectUID" yaml:"SubjectUID,omitempty"`
Collisions int `json:"Collisions" yaml:"Collisions,omitempty"`
Samples int `json:"Samples" yaml:"Samples,omitempty"`
Radius float64 `json:"Radius" yaml:"Radius,omitempty"`
EmbeddingJSON []byte `gorm:"type:MEDIUMBLOB;" json:"EmbeddingJSON" yaml:"EmbeddingJSON,omitempty"`
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"UpdatedAt,omitempty"`
embedding Embedding `gorm:"-"`
ID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false;" json:"ID" yaml:"ID"`
FaceSrc string `gorm:"type:VARBINARY(8);" json:"Src" yaml:"Src,omitempty"`
SubjectUID string `gorm:"type:VARBINARY(42);index;" json:"SubjectUID" yaml:"SubjectUID,omitempty"`
Collisions int `json:"Collisions" yaml:"Collisions,omitempty"`
Samples int `json:"Samples" yaml:"Samples,omitempty"`
Radius float64 `json:"Radius" yaml:"Radius,omitempty"`
EmbeddingJSON json.RawMessage `gorm:"type:MEDIUMBLOB;" json:"-" yaml:"EmbeddingJSON,omitempty"`
CreatedAt time.Time `json:"CreatedAt" yaml:"CreatedAt,omitempty"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"UpdatedAt,omitempty"`
embedding Embedding `gorm:"-"`
}
// UnknownFace can be used as a placeholder for unknown faces.

View file

@ -414,7 +414,7 @@ func (m *File) AddFace(f face.Face, refUID string) {
// FaceCount returns the current number of valid faces detected.
func (m *File) FaceCount() (c int) {
if err := Db().Model(Marker{}).Where("marker_invalid = 0 AND file_id = ?", m.ID).
if err := Db().Model(Marker{}).Where("file_id = ? AND marker_invalid = 0", m.ID).
Count(&c).Error; err != nil {
log.Errorf("file: %s (count faces)", err)
return 0

View file

@ -20,26 +20,26 @@ const (
// Marker represents an image marker point.
type Marker struct {
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
FileID uint `gorm:"index;" json:"-" yaml:"-"`
MarkerType string `gorm:"type:VARBINARY(8);index:idx_markers_subject;default:'';" json:"Type" yaml:"Type"`
MarkerSrc string `gorm:"type:VARBINARY(8);default:'';" json:"Src" yaml:"Src,omitempty"`
MarkerName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name,omitempty"`
SubjectUID string `gorm:"type:VARBINARY(42);index:idx_markers_subject;" json:"SubjectUID" yaml:"SubjectUID,omitempty"`
SubjectSrc string `gorm:"type:VARBINARY(8);default:'';" json:"SubjectSrc" yaml:"SubjectSrc,omitempty"`
FaceID string `gorm:"type:VARBINARY(42);index;" json:"FaceID" yaml:"FaceID,omitempty"`
EmbeddingsJSON []byte `gorm:"type:MEDIUMBLOB;" json:"EmbeddingsJSON" yaml:"EmbeddingsJSON,omitempty"`
MarkerScore int `gorm:"type:SMALLINT" json:"Score" yaml:"Score,omitempty"`
MarkerInvalid bool `json:"Invalid" yaml:"Invalid,omitempty"`
MarkerJSON []byte `gorm:"type:MEDIUMBLOB;" json:"MarkerJSON" yaml:"MarkerJSON,omitempty"`
X float32 `gorm:"type:FLOAT;" json:"X" yaml:"X,omitempty"`
Y float32 `gorm:"type:FLOAT;" json:"Y" yaml:"Y,omitempty"`
W float32 `gorm:"type:FLOAT;" json:"W" yaml:"W,omitempty"`
H float32 `gorm:"type:FLOAT;" json:"H" yaml:"H,omitempty"`
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
FileID uint `gorm:"index;" json:"-" yaml:"-"`
MarkerType string `gorm:"type:VARBINARY(8);index:idx_markers_subject;default:'';" json:"Type" yaml:"Type"`
MarkerSrc string `gorm:"type:VARBINARY(8);default:'';" json:"Src" yaml:"Src,omitempty"`
MarkerName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name,omitempty"`
SubjectUID string `gorm:"type:VARBINARY(42);index:idx_markers_subject;" json:"SubjectUID" yaml:"SubjectUID,omitempty"`
SubjectSrc string `gorm:"type:VARBINARY(8);default:'';" json:"SubjectSrc" yaml:"SubjectSrc,omitempty"`
Subject *Subject `gorm:"foreignkey:SubjectUID;association_foreignkey:SubjectUID;association_autoupdate:false;association_autocreate:false;association_save_reference:false" json:"Subject,omitempty" yaml:"-"`
FaceID string `gorm:"type:VARBINARY(42);index;" json:"FaceID" yaml:"FaceID,omitempty"`
EmbeddingsJSON json.RawMessage `gorm:"type:MEDIUMBLOB;" json:"-" yaml:"EmbeddingsJSON,omitempty"`
embeddings Embeddings `gorm:"-"`
LandmarksJSON json.RawMessage `gorm:"type:MEDIUMBLOB;" json:"-" yaml:"LandmarksJSON,omitempty"`
X float32 `gorm:"type:FLOAT;" json:"X" yaml:"X,omitempty"`
Y float32 `gorm:"type:FLOAT;" json:"Y" yaml:"Y,omitempty"`
W float32 `gorm:"type:FLOAT;" json:"W" yaml:"W,omitempty"`
H float32 `gorm:"type:FLOAT;" json:"H" yaml:"H,omitempty"`
Score int `gorm:"type:SMALLINT" json:"Score" yaml:"Score,omitempty"`
MarkerInvalid bool `json:"Invalid" yaml:"Invalid,omitempty"`
CreatedAt time.Time
UpdatedAt time.Time
Subject *Subject `gorm:"foreignkey:SubjectUID;association_foreignkey:SubjectUID;association_autoupdate:false;association_autocreate:false;association_save_reference:false" json:"Subject,omitempty" yaml:"-"`
embeddings Embeddings `gorm:"-"`
}
// UnknownMarker can be used as a default for unknown markers.
@ -51,10 +51,10 @@ func (Marker) TableName() string {
}
// NewMarker creates a new entity.
func NewMarker(fileUID uint, refUID, markerSrc, markerType string, x, y, w, h float32) *Marker {
func NewMarker(fileID uint, subjectUID, markerSrc, markerType string, x, y, w, h float32) *Marker {
m := &Marker{
FileID: fileUID,
SubjectUID: refUID,
FileID: fileID,
SubjectUID: subjectUID,
MarkerSrc: markerSrc,
MarkerType: markerType,
X: x,
@ -72,9 +72,9 @@ func NewFaceMarker(f face.Face, fileID uint, refUID string) *Marker {
m := NewMarker(fileID, refUID, SrcImage, MarkerFace, pos.X, pos.Y, pos.W, pos.H)
m.MarkerScore = f.Score
m.MarkerJSON = f.RelativeLandmarksJSON()
m.EmbeddingsJSON = f.EmbeddingsJSON()
m.LandmarksJSON = f.RelativeLandmarksJSON()
m.Score = f.Score
return m
}
@ -208,8 +208,8 @@ func UpdateOrCreateMarker(m *Marker) (*Marker, error) {
"Y": m.Y,
"W": m.W,
"H": m.H,
"MarkerScore": m.MarkerScore,
"MarkerJSON": m.MarkerJSON,
"Score": m.Score,
"LandmarksJSON": m.LandmarksJSON,
"EmbeddingsJSON": m.EmbeddingsJSON,
"SubjectUID": m.SubjectUID,
})

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,7 @@
package entity
import (
"encoding/json"
"fmt"
"sync"
"time"
@ -22,26 +23,26 @@ type Subjects []Subject
// Subject represents a named photo subject, typically a person.
type Subject struct {
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
SubjectUID string `gorm:"type:VARBINARY(42);unique_index;" json:"UID" yaml:"UID"`
SubjectType string `gorm:"type:VARBINARY(8);" json:"Type" yaml:"Type"`
SubjectSrc string `gorm:"type:VARBINARY(8);" json:"Src" yaml:"Src"`
SubjectSlug string `gorm:"type:VARBINARY(255);index;" json:"Slug" yaml:"-"`
SubjectName string `gorm:"type:VARCHAR(255);index;" json:"Name" yaml:"Name"`
SubjectDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
SubjectNotes string `gorm:"type:TEXT;" json:"Notes,omitempty" yaml:"Notes,omitempty"`
SubjectJSON []byte `gorm:"type:MEDIUMBLOB;" json:"JSON,omitempty" yaml:"JSON,omitempty"`
Favorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
Hidden bool `json:"Hidden" yaml:"Hidden,omitempty"`
Private bool `json:"Private" yaml:"Private,omitempty"`
PhotoCount int `gorm:"default:0" json:"PhotoCount" yaml:"-"`
BirthYear int `json:"BirthYear" yaml:"BirthYear,omitempty"`
BirthMonth int `json:"BirthMonth" yaml:"BirthMonth,omitempty"`
BirthDay int `json:"BirthDay" yaml:"BirthDay,omitempty"`
PassedAway *time.Time `json:"PassedAway,omitempty" yaml:"PassedAway,omitempty"`
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
SubjectUID string `gorm:"type:VARBINARY(42);unique_index;" json:"UID" yaml:"UID"`
SubjectType string `gorm:"type:VARBINARY(8);" json:"Type" yaml:"Type"`
SubjectSrc string `gorm:"type:VARBINARY(8);" json:"Src" yaml:"Src"`
SubjectSlug string `gorm:"type:VARBINARY(255);index;" json:"Slug" yaml:"-"`
SubjectName string `gorm:"type:VARCHAR(255);index;" json:"Name" yaml:"Name"`
SubjectDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
SubjectNotes string `gorm:"type:TEXT;" json:"Notes,omitempty" yaml:"Notes,omitempty"`
MetadataJSON json.RawMessage `gorm:"type:MEDIUMBLOB;" json:"Metadata,omitempty" yaml:"Metadata,omitempty"`
Favorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
Hidden bool `json:"Hidden" yaml:"Hidden,omitempty"`
Private bool `json:"Private" yaml:"Private,omitempty"`
PhotoCount int `gorm:"default:0" json:"PhotoCount" yaml:"-"`
BirthYear int `json:"BirthYear" yaml:"BirthYear,omitempty"`
BirthMonth int `json:"BirthMonth" yaml:"BirthMonth,omitempty"`
BirthDay int `json:"BirthDay" yaml:"BirthDay,omitempty"`
PassedAway *time.Time `json:"PassedAway,omitempty" yaml:"PassedAway,omitempty"`
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
UpdatedAt time.Time `json:"UpdatedAt" yaml:"-"`
DeletedAt *time.Time `sql:"index" json:"DeletedAt,omitempty" yaml:"-"`
}
// UnknownPerson can be used as a placeholder for unknown people.

View file

@ -30,7 +30,7 @@ var SubjectFixtures = SubjectMap{
Hidden: false,
SubjectDescription: "Subject Description",
SubjectNotes: "Short Note",
SubjectJSON: []byte(""),
MetadataJSON: []byte(""),
PhotoCount: 1,
BirthYear: 2000,
BirthMonth: 5,

View file

@ -4,13 +4,13 @@ import "github.com/ulule/deepcopier"
// Marker represents an image marker edit form.
type Marker struct {
MarkerType string `json:"Type"`
SubjectUID string `json:"SubjectUID"`
SubjectSrc string `json:"SubjectSrc"`
MarkerName string `json:"Name"`
MarkerSrc string `json:"Src"`
MarkerScore int `json:"Score"`
MarkerInvalid bool `json:"Invalid"`
MarkerType string `json:"Type"`
MarkerSrc string `json:"Src"`
MarkerName string `json:"Name"`
SubjectUID string `json:"SubjectUID"`
SubjectSrc string `json:"SubjectSrc"`
Score int `json:"Score"`
Invalid bool `json:"Invalid"`
}
func NewMarker(m interface{}) (f Marker, err error) {

View file

@ -9,21 +9,21 @@ import (
func TestNewMarker(t *testing.T) {
t.Run("success", func(t *testing.T) {
var m = struct {
MarkerType string
MarkerSrc string
MarkerName string
SubjectUID string
SubjectSrc string
MarkerScore int
MarkerInvalid bool
MarkerType string
MarkerSrc string
MarkerName string
SubjectUID string
SubjectSrc string
Score int
Invalid bool
}{
MarkerType: "face",
MarkerSrc: "image",
MarkerName: "Foo",
SubjectUID: "3h59wvth837b5vyiub35",
SubjectSrc: "meta",
MarkerScore: 100,
MarkerInvalid: true,
MarkerType: "face",
MarkerSrc: "image",
MarkerName: "Foo",
SubjectUID: "3h59wvth837b5vyiub35",
SubjectSrc: "meta",
Score: 100,
Invalid: true,
}
f, err := NewMarker(m)
@ -37,7 +37,7 @@ func TestNewMarker(t *testing.T) {
assert.Equal(t, "Foo", f.MarkerName)
assert.Equal(t, "3h59wvth837b5vyiub35", f.SubjectUID)
assert.Equal(t, "meta", f.SubjectSrc)
assert.Equal(t, 100, f.MarkerScore)
assert.Equal(t, true, f.MarkerInvalid)
assert.Equal(t, 100, f.Score)
assert.Equal(t, true, f.Invalid)
})
}