886 lines
36 KiB
Java
886 lines
36 KiB
Java
package it.acxent.face;
|
|
|
|
import it.acxent.db.ApplParmFull;
|
|
import it.acxent.db.DBAdapter;
|
|
import it.acxent.db.ResParm;
|
|
import it.acxent.db.WcString;
|
|
import it.acxent.face.api.vision.GoogleVisionApi;
|
|
import it.acxent.face.api.vision.GoogleVisionResult;
|
|
import it.acxent.util.DoubleOperator;
|
|
import it.acxent.util.StringTokenizer;
|
|
import it.acxent.util.Vectumerator;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
import java.io.Serializable;
|
|
import java.math.RoundingMode;
|
|
import java.sql.PreparedStatement;
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import javax.imageio.ImageIO;
|
|
import org.apache.commons.math3.geometry.Vector;
|
|
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
|
|
import org.json.JSONArray;
|
|
import org.json.JSONObject;
|
|
|
|
public class FotoFaceVision extends DBAdapter implements Serializable {
|
|
private static final long serialVersionUID = 1683972032841L;
|
|
|
|
private Face face;
|
|
|
|
private long id_fotoFace;
|
|
|
|
private long id_foto;
|
|
|
|
private String jsonData;
|
|
|
|
private Foto foto;
|
|
|
|
private long faceTopVx;
|
|
|
|
private long faceTopVy;
|
|
|
|
private long faceBottomVx;
|
|
|
|
private long faceBottomVy;
|
|
|
|
private String featureVector1;
|
|
|
|
private String featureVector2;
|
|
|
|
private String fileName;
|
|
|
|
private String label;
|
|
|
|
private String labelDb;
|
|
|
|
public FotoFaceVision(ApplParmFull newApplParmFull) {
|
|
super(newApplParmFull);
|
|
}
|
|
|
|
public FotoFaceVision() {}
|
|
|
|
public void setId_fotoFace(long newId_fotoFace) {
|
|
this.id_fotoFace = newId_fotoFace;
|
|
}
|
|
|
|
public void setId_foto(long newId_foto) {
|
|
this.id_foto = newId_foto;
|
|
setFoto(null);
|
|
}
|
|
|
|
public void setJsonData(String newJsonData) {
|
|
this.jsonData = newJsonData;
|
|
}
|
|
|
|
public final ResParm loadSelfieByGoogleVision(String fileName) {
|
|
ResParm rp = new ResParm();
|
|
try {
|
|
String GVA_KEY = getParm("GOOGLE_API_KEY_VISION").getTesto();
|
|
GoogleVisionApi gva = new GoogleVisionApi(GVA_KEY);
|
|
GoogleVisionResult resF = gva.annotateFaces(fileName);
|
|
if (resF.isOk()) {
|
|
rp = loadSelfieByJson((JSONObject)resF.getResult());
|
|
} else {
|
|
rp.setStatus(false);
|
|
rp.setMsg(resF.getMsg());
|
|
}
|
|
} catch (Exception e) {
|
|
rp.setException(e);
|
|
rp.setStatus(false);
|
|
}
|
|
return rp;
|
|
}
|
|
|
|
public final ResParm loadSelfieByJson(JSONObject jo) {
|
|
ResParm rp = new ResParm();
|
|
StringBuilder msg = new StringBuilder();
|
|
JSONArray jaResponses = jo.getJSONArray("responses");
|
|
boolean visiTrovati = false;
|
|
for (int i = 0; i < jaResponses.length(); i++) {
|
|
JSONObject joResponse = jaResponses.getJSONObject(i);
|
|
if (joResponse.has("faceAnnotations")) {
|
|
visiTrovati = true;
|
|
JSONArray jaFaceAnnotations = joResponse.getJSONArray("faceAnnotations");
|
|
if (jaFaceAnnotations.length() > 1) {
|
|
rp.setStatus(false);
|
|
rp.setMsg("Trovati duo o piu visi..");
|
|
} else {
|
|
JSONObject joFaceAnnotation = jaFaceAnnotations.getJSONObject(0);
|
|
JSONObject joFace = new JSONObject();
|
|
JSONObject joFdBoundingPoly = joFaceAnnotation.getJSONObject("fdBoundingPoly");
|
|
joFace.put("fdBoundingPoly", joFdBoundingPoly);
|
|
JSONArray jaLandmarks = joFaceAnnotation.getJSONArray("landmarks");
|
|
joFace.put("landmarks", jaLandmarks);
|
|
setJsonData(joFace.toString());
|
|
rp = _loadFotoFaceFromFaceJson(false);
|
|
if (!rp.getStatus())
|
|
msg.append("Errore: impossibile caricare fotoface da json per il selfie: " + rp.getMsg());
|
|
}
|
|
}
|
|
}
|
|
if (!visiTrovati) {
|
|
rp.setStatus(false);
|
|
rp.setMsg("Nessun viso trovato!!");
|
|
}
|
|
return rp;
|
|
}
|
|
|
|
public long getId_fotoFace() {
|
|
return this.id_fotoFace;
|
|
}
|
|
|
|
public long getId_foto() {
|
|
return this.id_foto;
|
|
}
|
|
|
|
public String getJsonData() {
|
|
return (this.jsonData == null) ? "" : this.jsonData.trim();
|
|
}
|
|
|
|
public void setFoto(Foto newFoto) {
|
|
this.foto = newFoto;
|
|
}
|
|
|
|
public Foto getFoto() {
|
|
this.foto = (Foto)getSecondaryObject(this.foto, Foto.class, getId_foto());
|
|
return this.foto;
|
|
}
|
|
|
|
protected ResParm checkDeleteCascade() {
|
|
return new ResParm(true);
|
|
}
|
|
|
|
protected void deleteCascade() {}
|
|
|
|
public Vectumerator<FotoFaceVision> findByCR(FotoFaceCR CR, int pageNumber, int pageRows) {
|
|
String s_Sql_Find = "select A.* from FOTO_FACE AS A";
|
|
String s_Sql_Order = "";
|
|
WcString wc = new WcString();
|
|
if (!CR.getSearchTxt().trim().isEmpty()) {
|
|
StringTokenizer st = new StringTokenizer(CR.getSearchTxt().trim(), " ");
|
|
StringBuffer txt = new StringBuffer("(");
|
|
while (st.hasMoreTokens()) {
|
|
String token = st.nextToken();
|
|
txt.append("(A.Cognome like '%" + token + "%' or A.Nome like '%" + token + "%')");
|
|
if (st.hasMoreTokens())
|
|
txt.append(" and ");
|
|
}
|
|
txt.append(")");
|
|
wc.addWc(txt.toString());
|
|
}
|
|
try {
|
|
PreparedStatement stmt = getConn().prepareStatement(s_Sql_Find + s_Sql_Find + wc.toString());
|
|
return findRows(stmt, pageNumber, pageRows);
|
|
} catch (SQLException e) {
|
|
removeCPConnection();
|
|
handleDebug(e);
|
|
return AB_EMPTY_VECTUMERATOR;
|
|
}
|
|
}
|
|
|
|
private ResParm _loadFotoFaceFromFaceJson(boolean salva) {
|
|
ResParm rp = new ResParm();
|
|
if (getJsonData().isEmpty()) {
|
|
rp.setStatus(false);
|
|
rp.setMsg("Json data vuoto... non sono state trovate facce");
|
|
} else {
|
|
this.face = new Face();
|
|
JSONObject joFace = new JSONObject(getJsonData());
|
|
JSONObject joFdBoundingPoly = joFace.getJSONObject("fdBoundingPoly");
|
|
JSONArray jaVertices = joFdBoundingPoly.getJSONArray("vertices");
|
|
JSONObject joTopLeft = jaVertices.getJSONObject(0);
|
|
JSONObject joTopRigth = jaVertices.getJSONObject(1);
|
|
JSONObject joBottomRigth = jaVertices.getJSONObject(2);
|
|
JSONObject joBottomLeft = jaVertices.getJSONObject(3);
|
|
try {
|
|
this.face.setB_TOP_LEFT(new Point(joTopLeft.getLong("x"),
|
|
joTopLeft.getLong("y")));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
try {
|
|
this.face.setB_TOP_RIGHT(new Point(joTopRigth.getLong("x"),
|
|
joTopRigth.getLong("y")));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
try {
|
|
this.face.setB_BOTTOM_RIGHT(new Point(joBottomRigth.getLong("x"),
|
|
joBottomRigth.getLong("y")));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
try {
|
|
this.face.setB_BOTTOM_LEFT(new Point(joBottomLeft.getLong("x"),
|
|
joBottomLeft.getLong("y")));
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
JSONArray jaLandmarks = joFace.getJSONArray("landmarks");
|
|
for (int k = 0; k < jaLandmarks.length(); k++) {
|
|
JSONObject joLandmark = jaLandmarks.getJSONObject(k);
|
|
_fillFaceLandmark(this.face, joLandmark);
|
|
}
|
|
if (salva) {
|
|
rp = save();
|
|
} else {
|
|
rp.setStatus(true);
|
|
rp.setMsg("Fotoface creato ma non salvato");
|
|
}
|
|
}
|
|
return rp;
|
|
}
|
|
|
|
public ResParm deleteFotoFaceByFoto(long l_id_foto) {
|
|
if (getApFull() == null || l_id_foto == 0L)
|
|
return new ResParm(false, "Errore!! Dati connessione db assenti");
|
|
return delete("delete from FOTO_FACE WHERE id_foto=" + l_id_foto);
|
|
}
|
|
|
|
public void findFirstByFoto(long l_id_foto) {
|
|
String s_Sql_Find = "select A.* from FOTO_FACE AS A";
|
|
String s_Sql_Order = "";
|
|
WcString wc = new WcString();
|
|
wc.addWc("A.id_foto=" + l_id_foto);
|
|
try {
|
|
PreparedStatement stmt = getConn().prepareStatement(s_Sql_Find + s_Sql_Find + wc.toString());
|
|
findFirstRecord(stmt);
|
|
} catch (SQLException e) {
|
|
removeCPConnection();
|
|
handleDebug(e);
|
|
}
|
|
}
|
|
|
|
private static final void _fillFaceLandmark(Face face, JSONObject joLandmark) {
|
|
String type = joLandmark.getString("type");
|
|
JSONObject joPosition = joLandmark.getJSONObject("position");
|
|
Point currentPoint = new Point(joPosition.getLong("x"),
|
|
joPosition.getLong("y"), joPosition.getLong("z"));
|
|
if (type.equals("LEFT_EYE")) {
|
|
face.setEL_C(currentPoint);
|
|
} else if (type.equals("RIGHT_EYE")) {
|
|
face.setER_C(currentPoint);
|
|
} else if (type.equals("LEFT_OF_LEFT_EYEBROW")) {
|
|
face.setEBL_L(currentPoint);
|
|
} else if (type.equals("RIGHT_OF_LEFT_EYEBROW")) {
|
|
face.setEBL_R(currentPoint);
|
|
} else if (type.equals("LEFT_OF_RIGHT_EYEBROW")) {
|
|
face.setEBR_L(currentPoint);
|
|
} else if (type.equals("RIGHT_OF_RIGHT_EYEBROW")) {
|
|
face.setEBR_R(currentPoint);
|
|
} else if (type.equals("MIDPOINT_BETWEEN_EYES")) {
|
|
face.setE_C(currentPoint);
|
|
} else if (type.equals("NOSE_TIP")) {
|
|
face.setN_T(currentPoint);
|
|
} else if (type.equals("UPPER_LIP")) {
|
|
face.setL_T(currentPoint);
|
|
} else if (type.equals("LOWER_LIP")) {
|
|
face.setL_B(currentPoint);
|
|
} else if (type.equals("MOUTH_LEFT")) {
|
|
face.setM_L(currentPoint);
|
|
} else if (type.equals("MOUTH_RIGHT")) {
|
|
face.setM_R(currentPoint);
|
|
} else if (type.equals("MOUTH_CENTER")) {
|
|
face.setM_C(currentPoint);
|
|
} else if (type.equals("NOSE_BOTTOM_RIGHT")) {
|
|
face.setN_RB(currentPoint);
|
|
} else if (type.equals("NOSE_BOTTOM_LEFT")) {
|
|
face.setN_LB(currentPoint);
|
|
} else if (type.equals("NOSE_BOTTOM_CENTER")) {
|
|
face.setN_CB(currentPoint);
|
|
} else if (type.equals("LEFT_EYE_TOP_BOUNDARY")) {
|
|
face.setEL_T(currentPoint);
|
|
} else if (type.equals("LEFT_EYE_RIGHT_CORNER")) {
|
|
face.setEL_R(currentPoint);
|
|
} else if (type.equals("LEFT_EYE_BOTTOM_BOUNDARY")) {
|
|
face.setEL_B(currentPoint);
|
|
} else if (type.equals("LEFT_EYE_LEFT_CORNER")) {
|
|
face.setEL_L(currentPoint);
|
|
} else if (type.equals("RIGHT_EYE_TOP_BOUNDARY")) {
|
|
face.setER_T(currentPoint);
|
|
} else if (type.equals("RIGHT_EYE_RIGHT_CORNER")) {
|
|
face.setER_R(currentPoint);
|
|
} else if (type.equals("RIGHT_EYE_BOTTOM_BOUNDARY")) {
|
|
face.setER_B(currentPoint);
|
|
} else if (type.equals("RIGHT_EYE_LEFT_CORNER")) {
|
|
face.setER_L(currentPoint);
|
|
} else if (type.equals("LEFT_EYEBROW_UPPER_MIDPOINT")) {
|
|
face.setEBL_M(currentPoint);
|
|
} else if (type.equals("RIGHT_EYEBROW_UPPER_MIDPOINT")) {
|
|
face.setEBR_M(currentPoint);
|
|
} else if (type.equals("LEFT_EAR_TRAGION")) {
|
|
face.setEA_L(currentPoint);
|
|
} else if (type.equals("RIGHT_EAR_TRAGION")) {
|
|
face.setEA_R(currentPoint);
|
|
} else if (type.equals("FOREHEAD_GLABELLA")) {
|
|
face.setFORH(currentPoint);
|
|
} else if (type.equals("CHIN_GNATHION")) {
|
|
face.setCH(currentPoint);
|
|
} else if (type.equals("CHIN_LEFT_GONION")) {
|
|
face.setCH_L(currentPoint);
|
|
} else if (type.equals("CHIN_RIGHT_GONION")) {
|
|
face.setCH_R(currentPoint);
|
|
} else if (type.equals("LEFT_CHEEK_CENTER")) {
|
|
face.setCK_L(currentPoint);
|
|
} else if (type.equals("RIGHT_CHEEK_CENTER")) {
|
|
face.setCK_R(currentPoint);
|
|
} else {
|
|
System.out.println("ERRORE!!! Face.fillFaceLandmark tipo non trovato: " + type);
|
|
}
|
|
}
|
|
|
|
public double getCalcFaceIdx1() {
|
|
DoubleOperator dop = new DoubleOperator();
|
|
dop.setScale(2, RoundingMode.UNNECESSARY);
|
|
dop.add(Point.getDistanceNormF(getFace().getEA_L(), getFace().getM_C(), getFace().getScaleFactor()));
|
|
dop.add(Point.getDistanceNormF(getFace().getEA_R(), getFace().getM_C(), getFace().getScaleFactor()));
|
|
return dop.getResult();
|
|
}
|
|
|
|
public double getCalcFaceIdx2() {
|
|
DoubleOperator dop = new DoubleOperator();
|
|
dop.setScale(2, RoundingMode.UNNECESSARY);
|
|
dop.add(Point.getDistanceNormF(getFace().getEA_R(), getFace().getN_T(), getFace().getScaleFactor()));
|
|
dop.add(Point.getDistanceNormF(getFace().getEA_L(), getFace().getN_T(), getFace().getScaleFactor()));
|
|
dop.add(Point.getDistanceNormF(getFace().getM_C(), getFace().getN_T(), getFace().getScaleFactor()));
|
|
return dop.getResult();
|
|
}
|
|
|
|
public double getCalcFaceIdx3() {
|
|
DoubleOperator dop = new DoubleOperator();
|
|
dop.setScale(2, RoundingMode.UNNECESSARY);
|
|
dop.add(Point.getDistanceNormF(getFace().getCK_L(), getFace().getCK_R(), getFace().getScaleFactor()));
|
|
return dop.getResult();
|
|
}
|
|
|
|
public double getCalcFaceIdx4() {
|
|
DoubleOperator dop = new DoubleOperator();
|
|
dop.setScale(2, RoundingMode.UNNECESSARY);
|
|
dop.add(Point.getDistanceNormF(getFace().getEA_R(), getFace().getN_T(), getFace().getScaleFactor()));
|
|
dop.add(Point.getDistanceNormF(getFace().getEA_L(), getFace().getN_T(), getFace().getScaleFactor()));
|
|
dop.add(Point.getDistanceNormF(getFace().getM_C(), getFace().getN_T(), getFace().getScaleFactor()));
|
|
return dop.getResult();
|
|
}
|
|
|
|
public double[] getFaceIdRange(double faceId, double percRange) {
|
|
DoubleOperator scarto = new DoubleOperator(100.0F);
|
|
scarto.setScale(2, RoundingMode.UNNECESSARY);
|
|
scarto.subtract(percRange);
|
|
scarto.multiply(faceId);
|
|
scarto.divide(100.0F);
|
|
DoubleOperator min = new DoubleOperator(faceId);
|
|
min.subtract(scarto);
|
|
DoubleOperator max = new DoubleOperator(faceId);
|
|
max.add(scarto);
|
|
double[] result = { min.getResult(), max.getResult() };
|
|
return result;
|
|
}
|
|
|
|
public ResParm save() {
|
|
String l_labelDb = getLabelDb();
|
|
if (!getJsonData().isEmpty()) {
|
|
_createFeatureVectorAll();
|
|
} else {
|
|
println("FotoFace: save: " + getFoto().getFileName() + " NO json data on foto face " + getId_fotoFace());
|
|
}
|
|
createFaceImage(false);
|
|
ResParm rp = super.save();
|
|
if (rp.getStatus())
|
|
if (!getLabel().equals(l_labelDb))
|
|
rp.append(getFoto().updatePettoraliByFotoFace(true));
|
|
return rp;
|
|
}
|
|
|
|
public Face getFace() {
|
|
if (this.face == null && !getJsonData().isEmpty())
|
|
_loadFotoFaceFromFaceJson(false);
|
|
return this.face;
|
|
}
|
|
|
|
public void setFace(Face face) {
|
|
this.face = face;
|
|
}
|
|
|
|
public ResParm _createFeatureVectorAll() {
|
|
ResParm rp = new ResParm();
|
|
List<Double> featureVector = new ArrayList<>();
|
|
Double faceHeight = Point.getDistance(getFace().getFORH(), getFace().getM_C());
|
|
Double faceWidth = Point.getDistance(getFace().getEA_L(), getFace().getEA_R());
|
|
Double eyeDistance = Point.getDistance(getFace().getEL_C(), getFace().getER_C());
|
|
Double mouthLen = Point.getDistance(getFace().getM_L(), getFace().getM_R());
|
|
Double nooseLen = Point.getDistance(getFace().getE_C(), getFace().getN_CB());
|
|
List<Point> points = new ArrayList<>();
|
|
points.add(getFace().getEL_C());
|
|
points.add(getFace().getER_C());
|
|
points.add(getFace().getEA_L());
|
|
points.add(getFace().getEA_R());
|
|
points.add(getFace().getEBL_M());
|
|
points.add(getFace().getEBR_M());
|
|
points.add(getFace().getCK_L());
|
|
points.add(getFace().getCK_R());
|
|
points.add(getFace().getM_C());
|
|
points.add(getFace().getN_T());
|
|
points.add(getFace().getE_C());
|
|
points.add(getFace().getFORH());
|
|
List<Double> distances = new ArrayList<>();
|
|
for (int i = 0; i < points.size() - 1; i++) {
|
|
Point p1 = points.get(i);
|
|
for (int j = i + 1; j < points.size(); j++) {
|
|
Point p2 = points.get(j);
|
|
double distance = Point.getDistance(p1, p2);
|
|
distances.add(Double.valueOf(distance));
|
|
}
|
|
}
|
|
double averageDistance = calculateAverageDistance(distances);
|
|
featureVector.add(Double.valueOf(averageDistance));
|
|
Double eyeMouthDistance = Point.getDistance(getFace().getE_C(), getFace().getM_C());
|
|
featureVector.add(Double.valueOf(eyeMouthDistance / eyeDistance));
|
|
Double eyeNoseDistance = Point.getDistance(getFace().getE_C(), getFace().getN_T());
|
|
featureVector.add(Double.valueOf(eyeDistance / eyeNoseDistance));
|
|
Double eyeChinDistance = Point.getDistance(getFace().getE_C(), getFace().getCH());
|
|
Double eyeLipCHinDistance = Point.getDistance(getFace().getL_B(), getFace().getCH());
|
|
featureVector.add(Double.valueOf(eyeDistance / eyeLipCHinDistance));
|
|
Double eyeLipNooseDistance = Point.getDistance(getFace().getL_T(), getFace().getN_T());
|
|
featureVector.add(Double.valueOf(eyeDistance / eyeLipNooseDistance));
|
|
Double eyeEyebrowDistance = Point.getDistance(getFace().getEBL_M(), getFace().getEBR_M());
|
|
featureVector.add(Double.valueOf(eyeDistance / eyeEyebrowDistance));
|
|
Point midCheekPoint = new Point((getFace().getCK_L().getX() + getFace().getCK_R().getX()) / 2L, (
|
|
getFace().getCK_L().getY() + getFace().getCK_R().getY()) / 2L, (
|
|
getFace().getCK_L().getZ() + getFace().getCK_R().getZ()) / 2L);
|
|
Double eyeCheekDistance = Point.getDistance(getFace().getE_C(), midCheekPoint);
|
|
featureVector.add(Double.valueOf(eyeDistance / eyeCheekDistance));
|
|
featureVector.add(eyeDistance);
|
|
featureVector.add(eyeEyebrowDistance);
|
|
Double cheekDistance = Point.getDistance(getFace().getCK_L(), getFace().getCK_R());
|
|
featureVector.add(cheekDistance);
|
|
Double mouthCornerDistance = Point.getDistance(getFace().getM_L(), getFace().getM_R());
|
|
featureVector.add(mouthCornerDistance);
|
|
Double chinDistance = Point.getDistance(getFace().getCH_L(), getFace().getCH_R());
|
|
featureVector.add(chinDistance);
|
|
featureVector.add(faceWidth);
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEL_C(), getFace().getE_C(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEL_C(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEBL_M(), getFace().getEL_C(), getFace().getN_T())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEBR_M(), getFace().getER_C(), getFace().getN_T())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEL_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEBL_L(), getFace().getEBL_M(), getFace().getEBL_R())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEBR_L(), getFace().getEBR_M(), getFace().getEBR_R())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEA_R(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEA_L(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(eyeDistance / faceWidth));
|
|
Double noseLen = Point.getDistance(getFace().getE_C(), getFace().getN_CB());
|
|
featureVector.add(Double.valueOf(noseLen / faceHeight));
|
|
featureVector.add(Double.valueOf(mouthLen / faceWidth));
|
|
featureVector.add(Double.valueOf(eyeEyebrowDistance / faceWidth));
|
|
featureVector.add(Double.valueOf(cheekDistance / faceWidth));
|
|
normalizeFeatureVector(featureVector);
|
|
StringBuilder sb = new StringBuilder();
|
|
for (Iterator<Double> iterator = featureVector.iterator(); iterator.hasNext(); ) {
|
|
double element = iterator.next();
|
|
sb.append(element);
|
|
sb.append(",");
|
|
}
|
|
setFeatureVector1(sb.toString().substring(1, sb.toString().length() - 1));
|
|
return rp;
|
|
}
|
|
|
|
public ResParm _createFeatureVectorTop() {
|
|
ResParm rp = new ResParm();
|
|
if (getFace() == null) {
|
|
rp.setStatus(false);
|
|
rp.setMsg(getFoto().getFileName() + ": No json data...");
|
|
return rp;
|
|
}
|
|
List<Double> featureVector = new ArrayList<>();
|
|
List<Point> points = new ArrayList<>();
|
|
points.add(getFace().getEL_C());
|
|
points.add(getFace().getER_C());
|
|
points.add(getFace().getEA_L());
|
|
points.add(getFace().getEA_R());
|
|
points.add(getFace().getCK_L());
|
|
points.add(getFace().getCK_R());
|
|
points.add(getFace().getM_C());
|
|
points.add(getFace().getN_T());
|
|
List<Double> distances = new ArrayList<>();
|
|
for (int i = 0; i < points.size() - 1; i++) {
|
|
Point p1 = points.get(i);
|
|
for (int j = i + 1; j < points.size(); j++) {
|
|
Point p2 = points.get(j);
|
|
double distance = Point.getDistance(p1, p2);
|
|
distances.add(Double.valueOf(distance));
|
|
}
|
|
}
|
|
double averageDistance = calculateAverageDistance(distances);
|
|
featureVector.add(Double.valueOf(averageDistance));
|
|
Double eyeDistance = Point.getDistance(getFace().getEL_C(), getFace().getER_C());
|
|
featureVector.add(eyeDistance);
|
|
Double eyeMouthDistance = Point.getDistance(getFace().getE_C(), getFace().getM_C());
|
|
featureVector.add(Double.valueOf(eyeMouthDistance / eyeDistance));
|
|
Double eyeNoseDistance = Point.getDistance(getFace().getE_C(), getFace().getN_T());
|
|
featureVector.add(Double.valueOf(eyeDistance / eyeNoseDistance));
|
|
Double eyeChinDistance = Point.getDistance(getFace().getE_C(), getFace().getCH());
|
|
Double eyeEyebrowDistance = Point.getDistance(getFace().getEBL_M(), getFace().getEBR_M());
|
|
Point midCheekPoint = new Point((getFace().getCK_L().getX() + getFace().getCK_R().getX()) / 2L, (
|
|
getFace().getCK_L().getY() + getFace().getCK_R().getY()) / 2L, (
|
|
getFace().getCK_L().getZ() + getFace().getCK_R().getZ()) / 2L);
|
|
Double eyeCheekDistance = Point.getDistance(getFace().getE_C(), midCheekPoint);
|
|
Double cheekDistance = Point.getDistance(getFace().getCK_L(), getFace().getCK_R());
|
|
featureVector.add(cheekDistance);
|
|
Double mouthCornerDistance = Point.getDistance(getFace().getM_L(), getFace().getM_R());
|
|
Double chinDistance = Point.getDistance(getFace().getCH_L(), getFace().getCH_R());
|
|
featureVector.add(chinDistance);
|
|
Double faceWidth = Point.getDistance(getFace().getEA_L(), getFace().getEA_R());
|
|
featureVector.add(faceWidth);
|
|
Double faceHeight = Point.getDistance(getFace().getFORH(), getFace().getM_C());
|
|
featureVector.add(faceHeight);
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEL_C(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEL_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEA_R(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEA_L(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(eyeDistance / faceWidth));
|
|
Double noseLen = Point.getDistance(getFace().getE_C(), getFace().getN_CB());
|
|
featureVector.add(Double.valueOf(noseLen / faceHeight));
|
|
Double mouthLen = Point.getDistance(getFace().getM_L(), getFace().getM_R());
|
|
featureVector.add(Double.valueOf(cheekDistance / faceWidth));
|
|
featureVector.add(Double.valueOf(faceHeight / faceWidth));
|
|
normalizeFeatureVector(featureVector);
|
|
StringBuilder sb = new StringBuilder();
|
|
for (Iterator<Double> iterator = featureVector.iterator(); iterator.hasNext(); ) {
|
|
double element = iterator.next();
|
|
sb.append(element);
|
|
sb.append(",");
|
|
}
|
|
setFeatureVector1(sb.toString().substring(1, sb.toString().length() - 1));
|
|
return rp;
|
|
}
|
|
|
|
public static double calculateAngleDeg(Point p1, Point p2, Point p3) {
|
|
Vector3D v1 = new Vector3D((double)p1.getX(), (double)p1.getY(), (double)p1.getZ());
|
|
Vector3D v2 = new Vector3D((double)p2.getX(), (double)p2.getY(), (double)p2.getZ());
|
|
Vector3D v3 = new Vector3D((double)p3.getX(), (double)p3.getY(), (double)p3.getZ());
|
|
Vector3D v12 = v2.subtract((Vector)v1);
|
|
Vector3D v23 = v2.subtract((Vector)v3);
|
|
double angRad = Vector3D.angle(v12, v23);
|
|
return Math.toDegrees(angRad);
|
|
}
|
|
|
|
public static double calculateAverageDistance(List<Double> distances) {
|
|
double sum = 0.0D;
|
|
for (Iterator<Double> iterator = distances.iterator(); iterator.hasNext(); ) {
|
|
double distance = iterator.next();
|
|
sum += distance;
|
|
}
|
|
return sum / (double)distances.size();
|
|
}
|
|
|
|
public static void normalizeFeatureVector(List<Double> featureVector) {
|
|
double norm = calculateEuclideanNorm(featureVector);
|
|
for (int i = 0; i < featureVector.size(); i++)
|
|
featureVector.set(i, Double.valueOf(featureVector.get(i) / norm));
|
|
}
|
|
|
|
private static double calculateEuclideanNorm(List<Double> vector) {
|
|
double sumOfSquares = 0.0D;
|
|
for (Iterator<Double> iterator = vector.iterator(); iterator.hasNext(); ) {
|
|
double value = iterator.next();
|
|
sumOfSquares += value * value;
|
|
}
|
|
return Math.sqrt(sumOfSquares);
|
|
}
|
|
|
|
public static double calculateDotProduct(List<Double> featureVector1, List<Double> featureVector2) {
|
|
if (featureVector1.size() != featureVector2.size())
|
|
return -1.0D;
|
|
double dotProduct = 0.0D;
|
|
for (int i = 0; i < featureVector1.size(); i++)
|
|
dotProduct += featureVector1.get(i) * featureVector2.get(i);
|
|
return dotProduct;
|
|
}
|
|
|
|
public static double calculateEuclideanDistance(List<Double> featureVector1, List<Double> featureVector2) {
|
|
if (featureVector1.size() != featureVector2.size()) {
|
|
System.out.println("calculateEuclideanDistance: " + featureVector1.size() + " " + featureVector2.size());
|
|
return 99999.0D;
|
|
}
|
|
double sumOfSquares = 0.0D;
|
|
for (int i = 0; i < featureVector1.size(); i++) {
|
|
double diff = featureVector1.get(i) - featureVector2.get(i);
|
|
sumOfSquares += diff * diff;
|
|
}
|
|
return Math.sqrt(sumOfSquares);
|
|
}
|
|
|
|
public long getFaceTopVx() {
|
|
if (this.faceTopVx == 0L && getFace() != null)
|
|
this.faceTopVx = getFace().getB_TOP_RIGHT().getX();
|
|
return this.faceTopVx;
|
|
}
|
|
|
|
public void setFaceTopVx(long faceTopVx) {
|
|
this.faceTopVx = faceTopVx;
|
|
}
|
|
|
|
public long getFaceTopVy() {
|
|
if (this.faceTopVy == 0L && getFace() != null)
|
|
this.faceTopVy = getFace().getB_TOP_RIGHT().getY();
|
|
return this.faceTopVy;
|
|
}
|
|
|
|
public void setFaceTopVy(long faceTopVy) {
|
|
this.faceTopVy = faceTopVy;
|
|
}
|
|
|
|
public long getFaceBottomVx() {
|
|
if (this.faceBottomVx == 0L && getFace() != null)
|
|
this.faceBottomVx = getFace().getB_BOTTOM_LEFT().getX();
|
|
return this.faceBottomVx;
|
|
}
|
|
|
|
public void setFaceBottomVx(long faceBottomVx) {
|
|
this.faceBottomVx = faceBottomVx;
|
|
}
|
|
|
|
public long getFaceBottomVy() {
|
|
if (this.faceBottomVy == 0L && getFace() != null)
|
|
this.faceBottomVy = getFace().getB_BOTTOM_LEFT().getY();
|
|
return this.faceBottomVy;
|
|
}
|
|
|
|
public void setFaceBottomVy(long faceBottomVy) {
|
|
this.faceBottomVy = faceBottomVy;
|
|
}
|
|
|
|
public String getFeatureVector1() {
|
|
return (this.featureVector1 == null) ? "" : this.featureVector1.trim();
|
|
}
|
|
|
|
public void setFeatureVector1(String featureVector1) {
|
|
this.featureVector1 = featureVector1;
|
|
}
|
|
|
|
public String getFeatureVector2() {
|
|
return (this.featureVector2 == null) ? "" : this.featureVector2.trim();
|
|
}
|
|
|
|
public void setFeatureVector2(String featureVector2) {
|
|
this.featureVector2 = featureVector2;
|
|
}
|
|
|
|
public Vectumerator<FotoFaceVision> findByFoto(long l_id_foto) {
|
|
String s_Sql_Find = "select A.* from FOTO_FACE AS A";
|
|
String s_Sql_Order = " order by faceTopVx";
|
|
WcString wc = new WcString();
|
|
wc.addWc("A.id_foto=" + l_id_foto);
|
|
try {
|
|
PreparedStatement stmt = getConn().prepareStatement(s_Sql_Find + s_Sql_Find + wc.toString());
|
|
return findRows(stmt);
|
|
} catch (SQLException e) {
|
|
removeCPConnection();
|
|
handleDebug(e);
|
|
return AB_EMPTY_VECTUMERATOR;
|
|
}
|
|
}
|
|
|
|
public Vectumerator<FotoFaceVision> findByFotoConLabel(long l_id_foto) {
|
|
String s_Sql_Find = "select A.* from FOTO_FACE AS A";
|
|
String s_Sql_Order = " order by faceTopVx";
|
|
WcString wc = new WcString();
|
|
wc.addWc("A.id_foto=" + l_id_foto);
|
|
wc.addWc("(A.label is not null or A.label <>'')");
|
|
try {
|
|
PreparedStatement stmt = getConn().prepareStatement(s_Sql_Find + s_Sql_Find + wc.toString());
|
|
return findRows(stmt);
|
|
} catch (SQLException e) {
|
|
removeCPConnection();
|
|
handleDebug(e);
|
|
return AB_EMPTY_VECTUMERATOR;
|
|
}
|
|
}
|
|
|
|
public List<Double> getFetureVetctor1list() {
|
|
if (getFeatureVector1().isEmpty())
|
|
return null;
|
|
StringTokenizer st = new StringTokenizer(getFeatureVector1(), ",");
|
|
List<Double> res = new ArrayList<>();
|
|
while (st.hasMoreTokens()) {
|
|
String token = st.nextToken();
|
|
res.add(Double.valueOf(Double.parseDouble(token)));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public ResParm _createFeatureVectorBottom() {
|
|
ResParm rp = new ResParm();
|
|
if (getFace() == null) {
|
|
rp.setStatus(false);
|
|
rp.setMsg(getFoto().getFileName() + ": No json data...");
|
|
return rp;
|
|
}
|
|
List<Double> featureVector = new ArrayList<>();
|
|
List<Point> points = new ArrayList<>();
|
|
points.add(getFace().getEL_C());
|
|
points.add(getFace().getER_C());
|
|
points.add(getFace().getEA_L());
|
|
points.add(getFace().getEA_R());
|
|
points.add(getFace().getCK_L());
|
|
points.add(getFace().getCK_R());
|
|
points.add(getFace().getM_C());
|
|
points.add(getFace().getN_T());
|
|
List<Double> distances = new ArrayList<>();
|
|
for (int i = 0; i < points.size() - 1; i++) {
|
|
Point p1 = points.get(i);
|
|
for (int j = i + 1; j < points.size(); j++) {
|
|
Point p2 = points.get(j);
|
|
double distance = Point.getDistance(p1, p2);
|
|
distances.add(Double.valueOf(distance));
|
|
}
|
|
}
|
|
double averageDistance = calculateAverageDistance(distances);
|
|
featureVector.add(Double.valueOf(averageDistance));
|
|
Double eyeDistance = Point.getDistance(getFace().getEL_C(), getFace().getER_C());
|
|
featureVector.add(eyeDistance);
|
|
Double eyeMouthDistance = Point.getDistance(getFace().getE_C(), getFace().getM_C());
|
|
featureVector.add(Double.valueOf(eyeMouthDistance / eyeDistance));
|
|
Double eyeNoseDistance = Point.getDistance(getFace().getE_C(), getFace().getN_T());
|
|
featureVector.add(Double.valueOf(eyeDistance / eyeNoseDistance));
|
|
Double eyeChinDistance = Point.getDistance(getFace().getE_C(), getFace().getCH());
|
|
Double eyeEyebrowDistance = Point.getDistance(getFace().getEBL_M(), getFace().getEBR_M());
|
|
Point midCheekPoint = new Point((getFace().getCK_L().getX() + getFace().getCK_R().getX()) / 2L, (
|
|
getFace().getCK_L().getY() + getFace().getCK_R().getY()) / 2L, (
|
|
getFace().getCK_L().getZ() + getFace().getCK_R().getZ()) / 2L);
|
|
Double eyeCheekDistance = Point.getDistance(getFace().getE_C(), midCheekPoint);
|
|
Double cheekDistance = Point.getDistance(getFace().getCK_L(), getFace().getCK_R());
|
|
featureVector.add(cheekDistance);
|
|
Double mouthCornerDistance = Point.getDistance(getFace().getM_L(), getFace().getM_R());
|
|
Double chinDistance = Point.getDistance(getFace().getCH_L(), getFace().getCH_R());
|
|
featureVector.add(chinDistance);
|
|
Double faceWidth = Point.getDistance(getFace().getEA_L(), getFace().getEA_R());
|
|
featureVector.add(faceWidth);
|
|
Double faceHeight = Point.getDistance(getFace().getFORH(), getFace().getM_C());
|
|
featureVector.add(faceHeight);
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEL_C(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getN_T(), getFace().getM_C())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEL_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEA_R(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getEA_L(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(calculateAngleDeg(getFace().getER_C(), getFace().getM_C(), getFace().getCH())));
|
|
featureVector.add(Double.valueOf(eyeDistance / faceWidth));
|
|
Double noseLen = Point.getDistance(getFace().getE_C(), getFace().getN_CB());
|
|
featureVector.add(Double.valueOf(noseLen / faceHeight));
|
|
Double mouthLen = Point.getDistance(getFace().getM_L(), getFace().getM_R());
|
|
featureVector.add(Double.valueOf(cheekDistance / faceWidth));
|
|
featureVector.add(Double.valueOf(faceHeight / faceWidth));
|
|
normalizeFeatureVector(featureVector);
|
|
StringBuilder sb = new StringBuilder();
|
|
for (Iterator<Double> iterator = featureVector.iterator(); iterator.hasNext(); ) {
|
|
double element = iterator.next();
|
|
sb.append(element);
|
|
sb.append(",");
|
|
}
|
|
setFeatureVector1(sb.toString().substring(1, sb.toString().length() - 1));
|
|
return rp;
|
|
}
|
|
|
|
public String getFileName() {
|
|
if (this.fileName == null || this.fileName.isEmpty())
|
|
this
|
|
.fileName = getFoto().getFileNameReale() + " _" + getFoto().getFileNameReale() + "_tr-" + getId_fotoFace() + "-" + getFaceTopVx() + "_bl-" + getFaceTopVy() + "-" + getFaceBottomVx() + ".jpg";
|
|
return (this.fileName == null) ? "" : this.fileName.trim();
|
|
}
|
|
|
|
public void setFileName(String fileName) {
|
|
this.fileName = fileName;
|
|
}
|
|
|
|
public String getLabel() {
|
|
return (this.label == null) ? "" : this.label.trim();
|
|
}
|
|
|
|
public void setLabel(String label) {
|
|
this.label = label;
|
|
}
|
|
|
|
public ResParm createFaceImage(boolean overwrite) {
|
|
ResParm rp = new ResParm();
|
|
if (getId_fotoFace() > 0L && hasImageBounds())
|
|
try {
|
|
File faceImg = new File(getFullFaceImgPath());
|
|
if (!faceImg.exists() || overwrite) {
|
|
if (faceImg.exists())
|
|
faceImg.delete();
|
|
BufferedImage sourceImage = ImageIO.read(new File(getFoto().getFileNameFullPath()));
|
|
int sourceWidth = sourceImage.getWidth();
|
|
int sourceHeight = sourceImage.getHeight();
|
|
int margin = 10;
|
|
int faceTopRightX = (int)getFaceTopVx() + margin;
|
|
int faceTopRightY = (int)getFaceTopVy() - margin;
|
|
int faceBottomLeftX = (int)getFaceBottomVx() - margin;
|
|
int faceBottomLeftY = (int)getFaceBottomVy() + margin;
|
|
int faceTopLeftX = faceBottomLeftX;
|
|
int faceTopLeftY = faceTopRightY;
|
|
int faceBottomRightX = faceTopRightX;
|
|
int faceBottomRightY = faceBottomLeftY;
|
|
int faceWidth = faceBottomRightX - faceTopLeftX;
|
|
int faceHeight = faceBottomRightY - faceTopLeftY;
|
|
DoubleOperator percW = new DoubleOperator((double)sourceWidth, 4);
|
|
percW.divide((float)faceWidth);
|
|
percW.subtract(1);
|
|
percW.multiply(100);
|
|
DoubleOperator percH = new DoubleOperator((double)sourceHeight, 4);
|
|
percH.divide((float)faceHeight);
|
|
percH.subtract(1);
|
|
percH.multiply(100);
|
|
File targetDir = new File(getFoto().getPuntoFoto().getPathCompletoFotoFace());
|
|
if (!targetDir.exists())
|
|
targetDir.mkdirs();
|
|
if (percW.getResult() < 26.0D || percH.getResult() < 26.0D) {
|
|
DBAdapter.copyFile(getFoto().getFileNameFullPath(), getFullFaceImgPath());
|
|
} else {
|
|
BufferedImage faceImage = sourceImage.getSubimage(faceTopLeftX, faceTopLeftY, faceWidth, faceHeight);
|
|
ImageIO.write(faceImage, "jpg", faceImg);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return rp;
|
|
}
|
|
|
|
public String getFullFaceImgPath() {
|
|
return getFoto().getPuntoFoto().getPathCompletoFotoFace() + "/" + getFoto().getPuntoFoto().getPathCompletoFotoFace();
|
|
}
|
|
|
|
protected void fillFields(ResultSet rst) {
|
|
super.fillFields(rst);
|
|
setLabelDb(getLabel());
|
|
createFaceImage(false);
|
|
}
|
|
|
|
public boolean hasImageBounds() {
|
|
if (getFaceTopVx() == 0L || getFaceBottomVx() == 0L || getFaceBottomVy() == 0L || getFaceTopVy() == 0L)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public String getLabelDb() {
|
|
return (this.labelDb == null) ? "" : this.labelDb.trim();
|
|
}
|
|
|
|
public void setLabelDb(String labelDb) {
|
|
this.labelDb = labelDb;
|
|
}
|
|
|
|
protected void initFields() {
|
|
super.initFields();
|
|
setLabelDb(null);
|
|
}
|
|
}
|