/** * * 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 db = { sequelize: new Sequelize(config.get("db.photos")), 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 }, 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', } }, 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();