281 lines
6.7 KiB
JavaScript
Executable File
281 lines
6.7 KiB
JavaScript
Executable File
/**
|
|
* * Copyright (c) 2016, Intel Corporation.
|
|
*
|
|
* This program is licensed under the terms and conditions of the
|
|
* Apache License, version 2.0. The full text of the Apache License is at
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
/**
|
|
* This class will instantiate the ORM, load in the models, call the method
|
|
* to create db connections, test the connection, then create the tables and
|
|
* relationships if not present
|
|
*/
|
|
const fs = require('fs'),
|
|
path = require('path'),
|
|
Sequelize = require('sequelize'),
|
|
config = require('config');
|
|
|
|
function init() {
|
|
const dbConfig = {...config.get("db.photos")};
|
|
let configPath = process.env.NODE_CONFIG_DIR;
|
|
if (configPath) {
|
|
configPath = configPath.replace(/config/, '');
|
|
} else {
|
|
configPath = './'
|
|
}
|
|
dbConfig.host = `${configPath}${dbConfig.host}`;
|
|
const db = {
|
|
sequelize: new Sequelize(dbConfig),
|
|
Sequelize: Sequelize
|
|
};
|
|
|
|
return db.sequelize.authenticate().then(function () {
|
|
const Album = db.sequelize.define('album', {
|
|
id: {
|
|
type: Sequelize.INTEGER,
|
|
primaryKey: true,
|
|
autoIncrement: true
|
|
},
|
|
path: Sequelize.STRING,
|
|
name: Sequelize.STRING,
|
|
parentId: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: true
|
|
}
|
|
}, {
|
|
timestamps: false,
|
|
classMethods: {
|
|
associate: function() {
|
|
Album.hasOne(Album, {as:'Album', foreignKey: 'parentId'});
|
|
}
|
|
}
|
|
});
|
|
|
|
const Photo = db.sequelize.define('photo', {
|
|
id: {
|
|
type: Sequelize.INTEGER,
|
|
primaryKey: true,
|
|
autoIncrement: true
|
|
},
|
|
name: Sequelize.STRING,
|
|
filename: Sequelize.STRING,
|
|
added: Sequelize.DATE,
|
|
modified: Sequelize.DATE,
|
|
updated: Sequelize.DATE,
|
|
scanned: Sequelize.DATE,
|
|
taken: Sequelize.DATE,
|
|
width: Sequelize.INTEGER,
|
|
height: Sequelize.INTEGER,
|
|
size: Sequelize.INTEGER,
|
|
faces: {
|
|
type: Sequelize.INTEGER,
|
|
defaultValue: -1 /* not scanned */
|
|
},
|
|
faceScannedWith: {
|
|
type: Sequelize.INTEGER,
|
|
defaultValue: 0
|
|
},
|
|
duplicate: {
|
|
type: Sequelize.BOOLEAN,
|
|
defaultValue: 0
|
|
},
|
|
deleted: {
|
|
type: Sequelize.BOOLEAN,
|
|
defaultValue: 0
|
|
},
|
|
albumId: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: true,
|
|
references: {
|
|
model: Album,
|
|
key: 'id',
|
|
}
|
|
}
|
|
}, {
|
|
timestamps: false
|
|
});
|
|
|
|
const Identity = db.sequelize.define('identity', {
|
|
id: {
|
|
type: Sequelize.INTEGER,
|
|
primaryKey: true,
|
|
autoIncrement: true
|
|
},
|
|
lastName: Sequelize.STRING,
|
|
firstName: Sequelize.STRING,
|
|
middleName: Sequelize.STRING,
|
|
displayName: {
|
|
type: Sequelize.STRING,
|
|
allowNull: false
|
|
},
|
|
faceId: {
|
|
type: Sequelize.INTEGER,
|
|
sallowNull: true,
|
|
references: {
|
|
model: Photo,
|
|
key: 'id',
|
|
}
|
|
},
|
|
facesCount: Sequelize.INTEGER,
|
|
descriptors: Sequelize.BLOB /* average of all faces mapped to this */
|
|
}, {
|
|
timestamps: false
|
|
});
|
|
|
|
const FaceDescriptor = db.sequelize.define('facedescriptor', {
|
|
id: {
|
|
type: Sequelize.INTEGER,
|
|
primaryKey: true,
|
|
autoIncrement: true
|
|
},
|
|
descriptors: Sequelize.BLOB
|
|
}, {
|
|
timestamps: false
|
|
});
|
|
|
|
const Face = db.sequelize.define('face', {
|
|
id: {
|
|
type: Sequelize.INTEGER,
|
|
primaryKey: true,
|
|
autoIncrement: true
|
|
},
|
|
photoId: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: false,
|
|
references: {
|
|
model: Photo,
|
|
key: 'id',
|
|
}
|
|
},
|
|
scanVersion: {
|
|
type: Sequelize.INTEGER,
|
|
/*
|
|
* 0 - original scan type
|
|
* 1 - Retinaface w/ 0.25% face margin
|
|
*/
|
|
defaultValue: 0
|
|
},
|
|
focus: { /* focal via laplacian variance https://pyimagesearch.com/2015/09/07/blur-detection-with-opencv/ */
|
|
type: Sequelize.DOUBLE,
|
|
defaultValue: 0
|
|
},
|
|
|
|
top: Sequelize.FLOAT, /* 0..1 * photoId.height */
|
|
left: Sequelize.FLOAT, /* 0..1 * photoId.width */
|
|
bottom: Sequelize.FLOAT, /* 0..1 * photoId.height */
|
|
right: Sequelize.FLOAT, /* 0..1 * photoId.width */
|
|
faceConfidence: { /* How confident that this is a face? */
|
|
type: Sequelize.DOUBLE,
|
|
defaultValue: 0
|
|
},
|
|
|
|
descriptorId: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: true,
|
|
references: {
|
|
model: FaceDescriptor,
|
|
key: 'id',
|
|
}
|
|
},
|
|
|
|
identityId: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: true,
|
|
references: {
|
|
model: Identity,
|
|
key: 'id',
|
|
}
|
|
},
|
|
distance: {
|
|
type: Sequelize.FLOAT,
|
|
defaultValue: -1
|
|
},
|
|
classifiedBy: {
|
|
type: Sequelize.DataTypes.ENUM(
|
|
'machine',
|
|
'human',
|
|
'not-a-face'), /* implies "human"; identityId=NULL */
|
|
defaultValue: 'machine',
|
|
},
|
|
lastComparedId: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: true,
|
|
}
|
|
}, {
|
|
timestamps: false,
|
|
classMethods: {
|
|
associate: function() {
|
|
Album.hasOne(Face, {as:'Face', foreignKey: 'lastComparedId'});
|
|
}
|
|
}
|
|
});
|
|
|
|
const FaceDistances = db.sequelize.define('facedistance', {
|
|
descriptor1Id: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: false,
|
|
references: {
|
|
model: FaceDescriptor,
|
|
key: 'id',
|
|
}
|
|
},
|
|
descriptor2Id: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: false,
|
|
references: {
|
|
model: FaceDescriptor,
|
|
key: 'id',
|
|
}
|
|
},
|
|
distanceCosine: {
|
|
type: Sequelize.DOUBLE,
|
|
defaultValue: 1.0
|
|
},
|
|
distanceEuclidian: {
|
|
type: Sequelize.DOUBLE,
|
|
defaultValue: 1.0
|
|
},
|
|
distanceEuclidianL2: {
|
|
type: Sequelize.DOUBLE,
|
|
defaultValue: 1.0
|
|
}
|
|
}, {
|
|
timestamps: false
|
|
});
|
|
|
|
const PhotoHash = db.sequelize.define('photohash', {
|
|
hash: {
|
|
type: Sequelize.STRING,
|
|
primaryKey: true,
|
|
unique: true
|
|
},
|
|
photoId: {
|
|
type: Sequelize.INTEGER,
|
|
allowNull: true,
|
|
references: {
|
|
model: Photo,
|
|
key: 'id',
|
|
}
|
|
}
|
|
}, {
|
|
timestamps: false
|
|
});
|
|
|
|
return db.sequelize.sync({
|
|
force: false
|
|
}).then(function () {
|
|
return db;
|
|
});
|
|
}).catch(function (error) {
|
|
console.log("ERROR: Failed to authenticate with PHOTOS DB");
|
|
console.log("ERROR: " + JSON.stringify(config.get("db"), null, 2));
|
|
console.log(error);
|
|
throw error;
|
|
});
|
|
}
|
|
|
|
module.exports = init();
|