package it.acxent.face; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import it.acxent.common.StatusMsg; 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.FaceRecognitionApi; import it.acxent.face.api.FaceRecognitionApiResult; import it.acxent.face.api.TrainingImage; import it.acxent.face.scoring.SelfieScoringQueue; import it.acxent.face.scoring.SmartFaceScoringQueue; import it.acxent.log.Log; import it.acxent.util.AsyncExecutor; import it.acxent.util.StringTokenizer; import it.acxent.util.Timer; import it.acxent.util.Vectumerator; import java.io.File; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; public class Selfie extends _FaceAdapter implements Serializable, FaceScoreTarget { private static final long serialVersionUID = 1725875013194L; public static final long STATUS_DA_ELABORARE_0 = 0L; public static final long STATUS_IN_ELABORAZIONE = 1L; public static final long STATUS_ELABORAZIONE_CONCLUSA = 99L; public static final int FACE_WIDTH = 96; public static final int FACE_WIDTH_WWW = 192; private static final int NUM_THREADS_ELABORAZIONE = 5; private static final Map elaborazioniInCorso = Collections.synchronizedMap(new HashMap<>()); private long id_selfie; private String labelMd5; private String fileName; private long label; private long flgStatus; private long id_evento; private long codGara; private Evento evento; private Timestamp tsCreation; private String fileAlternativo; private double confidence; private String md5; private String md5Face; private String elencoFoto; private String elencoFotoExt; private long rangeExt; public Selfie(ApplParmFull newApplParmFull) { super(newApplParmFull); } public Selfie() {} public static void addCodaElaborazioneAsync(Selfie selfie, boolean inviaNotifiche) { AsyncExecutor.ELABORAZIONE_EXECUTOR.submit(() -> addCodaElaborazione(selfie, inviaNotifiche)); } public static void addCodaElaborazione(Selfie selfie, boolean inviaNotifiche) { boolean debug = false; DBAdapter.printDebug("addCodaElaborazione1"); if (selfie.getFlgStatus() == 0L) { DBAdapter.printDebug("addCodaElaborazione2"); boolean debug3 = true; int priority = 10; ResParm rp = new ResParm(); Timer timer = new Timer(); timer.start(); Evento evento = selfie.getEvento(); String TAG_THREAD_MSG = "SCORING SELFIE " + selfie.getId_selfie(); SelfieScoringQueue selfieScoringQueue = SelfieScoringQueue.getInstance(selfie.getApFull()); DBAdapter.printDebug("addCodaElaborazione3"); String targetDir = selfie.getParm("PATHFOTO_FACE").getTesto() + selfie.getParm("PATHFOTO_FACE").getTesto(); File targetDirFile = new File(targetDir); if (!targetDirFile.exists()) targetDirFile.mkdirs(); double confDetectLevel = evento.getDetectFaceConfidentThresold(); long dysType = selfie.getParm("ZOO_YUNET_SCORING_DYS_TYPE").getNumeroLong(); FaceScore fs = new FaceScore(selfie.getApFull()); StatusMsg.updateMsgByTag(evento.getApFull(), TAG_THREAD_MSG, "coda elab: QUERY TARGET X EVENTO......"); Vectumerator vecFsTarget = fs.findTargetByEvento(evento.getId_evento(), -1L); JsonObject jsonData = new JsonObject(); jsonData.addProperty("dis_type", Long.valueOf(dysType)); jsonData.addProperty("conf_threshold", Double.valueOf(confDetectLevel)); JsonObject jsonTarget = new JsonObject(); jsonTarget.addProperty("id", Long.valueOf(selfie.getId_selfie())); jsonTarget.addProperty("path", selfie.getRealSelfieImgPath()); jsonTarget.addProperty("md5", selfie.getMd5()); jsonTarget.addProperty("type", "selfie"); jsonData.add("target", (JsonElement)jsonTarget); FaceScore currentFs = new FaceScore(); JsonArray jsonQuery = new JsonArray(); while (vecFsTarget.hasMoreElements()) { currentFs = (FaceScore)vecFsTarget.nextElement(); JsonObject jsonQueryRow = new JsonObject(); jsonQueryRow.addProperty("id", Long.valueOf(currentFs.getId_fotoFace())); jsonQueryRow.addProperty("path", currentFs.getFotoFace().getFacePath()); jsonQueryRow.addProperty("md5", currentFs.getFotoFace().getMd5()); jsonQueryRow.addProperty("type", "face"); jsonQuery.add((JsonElement)jsonQueryRow); } DBAdapter.printDebug(debug, "1.. inizio scoring - " + selfieScoringQueue.getStatus()); SmartFaceScoringQueue smartFaceScoringQueue = SmartFaceScoringQueue.getInstance(evento.getApFull()); smartFaceScoringQueue.setPause(true); Vectumerator> vecF = selfieScoringQueue.faceScoring(evento, jsonQuery, jsonTarget, confDetectLevel, priority); DBAdapter.printDebug(debug3, "8. future arrivato"); DBAdapter.printDebug(debug3, "8.1 vecF.getTotNumberOfRecords(): " + vecF.getTotNumberOfRecords()); String eta = ""; Timer timerFuture = new Timer(); int futureError = 0; timerFuture.start(); for (int fidx = 0; fidx < vecF.getTotNumberOfRecords(); fidx++) { eta = timerFuture.getEta((long)fidx, (long)vecF.getTotNumberOfRecords()); StatusMsg.updateMsgByTag(evento.getApFull(), TAG_THREAD_MSG, "punto foto:" + currentFs.getFoto().getPuntoFoto().getDescrizione() + " future: " + fidx + "/" + vecF.getTotNumberOfRecords() + " futureError:" + futureError + " future eta: " + eta + "\n" + selfieScoringQueue.getStatus()); Future currentFuture = (Future)vecF.nextElement(); if (currentFuture == null) { rp.setStatus(false); rp.setMsg("Errore: Future null per indice " + fidx); DBAdapter.printDebug(debug3, "addCodaElaborazione4 -> null Errore: Future null per indice " + fidx); } else { try { rp = currentFuture.get(45L, TimeUnit.SECONDS); } catch (TimeoutException e) { DBAdapter.printDebug(debug3, "addCodaElaborazione5 -> Errore Timeout su future index " + fidx + ", ignorando."); } catch (InterruptedException e) { DBAdapter.printDebug(debug3, "addCodaElaborazione6 -> Errore Interruzione rilevata, terminazione del ciclo."); Thread.currentThread().interrupt(); } catch (ExecutionException e) { DBAdapter.printDebug(debug3, "addCodaElaborazione7 -> Errore durante l'esecuzione del task " + fidx + ": " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { DBAdapter.printDebug(debug3, "addCodaElaborazione8 -> Errore generico su future index " + fidx + ": " + e.getMessage()); e.printStackTrace(); } if (!rp.getStatus()) { DBAdapter.printDebug(debug3, "addCodaElaborazione9 -> errore future: " + rp.getMsg()); futureError++; } } } smartFaceScoringQueue.setPause(false); timerFuture.stop(); selfieScoringQueue.poolShutdown(); timer.stop(); String durata = "" + timer.getDurataMilliSec() / 1000L + " sec."; DBAdapter.printDebug(debug3, "addCodaElaborazione10 ->. shutdown concluso. Durata elaborazione selfie: " + durata); DBAdapter.printDebug(debug3, "addCodaElaborazione11 -> SELFIE STATUS_ELABORAZIONE_CONCLUSA SU face per selfie: " + selfie.getId_selfie()); selfie.updateFlgStatus(99L); if (inviaNotifiche) { if (evento.getCodiceEventoCliente().matches("\\d+")) { DBAdapter.printDebug(debug3, "addCodaElaborazione12 -> INVIO COMANDO NOTIFICHE!!! codiceEventoCliente: " + evento.getCodiceEventoCliente() + " evento: " + evento.getId_evento() + " durata:" + durata); Evento.inviaNotificaRemotaWww(selfie.getApFull(), Long.valueOf(evento.getCodiceEventoCliente()).longValue()); } else { DBAdapter.printDebug(debug3, "addCodaElaborazione13 -> NIENTE NOTIFICHE. evento.getCodiceEventoCliente() NON e' UN NUMERO: " + evento.getCodiceEventoCliente() + " evento: " + evento.getId_evento() + " DURATA" + durata); } } else { DBAdapter.printDebug(debug3, "addCodaElaborazione14 -> NIENTE NOTIFICHE. FALSE. evento: " + evento.getId_evento() + " DURATA" + durata); } StatusMsg.deleteMsgByTag(evento.getApFull(), TAG_THREAD_MSG); Log.addAltro(selfie.getApFull(), "127.0.0.1", 1L, " scoringSelfie: FINE!!! \n" + durata + "\nRisultato: " + rp.getMsg()); } else { DBAdapter.printDebug(debug, "addCodaElaborazione15 ->1 NENTE ADD CODA ELABORAZIONE.... SELFIE IN STATO DIVERSO DA DA ELABORARE_0: ID: " + selfie.getId_selfie() + " md5:" + selfie.getMd5()); } } public void setId_selfie(long newId_selfie) { this.id_selfie = newId_selfie; } public void setMd5(String newMd5) { this.md5 = newMd5; } public void setTsCreation(Timestamp newTsCreation) { this.tsCreation = newTsCreation; } public long getId_selfie() { return this.id_selfie; } public String getMd5() { return (this.md5 == null) ? "" : this.md5.trim(); } public Timestamp getTsCreation() { return this.tsCreation; } protected ResParm checkDeleteCascade() { return new ResParm(true); } protected void deleteCascade() {} public Vectumerator findByCR(SelfieCR CR, int pageNumber, int pageRows) { String s_Sql_Find = "select A.* from SELFIE 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; } } public String getFileName() { if (this.fileName == null || this.fileName.isEmpty()) this.fileName = getMd5() + ".jpg"; return (this.fileName == null) ? "" : this.fileName.trim(); } public String getFullFileNameSelfie() { return getPathCompletoSelfie() + "/" + getPathCompletoSelfie(); } public String getFullFileNameSelfieWww() { return getPathCompletoSelfieWww() + "/" + getPathCompletoSelfieWww(); } public String getRealSelfieImgPath() { String currentFileName; if (getFileAlternativo().isEmpty()) { currentFileName = getFullFileNameSelfie(); } else { currentFileName = getFileAlternativo(); } return currentFileName; } public String getRealSelfieImgMd5() { String currentMd5; if (getFileAlternativo().isEmpty()) { if (getMd5Face().isEmpty()) { currentMd5 = getMd5(); } else { currentMd5 = getMd5Face(); } } else { currentMd5 = getMd5(); } return currentMd5; } public boolean isSelfieImageExist() { if (getId_selfie() == 0L) return false; return new File(getRealSelfieImgPath()).exists(); } public boolean isSelfieGara(long l_id_gara) { return (getCodGara() == l_id_gara); } public String getPathCompletoSelfie() { String temp = DBAdapter.convertPathToCurrentFileSystemSeparator(getParm("FULL_PATH_SELFIE").getTesto()); if (!temp.endsWith(DBAdapter.SEPARATOR)) temp = temp + temp; return temp; } public String getPathCompletoSelfieWww() { String temp = getDocBase() + "_selfie"; if (!temp.endsWith(DBAdapter.SEPARATOR)) temp = temp + temp; return temp; } public void setFileName(String fileName) { this.fileName = fileName; } public ResParm save() { if (getTsCreation() == null) setTsCreation(getTimestamp()); if (getMd5Face().isEmpty()) setMd5Face(DBAdapter.getFileMd5(getFullFileNameFaceWww(192))); if (getMd5().isEmpty()) setMd5(DBAdapter.getFileMd5(getFullFileNameSelfie())); return super.save(); } public String getFullFileNameFaceWww(int w) { return getPathCompletoSelfieWww() + "/" + getPathCompletoSelfieWww() + getExtraPathFaces(w); } public String getExtraPathFaces(int w) { return "_faces" + w + "/"; } public void findByMd5(String l_md5) { String s_Sql_Find = "select A.* from SELFIE AS A"; String s_Sql_Order = ""; WcString wc = new WcString(); wc.addWc("A.md5='" + l_md5 + "'"); try { PreparedStatement stmt = getConn().prepareStatement(s_Sql_Find + s_Sql_Find + wc.toString()); findFirstRecord(stmt); } catch (SQLException e) { removeCPConnection(); handleDebug(e); } } @Deprecated public void findByMd5CodGara(String l_md5, long l_codGara) { String s_Sql_Find = "select A.* from SELFIE AS A"; String s_Sql_Order = ""; WcString wc = new WcString(); wc.addWc("A.md5='" + l_md5 + "'"); wc.addWc("A.codGara=" + l_codGara); try { PreparedStatement stmt = getConn().prepareStatement(s_Sql_Find + s_Sql_Find + wc.toString()); findFirstRecord(stmt); } catch (SQLException e) { removeCPConnection(); handleDebug(e); } } public void findByMd5Evento(String l_md5, long l_id_evento) { String s_Sql_Find = "select A.* from SELFIE AS A"; String s_Sql_Order = ""; WcString wc = new WcString(); wc.addWc("A.md5='" + l_md5 + "'"); wc.addWc("A.id_evento=" + l_id_evento); try { PreparedStatement stmt = getConn().prepareStatement(s_Sql_Find + s_Sql_Find + wc.toString()); findFirstRecord(stmt); } catch (SQLException e) { removeCPConnection(); handleDebug(e); } } public long getId_fotoFace() { return 0L; } public String getFacePath() { return getRealSelfieImgPath(); } public long getLabel() { return this.label; } public void setLabel(long label) { this.label = label; } public ResParm recognize(FaceRecognizer fr) { ResParm rp = new ResParm(); boolean debug = false; DBAdapter.printDebug(debug, " serfie.recognize chiamata _recognize"); if (getId_selfie() > 0L && this.label <= 0L) { List imageFilenames = new ArrayList<>(); imageFilenames.add(new TrainingImage(getFullFileNameSelfie(), getMd5())); rp = recognizeImages(fr, imageFilenames); } else { rp.setStatus(false); rp.setMsg("Errore! FotoFace nullo!"); } return rp; } public ResParm recognizeImages(FaceRecognizer fr, List imageFilenames) { ResParm rp = new ResParm(); boolean debug = false; long totImgTrovate = 0L; StringBuilder errMsg = new StringBuilder(); FaceRecognitionApi frApi = new FaceRecognitionApi(getApFull()); DBAdapter.printDebug(debug, " serfie.recognizeImages chiamata _recognize"); FaceRecognitionApiResult res = frApi.__recognize(fr.getId_faceRecognizer(), imageFilenames, false); JsonObject jRes = (JsonObject)res.getResult(); DBAdapter.printDebug(debug, " serfie.recognizeImages prima risposta jres: " + res.getMsg()); if (jRes != null) DBAdapter.printDebug(debug, " serfie.recognizeImages jres prima risposta jres: " + DBAdapter.gsonToString(jRes)); if (jRes != null && jRes.get("success").getAsBoolean() == true) { Selfie currentSelfie = new Selfie(getApFull()); rp = processRecognizingResponses(currentSelfie, jRes); totImgTrovate += (Long)rp.getReturnObj(); if (jRes.has("noImg")) { JsonArray jNoimgA = jRes.get("noImg").getAsJsonArray(); imageFilenames = new ArrayList<>(); for (int k = 0; k < jNoimgA.size(); k++) { JsonObject jNoImgRow = jNoimgA.get(k).getAsJsonObject(); DBAdapter.printDebug(debug, " serfie.recognizeImages noimg md5: " + jNoImgRow.get("md5").getAsString()); currentSelfie.findByMd5(jNoImgRow.get("md5").getAsString()); if (currentSelfie.getId_selfie() > 0L) imageFilenames.add(new TrainingImage( currentSelfie.getFullFileNameSelfie(), currentSelfie.getLabel(), currentSelfie.getMd5())); } DBAdapter.printDebug(" serfie.recognizeImages chiamata con immagini: n. immagini inviate: " + imageFilenames.size()); res = frApi.__recognize(fr.getId_faceRecognizer(), imageFilenames, true); jRes = (JsonObject)res.getResult(); System.out.println(String.valueOf(DBAdapter.getNowTs()) + " serfie.recognizeImages seconda risposta da _recognize:\n" + String.valueOf(DBAdapter.getNowTs())); if (jRes.get("success").getAsBoolean() == true) { rp = processRecognizingResponses(currentSelfie, jRes); totImgTrovate += (Long)rp.getReturnObj(); DBAdapter.printDebug(debug, " serfie.recognizeImages totimgtrovate: " + totImgTrovate); } } } rp.setMsg("Trovate " + totImgTrovate + " immagini. "); rp.setReturnObj(Long.valueOf(totImgTrovate)); if (errMsg.length() > 0) { rp.setStatus(false); rp.appendMsg(errMsg.toString()); } else { rp.setStatus(true); } return rp; } private ResParm processRecognizingResponses(Selfie currentSelfie, JsonObject jRes) { ResParm rp = new ResParm(); StringBuilder errMsg = new StringBuilder(); long totImgTrovate = 0L; if (jRes.has("responses")) { JsonArray jResponses = jRes.get("responses").getAsJsonArray(); for (int i = 0; i < jResponses.size(); i++) { JsonObject jResponse = jResponses.get(i).getAsJsonObject(); String md5 = jResponse.get("md5").getAsString(); currentSelfie.findByMd5(md5); if (currentSelfie.getId_selfie() > 0L) { JsonArray jLabels = jResponse.get("labels").getAsJsonArray(); JsonObject jLabelRow = jLabels.get(0).getAsJsonObject(); long predictedLabel = jLabelRow.get("label").getAsLong(); String predictedLabelMd5 = jLabelRow.get("labelMd5").getAsString(); double confidence = jLabelRow.get("confidence").getAsDouble(); currentSelfie.setLabel(predictedLabel); currentSelfie.setConfidence(confidence); currentSelfie.setLabelMd5(predictedLabelMd5); rp = currentSelfie.save(); if (rp.getStatus()) { totImgTrovate++; } else { errMsg.append(rp.getErrMsg()); errMsg.append("\n"); } } } } rp.setMsg("Trovate " + totImgTrovate + " immagini. "); rp.setReturnObj(Long.valueOf(totImgTrovate)); if (errMsg.length() > 0) { rp.setStatus(false); rp.appendMsg(errMsg.toString()); } else { rp.setStatus(true); } return rp; } public double getConfidence() { return this.confidence; } public void setConfidence(double confidence) { this.confidence = confidence; } public String getLabelMd5() { return (this.labelMd5 == null) ? "" : this.labelMd5.trim(); } public void setLabelMd5(String labelMd5) { this.labelMd5 = labelMd5; } public long getFlgStatus() { return this.flgStatus; } public static final String getStatus(long l_flgStatus) { if (l_flgStatus == 0L) return "Da elaborare"; if (l_flgStatus == 1L) return "In elaborazione"; if (l_flgStatus == 99L) return "Elaborazione Conclusa"; return "??"; } public final String getStatus() { return getStatus(getFlgStatus()); } public void setFlgStatus(long flgStatus) { this.flgStatus = flgStatus; } public ResParm updateFlgStatus(long flgStatus) { if (getId_selfie() == 0L) return new ResParm(false, "Selfie con id a 0"); ResParm rp = update("UPDATE SELFIE SET flgStatus=" + flgStatus + " where id_selfie=" + getId_selfie()); if (rp.getStatus()) setFlgStatus(flgStatus); return rp; } public ResParm resetSelfie() { if (getId_selfie() == 0L) return new ResParm(false, "Selfie con id a 0"); ResParm rp = update("UPDATE SELFIE set flgStatus=0 , elencofoto = null where id_selfie=" + getId_selfie()); if (rp.getStatus()) { setElencoFoto(null); setFlgStatus(0L); } elaborazioniInCorso.remove(Long.valueOf(getId_selfie())); return rp; } public long getId_evento() { return this.id_evento; } public void setId_evento(long id_evento) { this.id_evento = id_evento; setEvento(null); } public Evento getEvento() { this.evento = (Evento)getSecondaryObject(this.evento, Evento.class, getId_evento()); return this.evento; } public void setEvento(Evento evento) { this.evento = evento; } public JsonObject getJsonResponseByEvento(long l_id_evento) { boolean debug = true; if (getId_selfie() == 0L) return null; JsonObject response = new JsonObject(); response.addProperty("md5", this.md5); Evento evento = new Evento(getApFull()); evento.findByPrimaryKey(l_id_evento); JsonArray labelsArray = new JsonArray(); FaceScore sf = new FaceScore(getApFull()); Vectumerator vec = sf.findBySelfieEvento(getId_selfie(), l_id_evento); while (vec.hasMoreElements()) { FaceScore row = (FaceScore)vec.nextElement(); JsonObject jRow = new JsonObject(); if (evento.getScoreThresoldSelfieSearch2() == 0.0D || (double)row.getScore() >= evento.getScoreThresoldSelfieSearch2()) { jRow.addProperty("confidence", Float.valueOf(row.getScore())); jRow.addProperty("fileName", row.getFotoFace2().getFoto().getFileName()); jRow.addProperty("id", Long.valueOf(row.getId_fotoFace2())); labelsArray.add((JsonElement)jRow); } } if (debug) DBAdapter.printDebug("elenco target score > di " + evento.getScoreThresoldSelfieSearch2() + " labelsArray.size(): " + labelsArray.size()); if (labelsArray.size() > 0) { long nTarget = getEvento().getScoreSelfieNTarget(); if (nTarget <= 0L) nTarget = 2L; long percTHreshold = getEvento().getScoreSelfieTargetThresold(); if (percTHreshold <= 0L) percTHreshold = 10L; double percentageThreshold = (double)percTHreshold / 100.0D; DBAdapter.printDebug(debug, "getJsonResponseByEvento " + evento.getScoreThresoldSelfieSearch2() + " labelsArray.size(): " + labelsArray.size() + "con n. target massimo " + nTarget + " e soglia di scarto massima " + percentageThreshold); List labels = new ArrayList<>(); for (JsonElement element : (Iterable)labelsArray) labels.add(element.getAsJsonObject()); labels.sort((a, b) -> Double.compare(b.get("confidence").getAsDouble(), a.get("confidence").getAsDouble())); double maxConfidence = labels.get(0).get("confidence").getAsDouble(); List filteredLabels = (List)labels.stream().filter(label -> (label.get("confidence").getAsDouble() >= maxConfidence * (1.0D - percentageThreshold))) .limit(nTarget).collect(Collectors.toList()); JsonArray filteredArray = new JsonArray(); Objects.requireNonNull(filteredArray); filteredLabels.forEach(filteredArray::add); Gson gson = new Gson(); DBAdapter.printDebug(debug, "Filtered JSON con n. target massimo " + nTarget + " e soglia di scarto massima " + percentageThreshold + "\n" + gson.toJson((JsonElement)filteredArray) + "\n"); JsonArray resultArray = new JsonArray(); for (JsonElement element : (Iterable)filteredArray) resultArray.add(element); for (JsonElement element : (Iterable)filteredArray) { JsonObject rowJo = element.getAsJsonObject(); long l_id_faceTarget = rowJo.get("id").getAsLong(); double l_confidenceTarget = rowJo.get("confidence").getAsDouble(); vec = sf.findQueryByFace(l_id_faceTarget, 0, 0); DBAdapter.printDebug(debug, "carico query da : " + l_id_faceTarget + ". tot elementi: " + vec.getTotNumberOfRecords()); while (vec.hasMoreElements()) { FaceScore row = (FaceScore)vec.nextElement(); JsonObject jRow = new JsonObject(); jRow.addProperty("confidence", Double.valueOf(l_confidenceTarget)); jRow.addProperty("fileName", row.getFotoFace2().getFoto().getFileName()); resultArray.add((JsonElement)jRow); } } response.add("labels", (JsonElement)resultArray); } if (debug) if (response.has("labels") && response.get("labels").isJsonArray()) { JsonArray labels = response.getAsJsonArray("labels"); DBAdapter.printDebug(debug, "RISULTATO FINALE: Numero foto trovate: " + labels.size()); } else { DBAdapter.printDebug(debug, "RISULTATO FINALE: Numero foto trovate: 0"); } return response; } public JsonObject getJsonResponseByEventoERRATO(long l_id_evento) { if (getId_selfie() == 0L) return null; JsonObject response = new JsonObject(); response.addProperty("md5", this.md5); Evento evento = new Evento(getApFull()); evento.findByPrimaryKey(l_id_evento); JsonArray labels = new JsonArray(); FaceScore sf = new FaceScore(getApFull()); Vectumerator vec = sf.findBySelfieEvento(getId_selfie(), l_id_evento); while (vec.hasMoreElements()) { FaceScore row = (FaceScore)vec.nextElement(); JsonObject jRow = new JsonObject(); if (evento.getScoreThresoldSelfieSearch2() == 0.0D || evento.getScoreThresoldSelfieSearch2() >= (double)row.getScore()) { jRow.addProperty("confidence", Float.valueOf(row.getScore())); jRow.addProperty("fileName", row.getFotoFace2().getFoto().getFileName()); labels.add((JsonElement)jRow); } } response.add("labels", (JsonElement)labels); return response; } public String getFileAlternativo() { return (this.fileAlternativo == null) ? "" : this.fileAlternativo.trim(); } public void setFileAlternativo(String fileAlternativo) { this.fileAlternativo = fileAlternativo; } public String getMd5Face() { return (this.md5Face == null) ? "" : this.md5Face.trim(); } public void setMd5Face(String md5Source) { this.md5Face = md5Source; } public final ResParm detectFaceWww(boolean force) { boolean debug = true; ResParm rp = new ResParm(); DBAdapter.printDebug(debug, "0 Selfie.detectFace call api......."); if (getId_selfie() == 0L || getApFull() == null) { rp.setStatus(false); rp.setMsg("Errore! Selfie non valido"); } double confidenceThresold = 0.85D; String sourceMd5 = DBAdapter.getFileMd5(getFullFileNameSelfie()); setMd5Face(sourceMd5); DBAdapter.printDebug(debug, "1-------------------- Selfie.detectFace ** ------------------------foto md5source: " + sourceMd5); if (!force); DBAdapter.printDebug(debug, "Selfie.detectFace: " + getId_selfie() + " " + getFullFileNameSelfie()); String userFR = getParm("FACE_RECOGNITION_API_USER").getTesto(); String pwdFR = getParm("FACE_RECOGNITION_API_PWD").getTesto(); FaceRecognitionApi bean = new FaceRecognitionApi(getApFull(), userFR, pwdFR); DBAdapter.printDebug(debug, "2 Selfie.detectFace call api foto md5source: " + sourceMd5); FaceRecognitionApiResult resF = bean.__detectFaces(getFullFileNameSelfieWww(), sourceMd5, 20L, false, confidenceThresold, false); if (resF.isOk()) { DBAdapter.printDebug("3 Selfie.detectFace ok... chiamo Selfie.createFaceByFaceRecognitionJson foto md5source: " + sourceMd5); return createFaceByFaceRecognitionJsonWww((JsonObject)resF.getResult()); } DBAdapter.printDebug(debug, "4 Selfie.detectFace KO foto md5: " + sourceMd5); rp.setStatus(false); rp.setMsg(resF.getMsg() + " id_Selfie: " + resF.getMsg()); return rp; } protected final ResParm createFaceByFaceRecognitionJsonWww(JsonObject jo) { ResParm rp = new ResParm(); boolean debug = false; DBAdapter.printDebug("1-------------------- createFaceByFaceRecognitionJson ------------------------ id_userGara: " + getId_selfie()); long minDimFoto = 45L; try { if (getId_selfie() == 0L || getApFull() == null) { rp.setStatus(false); rp.setMsg("Errore! Foto Selfie non valido...."); } StringBuilder msg = new StringBuilder(); int numOfNUmbers = 0; int numOfFaces = 0; int numOfSmallFaces = 0; long totFaces = 0L; int faceWidth = 192; int faceExtraMargin = 10; JsonArray jaResponses = jo.get("responses").getAsJsonArray(); boolean visiTrovati = false; if (jaResponses.size() > 0) { JsonObject joResponse = jaResponses.get(0).getAsJsonObject().getAsJsonObject("response"); String md5Response = joResponse.get("md5").getAsString().trim(); System.out.println("1.1 md5response: " + md5Response + " md5source: " + getMd5Face()); if (md5Response.equals(getMd5Face())) { DBAdapter.printDebug(debug, "2 foto md5source: " + getMd5Face() + " joResponse:\n" + DBAdapter.gsonToString(joResponse)); if (joResponse.has("faceAnnotations")) { visiTrovati = true; JsonArray jaFaceAnnotations = joResponse.getAsJsonArray("faceAnnotations"); numOfFaces = jaFaceAnnotations.size(); if (numOfFaces > 1) { rp.setStatus(false); rp.setMsg("Attenzione! Trovati " + numOfFaces + " visi"); } else { JsonObject joFaceAnnotation = jaFaceAnnotations.get(0).getAsJsonObject(); JsonObject joFace = new JsonObject(); JsonObject joFdBoundingPoly = joFaceAnnotation.getAsJsonObject("fdBoundingPoly"); joFace.add("fdBoundingPoly", (JsonElement)joFdBoundingPoly); JsonArray jaVertices = joFdBoundingPoly.getAsJsonArray("vertices"); JsonObject joTopLeft = jaVertices.get(0).getAsJsonObject(); JsonObject joBottomRight = jaVertices.get(2).getAsJsonObject(); boolean noDetect = false; long faceBottomVx = 0L, faceBottomVy = 0L, faceTopVx = 0L, faceTopVy = 0L; if (joBottomRight.has("x")) { faceBottomVx = joBottomRight.get("x").getAsLong(); faceBottomVy = joBottomRight.get("y").getAsLong(); } else { noDetect = true; } if (joTopLeft.has("x")) { faceTopVx = joTopLeft.get("x").getAsLong(); faceTopVy = joTopLeft.get("y").getAsLong(); } else { noDetect = true; } DBAdapter.printDebug(debug, "3 foto md5source: " + getMd5Face() + " salvo vertici : joface\n" + DBAdapter.gsonToString(joFace)); long latoX = Math.abs(faceBottomVx - faceBottomVy); DBAdapter.printDebug(debug, "5 faceBottomVx:" + faceBottomVx + " faceBottomVy:" + faceBottomVy + " faceTopVx:" + faceTopVx + " faceTopVy:" + faceTopVy + "\nlatoX: " + latoX + " dimfoto:" + minDimFoto); if (latoX >= minDimFoto) { rp = FaceRecognitionApi.createFace(getFullFileNameSelfieWww(), getFullFileNameFaceWww(faceWidth), faceTopVx, faceTopVy, faceBottomVx, faceBottomVy, faceWidth, faceExtraMargin, true); rp = save(); } else { numOfSmallFaces++; rp.setStatus(false); rp.setMsg("Attenzione! identificato viso troppo piccolo!"); } if (!rp.getStatus()) DBAdapter.printDebug(debug, "6 foto md5source: " + getMd5Face() + " errore : " + rp.getMsg()); } } } else { rp.setStatus(false); rp.setMsg("ERRORE! md5 invio diverso da md5 response. md5source:" + getMd5Face() + " --> " + md5Response); System.out.println(DBAdapter.getNowTsB() + " 9999 foto md5source: " + DBAdapter.getNowTsB() + " md5 response: " + getMd5Face() + " **************************** createFaceByFaceRecognitionJson **************************"); } } if (msg.length() > 0) { rp.setStatus(false); rp.setMsg(msg.toString()); } if (rp.getStatus()) rp.setMsg("Trovati " + numOfFaces + "(" + totFaces + ") visi e " + numOfNUmbers + " numeri foto piccole: " + numOfSmallFaces); } catch (Exception e) { e.printStackTrace(); rp.setStatus(false); rp.setMsg(e); } DBAdapter.printDebug(debug, " 8 foto md5source: " + getMd5Face() + " **************************** createFaceByFaceRecognitionJson **************************"); return rp; } public String getElencoFoto() { if (this.elencoFoto == null) return ""; return DBAdapter.removeDuplicates(this.elencoFoto, ","); } public void setElencoFoto(String elencofoto) { this.elencoFoto = elencofoto; setElencoFotoExt(null); } public synchronized void startThreadUpdateElencoFotoScoring() { DBAdapter.printDebug(true, "SelfieFE -> startThreadUpdateElencoFotoScoring... inizio"); long id = getId_selfie(); if (elaborazioniInCorso.containsKey(Long.valueOf(id))) { DBAdapter.printDebug(true, "ELABORAZIONE GIA' IN CORSO PER SELFIE ID: " + id); return; } elaborazioniInCorso.put(Long.valueOf(id), Boolean.valueOf(true)); DBAdapter.printDebug(true, "=====> ELABORAZIONE IN CORSO PER SELFIE ID: " + id); if (getId_selfie() > 0L && getCodGara() > 0L && getFlgStatus() != 99L) new Thread(() -> { try { boolean debug = false; long l_flgStatus = 0L; DBAdapter.printDebug(debug, "SelfieFE -> chiamata scoring. status: " + getFlgStatus()); FaceRecognitionApi frApi = new FaceRecognitionApi(getApFull()); DBAdapter.printDebug(debug, " selfieFE.startThreadUpdateElencoFotoScoring chiamata __scoringSelfie"); FaceRecognitionApiResult res = frApi.__scoringSelfie(getCodGara(), getFullFileNameFaceWww(192), getMd5(), false, false); if (!res.isOk()) { JsonObject jsonObject = res.getJsonObjectResult(); DBAdapter.printDebug(debug, "No img:\n" + DBAdapter.gsonToString(jsonObject)); if (jsonObject != null && jsonObject.has("noImg")) { DBAdapter.printDebug(debug, "No img NUOVA RICHIESTA"); res = frApi.__scoringSelfie(getCodGara(), getFullFileNameFaceWww(192), getMd5(), true, false); } } DBAdapter.printDebug(debug, "selfieFE RES:" + res.isOk()); if (res.isOk()) { JsonObject jsonObject = res.getJsonObjectResult(); JsonObject response = jsonObject.getAsJsonObject("response"); StringBuilder elencoFotoScoring = new StringBuilder(); JsonArray labels = null; JsonElement elem = response.get("labels"); if (elem != null && elem.isJsonArray()) { labels = elem.getAsJsonArray(); DBAdapter.printDebug(debug, "selfieFE Risultato elab:. n. labels: " + labels.size()); } else { DBAdapter.printDebug(debug, "selfieFE Risultato elab SENZA LABELS:\n" + DBAdapter.gsonToString(response)); } if (labels != null) for (int i = 0; i < labels.size(); i++) { JsonObject labelObject = labels.get(i).getAsJsonObject(); double confidence = labelObject.get("confidence").getAsDouble(); String fileName = labelObject.get("fileName").getAsString(); if (elencoFotoScoring.length() > 0) elencoFotoScoring.append(","); elencoFotoScoring.append(fileName); } if (!getElencoFoto().equals(elencoFotoScoring.toString())) { setElencoFoto(elencoFotoScoring.toString()); ResParm rp = super.save(); DBAdapter.printDebug("selfieFE updateElencoFotoScoring rp: " + rp.getMsg() + " adesso su selfie ho elencofoto:\n" + getElencoFoto()); } else { DBAdapter.printDebug(debug, "selfieFE updateElencoFotoScoring non ho salvato perché uguali"); } if (jsonObject.has("status")) l_flgStatus = jsonObject.get("status").getAsLong(); } else { l_flgStatus = 0L; DBAdapter.printDebug(debug, "selfieFE RES IS NOT OK --> save status STATUS_DA_ELABORARE_0 "); superSave(); } } finally { elaborazioniInCorso.remove(Long.valueOf(id)); DBAdapter.printDebug(true, "======> ELABORAZIONE TERMINTATA PER selfie ID: " + id); } }).start(); } public ResParm superSave() { return super.save(); } public long getCodGara() { return this.codGara; } public void setCodGara(long codGara) { this.codGara = codGara; } public String getElencoFotoExt() { if (getEvento().getSelfieRangeExt() == 0L) { setRangeExt(getEvento().getSelfieRangeExt()); DBAdapter.printDebug("getElencoFotoExt ritorno elenco foto"); calcolaElencoFotoExt(1L); return getElencoFoto(); } if (getRangeExt() != getEvento().getSelfieRangeExt() || this.elencoFotoExt == null || this.elencoFotoExt.isEmpty()) calcolaElencoFotoExt(getEvento().getSelfieRangeExt()); DBAdapter.printDebug("RITORNO ELENCOFOTOEXT: " + this.elencoFotoExt); return this.elencoFotoExt; } private void calcolaElencoFotoExt(long range) { boolean debug = false; DBAdapter.printDebug(debug, "updateElencoFotoExt"); if (getId_selfie() == 0L || getElencoFoto().isEmpty() || range <= 0L) return; String s_sql_find = "SELECT DISTINCT f2.filename FROM foto f1 JOIN foto f2 ON f1.id_evento = f2.id_evento AND f1.id_puntofoto = f2.id_puntofoto AND ABS(TIME_TO_SEC(f1.tempo) - TIME_TO_SEC(f2.tempo)) <=" + range; String s_sql_order = " order by f2.filename"; WcString wc = new WcString(); wc.addWc("f1.id_evento=" + getId_evento()); wc.addWc("f1.filename IN (" + convertToSqlInList(getElencoFoto()) + ")"); DBAdapter.printDebug(debug, "updateElencoFotoExt: " + s_sql_find + wc.toString() + s_sql_order); try { PreparedStatement stmt = getConn().prepareStatement(s_sql_find + s_sql_find + wc.toString()); ResultSet rst = stmt.executeQuery(); StringBuilder sb = new StringBuilder(); while (rst.next()) { if (sb.length() > 0) sb.append(","); String filename = rst.getString("filename"); sb.append(filename); } updateElencoFotoExt(sb.toString(), range); DBAdapter.printDebug(debug, "updateElencoFotoExt salvato: " + sb.toString()); } catch (SQLException e) { removeCPConnection(); handleDebug(e); } } public ResParm updateElencoFotoExt(String l_elencoFotoExt, long l_rangeExt) { boolean debug = false; if (getId_evento() == 0L) return new ResParm(false, "Evento con id a 0"); DBAdapter.printDebug(debug, "UPDATE SELFIE SET elencoFotoExt='" + l_elencoFotoExt + "', rangeExt=" + l_rangeExt + " where id_selfie=" + getId_selfie()); ResParm rp = update("UPDATE SELFIE SET elencoFotoExt='" + l_elencoFotoExt + "', rangeExt=" + l_rangeExt + " where id_selfie=" + getId_selfie()); if (rp.getStatus()) setElencoFotoExt(l_elencoFotoExt); DBAdapter.printDebug(debug, "SALVATAGGIO rp: " + rp.getMsg()); return rp; } public static String convertToSqlInList(String commaSeparatedFilenames) { return (String)Arrays.stream(commaSeparatedFilenames.split(",")).map(String::trim).map(s -> "'" + s + "'") .collect(Collectors.joining(", ")); } public void setElencoFotoExt(String elencoFotoExt) { this.elencoFotoExt = elencoFotoExt; } protected void fillFields(ResultSet rst) { super.fillFields(rst); try { if (isColumnInResultSet(rst, "elencoFotoExt")) setElencoFotoExt(rst.getString("elencoFotoExt")); } catch (SQLException e) { e.printStackTrace(); } } public long getRangeExt() { return this.rangeExt; } public void setRangeExt(long rangeExt) { this.rangeExt = rangeExt; } @Deprecated public ResParm updateElencoFoto(String l_updateElencoFoto) { if (getId_evento() == 0L) return new ResParm(false, "Evento con id a 0"); ResParm rp = update("UPDATE SELFIE SET elencoFoto='" + l_updateElencoFoto + "' where id_selfie=" + getId_selfie()); if (rp.getStatus()) setElencoFoto(l_updateElencoFoto); return rp; } }