diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/app/cache/FacesCacheService.java b/src/main/java/dev/mateuszkowalczyk/ffm/app/cache/FacesCacheService.java index 336292f..43f2e7e 100644 --- a/src/main/java/dev/mateuszkowalczyk/ffm/app/cache/FacesCacheService.java +++ b/src/main/java/dev/mateuszkowalczyk/ffm/app/cache/FacesCacheService.java @@ -24,6 +24,13 @@ public class FacesCacheService implements Runnable { } + public Mat readFaceToProcess(Face face) { + Mat image = Imgcodecs.imread(face.getPath()); + Imgproc.cvtColor(image, image, Imgproc.COLOR_RGB2GRAY); + + return image; + } + public Mat readFaceToProcess(String name) { Mat image = Imgcodecs.imread(this.cacheService.getPath() + DIRECTORY_NAME + "/" + name + ".JPG"); Imgproc.cvtColor(image, image, Imgproc.COLOR_RGB2GRAY); diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/Face.java b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/Face.java index fc459c5..c1a456b 100644 --- a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/Face.java +++ b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/Face.java @@ -24,7 +24,8 @@ public class Face { @Column(type = Column.Type.INT) private long photoId; - + @Column(type = Column.Type.INT) + private long personId; private Mat faceToProcess; public Face() { @@ -36,6 +37,15 @@ public class Face { this.name = resultSet.getString("name"); this.path = resultSet.getString("path"); this.photoId = resultSet.getInt("photoId"); + this.personId = resultSet.getInt("personId"); + } + + public long getPersonId() { + return personId; + } + + public void setPersonId(long personId) { + this.personId = personId; } public long getPhotoId() { @@ -73,7 +83,7 @@ public class Face { public Mat getFaceToProcess() { if (this.faceToProcess == null) { FacesCacheService facesCacheService = new FacesCacheService(); - this.faceToProcess = facesCacheService.readFaceToProcess(this.name); + this.faceToProcess = facesCacheService.readFaceToProcess(this); } return faceToProcess; diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/FaceDAO.java b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/FaceDAO.java index 68f9d67..77aa995 100644 --- a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/FaceDAO.java +++ b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/face/FaceDAO.java @@ -61,13 +61,14 @@ public class FaceDAO implements Dao { @Override public void add(Face face) { - String sql = "INSERT INTO face (name, path, photoId) values (?, ?, ?)"; + String sql = "INSERT INTO face (name, path, photoId, personId) values (?, ?, ?, ?)"; try { PreparedStatement preparedStatement = this.databaseService.getConnection().prepareStatement(sql); preparedStatement.setString(1, face.getName()); preparedStatement.setString(2, face.getPath()); preparedStatement.setLong(3, face.getPhotoId()); + preparedStatement.setLong(4, face.getPersonId()); preparedStatement.executeUpdate(); sql = "SELECT id FROM face ORDER BY id DESC LIMIT 1"; diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/person/Person.java b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/person/Person.java new file mode 100644 index 0000000..4e8ec0e --- /dev/null +++ b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/person/Person.java @@ -0,0 +1,42 @@ +package dev.mateuszkowalczyk.ffm.data.database.person; + +import dev.mateuszkowalczyk.ffm.data.database.annotation.Column; +import dev.mateuszkowalczyk.ffm.data.database.annotation.PrimaryKey; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.UUID; + +public class Person { + @PrimaryKey + @Column(type = Column.Type.INT) + private long id; + + @Column + private String name; + + public Person() { + this.name = UUID.randomUUID().toString(); + } + + public Person(ResultSet resultSet) throws SQLException { + this.id = resultSet.getLong("id"); + this.name = resultSet.getString("name"); + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/person/PersonDAO.java b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/person/PersonDAO.java new file mode 100644 index 0000000..ffb2398 --- /dev/null +++ b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/person/PersonDAO.java @@ -0,0 +1,90 @@ +package dev.mateuszkowalczyk.ffm.data.database.person; + +import dev.mateuszkowalczyk.ffm.data.DatabaseService; +import dev.mateuszkowalczyk.ffm.data.database.Dao; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class PersonDAO implements Dao { + private List personList = new ArrayList<>(); + private static PersonDAO instance; + private DatabaseService databaseService = DatabaseService.getInstance(); + + private PersonDAO () {} + + public static PersonDAO getInstance() { + if (instance == null) { + instance = new PersonDAO(); + } + + return instance; + } + + @Override + public Optional get(long id) { + return Optional.empty(); + } + + @Override + public List getAll() { + return this.getAll(false); + } + + @Override + public List getAll(boolean refresh) { + if (this.personList.size() == 0 || refresh) { + String sql = "SELECT * FROM person"; + try { + PreparedStatement preparedStatement = this.databaseService.getConnection().prepareStatement(sql); + ResultSet resultSet = preparedStatement.executeQuery(); + + while (resultSet.next()) { + Person person = new Person(resultSet); + this.personList.add(person); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + return this.personList; + } + + @Override + public void add(Person person) { + String sql = "INSERT INTO person (name) values(?)"; + + try { + PreparedStatement preparedStatement = databaseService.getConnection().prepareStatement(sql); + preparedStatement.setString(1, person.getName()); + preparedStatement.executeUpdate(); + + sql = "SELECT id FROM person ORDER BY id DESC LIMIT 1"; + + ResultSet resultSet = databaseService.getConnection().prepareStatement(sql).executeQuery(); + + while (resultSet.next()) { + person.setId(resultSet.getLong("id")); + this.personList.add(person); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void update(Person person) { + + } + + @Override + public void delete(Person person) { + + } +} diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/utils/DatabaseCreator.java b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/utils/DatabaseCreator.java index bda8acf..900e356 100644 --- a/src/main/java/dev/mateuszkowalczyk/ffm/data/database/utils/DatabaseCreator.java +++ b/src/main/java/dev/mateuszkowalczyk/ffm/data/database/utils/DatabaseCreator.java @@ -1,6 +1,7 @@ package dev.mateuszkowalczyk.ffm.data.database.utils; import dev.mateuszkowalczyk.ffm.data.database.face.Face; +import dev.mateuszkowalczyk.ffm.data.database.person.Person; import dev.mateuszkowalczyk.ffm.data.database.photo.Photo; import dev.mateuszkowalczyk.ffm.utils.ResourceLoader; @@ -34,5 +35,6 @@ public class DatabaseCreator { creator.create(Photo.class); creator.create(Face.class); + creator.create(Person.class); } } diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/image/FaceDetector.java b/src/main/java/dev/mateuszkowalczyk/ffm/image/FaceDetector.java index 251a578..312a3e4 100644 --- a/src/main/java/dev/mateuszkowalczyk/ffm/image/FaceDetector.java +++ b/src/main/java/dev/mateuszkowalczyk/ffm/image/FaceDetector.java @@ -22,6 +22,7 @@ import java.io.IOException; import static org.opencv.imgcodecs.Imgcodecs.imread; public class FaceDetector implements Runnable { + private FaceRecognition faceRecognition = new FaceRecognition(); private FaceDAO faceDAO = FaceDAO.getInstance(); private final Photo photo; @@ -58,6 +59,9 @@ public class FaceDetector implements Runnable { FacesCacheService facesCacheService = new FacesCacheService(croppedImage); facesCacheService.getPath(face); facesCacheService.createCachedFace(); + + this.faceRecognition.recognize(face); + this.faceDAO.add(face); }); diff --git a/src/main/java/dev/mateuszkowalczyk/ffm/image/FaceRecognition.java b/src/main/java/dev/mateuszkowalczyk/ffm/image/FaceRecognition.java new file mode 100644 index 0000000..8216fbe --- /dev/null +++ b/src/main/java/dev/mateuszkowalczyk/ffm/image/FaceRecognition.java @@ -0,0 +1,64 @@ +package dev.mateuszkowalczyk.ffm.image; + +import dev.mateuszkowalczyk.ffm.data.database.face.Face; +import dev.mateuszkowalczyk.ffm.data.database.face.FaceDAO; +import dev.mateuszkowalczyk.ffm.data.database.person.Person; +import dev.mateuszkowalczyk.ffm.data.database.person.PersonDAO; +import org.opencv.core.Mat; +import org.opencv.core.MatOfInt; +import org.opencv.face.LBPHFaceRecognizer; + +import java.util.ArrayList; +import java.util.List; + +public class FaceRecognition { + private PersonDAO personDAO = PersonDAO.getInstance(); + private FaceDAO faceDAO = FaceDAO.getInstance(); + + public void recognize(Face faceToRecognize) { + List faceList = faceDAO.getAll(); + List personList = personDAO.getAll(); + ArrayList facesImages = new ArrayList<>(); + ArrayList faceImagesIndex = new ArrayList<>(); + Person person; + + if (faceList.size() > 0) { + faceList.forEach(face -> { + var faceImage = face.getFaceToProcess(); + + facesImages.add(faceImage); + faceImagesIndex.add(faceList.indexOf(face)); + }); + + LBPHFaceRecognizer faceRecognizer = LBPHFaceRecognizer.create(); + MatOfInt matOfInt = new MatOfInt(); + matOfInt.fromList(faceImagesIndex); + faceRecognizer.train(facesImages, matOfInt); + + var result = faceRecognizer.predict_label(faceToRecognize.getFaceToProcess()); + + if (result == 0) { + person = createPerson(); + faceToRecognize.setPersonId(person.getId()); + } else { + faceToRecognize.setPersonId( + faceList.get(faceImagesIndex.indexOf(result)).getPersonId() + ); + } + + } else { + person = this.createPerson(); + + faceToRecognize.setPersonId(person.getId()); + } + + } + + private Person createPerson() { + Person person = new Person(); + this.personDAO.add(person); + + return person; + } + +}