parent
ca0d52b36e
commit
45355c7303
|
@ -55,9 +55,9 @@ var Entities = Types{
|
|||
"photos_keywords": &PhotoKeyword{},
|
||||
"passwords": &Password{},
|
||||
"links": &Link{},
|
||||
Marker{}.TableName(): &Marker{},
|
||||
Person{}.TableName(): &Person{},
|
||||
PersonFace{}.TableName(): &PersonFace{},
|
||||
Face{}.TableName(): &Face{},
|
||||
Marker{}.TableName(): &Marker{},
|
||||
}
|
||||
|
||||
type RowCount struct {
|
||||
|
|
|
@ -6,10 +6,10 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
type PeopleFaces []PersonFace
|
||||
type Faces []Face
|
||||
|
||||
// PersonFace represents the face of a Person.
|
||||
type PersonFace struct {
|
||||
// Face represents the face of a Person.
|
||||
type Face struct {
|
||||
ID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false;" json:"ID" yaml:"ID"`
|
||||
PersonUID string `gorm:"type:VARBINARY(42);index;" json:"PersonUID" yaml:"PersonUID,omitempty"`
|
||||
Embedding string `gorm:"type:LONGTEXT;" json:"Embedding" yaml:"Embedding,omitempty"`
|
||||
|
@ -19,16 +19,16 @@ type PersonFace struct {
|
|||
}
|
||||
|
||||
// TableName returns the entity database table name.
|
||||
func (PersonFace) TableName() string {
|
||||
return "people_faces_dev"
|
||||
func (Face) TableName() string {
|
||||
return "faces_dev2"
|
||||
}
|
||||
|
||||
// NewPersonFace returns a new face.
|
||||
func NewPersonFace(personUID, embedding string) *PersonFace {
|
||||
func NewPersonFace(personUID, embedding string) *Face {
|
||||
timeStamp := Timestamp()
|
||||
s := sha1.Sum([]byte(embedding))
|
||||
|
||||
result := &PersonFace{
|
||||
result := &Face{
|
||||
ID: base32.StdEncoding.EncodeToString(s[:]),
|
||||
PersonUID: personUID,
|
||||
Embedding: embedding,
|
||||
|
@ -40,12 +40,12 @@ func NewPersonFace(personUID, embedding string) *PersonFace {
|
|||
}
|
||||
|
||||
// UnmarshalEmbedding parses the face embedding JSON string.
|
||||
func (m *PersonFace) UnmarshalEmbedding() (result Embedding) {
|
||||
func (m *Face) UnmarshalEmbedding() (result Embedding) {
|
||||
return UnmarshalEmbedding(m.Embedding)
|
||||
}
|
||||
|
||||
// Save updates the existing or inserts a new face.
|
||||
func (m *PersonFace) Save() error {
|
||||
func (m *Face) Save() error {
|
||||
peopleMutex.Lock()
|
||||
defer peopleMutex.Unlock()
|
||||
|
||||
|
@ -53,7 +53,7 @@ func (m *PersonFace) Save() error {
|
|||
}
|
||||
|
||||
// Create inserts the face to the database.
|
||||
func (m *PersonFace) Create() error {
|
||||
func (m *Face) Create() error {
|
||||
peopleMutex.Lock()
|
||||
defer peopleMutex.Unlock()
|
||||
|
||||
|
@ -61,17 +61,17 @@ func (m *PersonFace) Create() error {
|
|||
}
|
||||
|
||||
// Delete removes the face from the database.
|
||||
func (m *PersonFace) Delete() error {
|
||||
func (m *Face) Delete() error {
|
||||
return Db().Delete(m).Error
|
||||
}
|
||||
|
||||
// Deleted returns true if the face is deleted.
|
||||
func (m *PersonFace) Deleted() bool {
|
||||
func (m *Face) Deleted() bool {
|
||||
return m.DeletedAt != nil
|
||||
}
|
||||
|
||||
// Restore restores the face in the database.
|
||||
func (m *PersonFace) Restore() error {
|
||||
func (m *Face) Restore() error {
|
||||
if m.Deleted() {
|
||||
return UnscopedDb().Model(m).Update("DeletedAt", nil).Error
|
||||
}
|
||||
|
@ -80,11 +80,11 @@ func (m *PersonFace) Restore() error {
|
|||
}
|
||||
|
||||
// Update a face property in the database.
|
||||
func (m *PersonFace) Update(attr string, value interface{}) error {
|
||||
func (m *Face) Update(attr string, value interface{}) error {
|
||||
return UnscopedDb().Model(m).Update(attr, value).Error
|
||||
}
|
||||
|
||||
// Updates face properties in the database.
|
||||
func (m *PersonFace) Updates(values interface{}) error {
|
||||
func (m *Face) Updates(values interface{}) error {
|
||||
return UnscopedDb().Model(m).Updates(values).Error
|
||||
}
|
12
internal/entity/face_test.go
Normal file
12
internal/entity/face_test.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFace_TableName(t *testing.T) {
|
||||
m := &Face{}
|
||||
assert.Contains(t, m.TableName(), "faces")
|
||||
}
|
|
@ -45,7 +45,7 @@ var UnknownMarker = NewMarker(0, "", SrcAuto, MarkerUnknown, 0, 0, 0, 0)
|
|||
|
||||
// TableName returns the entity database table name.
|
||||
func (Marker) TableName() string {
|
||||
return "markers_dev"
|
||||
return "markers_dev2"
|
||||
}
|
||||
|
||||
// NewMarker creates a new entity.
|
||||
|
|
|
@ -7,8 +7,8 @@ import (
|
|||
)
|
||||
|
||||
func TestMarker_TableName(t *testing.T) {
|
||||
fileSync := &Marker{}
|
||||
assert.Equal(t, "markers_dev", fileSync.TableName())
|
||||
m := &Marker{}
|
||||
assert.Contains(t, m.TableName(), "markers")
|
||||
}
|
||||
|
||||
func TestNewMarker(t *testing.T) {
|
||||
|
|
|
@ -15,31 +15,6 @@ var peopleMutex = sync.Mutex{}
|
|||
|
||||
type People []Person
|
||||
|
||||
// Relationships.
|
||||
/*
|
||||
const (
|
||||
RelUnknown = ""
|
||||
RelBaby = "baby"
|
||||
RelWife = "wife"
|
||||
RelHusband = "husband"
|
||||
RelDad = "dad"
|
||||
RelMom = "mom"
|
||||
RelWorkmate = "workmate"
|
||||
RelBestFriend = "best-friend"
|
||||
RelFriend = "friend"
|
||||
RelClassmate = "classmate"
|
||||
RelBoyfriend = "boyfriend"
|
||||
RelGirlfriend = "girlfriend"
|
||||
RelFamily = "family"
|
||||
RelGrandfather = "grandfather"
|
||||
RelGrandmother = "grandmother"
|
||||
RelBrother = "brother"
|
||||
RelSister = "sister"
|
||||
RelRelative = "relative"
|
||||
RelOther = "other"
|
||||
)
|
||||
*/
|
||||
|
||||
// Person represents a person on one or more photos.
|
||||
type Person struct {
|
||||
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
|
||||
|
@ -80,7 +55,7 @@ func CreateUnknownPerson() {
|
|||
|
||||
// TableName returns the entity database table name.
|
||||
func (Person) TableName() string {
|
||||
return "people_dev"
|
||||
return "people_dev2"
|
||||
}
|
||||
|
||||
// BeforeCreate creates a random UID if needed before inserting a new row to the database.
|
||||
|
|
|
@ -7,6 +7,11 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPerson_TableName(t *testing.T) {
|
||||
m := &Person{}
|
||||
assert.Contains(t, m.TableName(), "people")
|
||||
}
|
||||
|
||||
func TestNewPerson(t *testing.T) {
|
||||
t.Run("Jens_Mander", func(t *testing.T) {
|
||||
m := NewPerson("Jens Mander", SrcAuto, 0)
|
||||
|
|
|
@ -82,7 +82,7 @@ func (w *Faces) Analyze() (err error) {
|
|||
log.Infof("faces: max Ø %f < median %f < %f", maxMin, maxMedian, maxMax)
|
||||
}
|
||||
|
||||
if known, err := query.PeopleFaces(); err != nil {
|
||||
if known, err := query.Faces(); err != nil {
|
||||
log.Errorf("faces: %s", err)
|
||||
} else if len(known) == 0 {
|
||||
log.Infof("faces: no faces found")
|
||||
|
@ -233,7 +233,7 @@ func (w *Faces) Start() (err error) {
|
|||
log.Errorf("faces: %s", err)
|
||||
}
|
||||
|
||||
peopleFaces, err := query.PeopleFaces()
|
||||
peopleFaces, err := query.Faces()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -298,7 +298,7 @@ func (w *Faces) Start() (err error) {
|
|||
log.Errorf("faces: failed adding %s", txt.Quote(marker.MarkerLabel))
|
||||
} else if f, ok := faceMap[faceId]; ok {
|
||||
faceMap[faceId] = Face{Embedding: f.Embedding, PersonUID: person.PersonUID}
|
||||
entity.Db().Model(&entity.PersonFace{}).Where("id = ?", faceId).Update("PersonUID", person.PersonUID)
|
||||
entity.Db().Model(&entity.Face{}).Where("id = ?", faceId).Update("PersonUID", person.PersonUID)
|
||||
}
|
||||
|
||||
// Existing person?
|
||||
|
|
|
@ -18,8 +18,8 @@ func People(limit, offset int, embeddings bool) (result entity.People, err error
|
|||
return result, err
|
||||
}
|
||||
|
||||
// PeopleFaces finds a list of faces.
|
||||
func PeopleFaces() (result entity.PeopleFaces, err error) {
|
||||
// Faces finds a list of faces.
|
||||
func Faces() (result entity.Faces, err error) {
|
||||
stmt := Db().
|
||||
Order("id")
|
||||
|
||||
|
@ -31,6 +31,6 @@ func PeopleFaces() (result entity.PeopleFaces, err error) {
|
|||
// PurgeUnknownFaces removes unknown faces from the index.
|
||||
func PurgeUnknownFaces() error {
|
||||
return UnscopedDb().Delete(
|
||||
entity.PersonFace{},
|
||||
entity.Face{},
|
||||
"person_uid = '' AND updated_at < ?", entity.Yesterday()).Error
|
||||
}
|
||||
|
|
36
internal/query/people_test.go
Normal file
36
internal/query/people_test.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPeople(t *testing.T) {
|
||||
results, err := People(3, 0, false)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.GreaterOrEqual(t, 1, len(results))
|
||||
|
||||
for _, val := range results {
|
||||
assert.IsType(t, entity.Person{}, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFaces(t *testing.T) {
|
||||
results, err := Faces()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.GreaterOrEqual(t, 1, len(results))
|
||||
|
||||
for _, val := range results {
|
||||
assert.IsType(t, entity.Face{}, val)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue