Version 2.1 détection des visages
This commit is contained in:
parent
098cb5142a
commit
c59ec9bbf8
23
README.md
23
README.md
@ -1,5 +1,9 @@
|
|||||||
# photo_mem_cv
|
# photo_mem_cv
|
||||||
|
|
||||||
|
Version 2.1 juin 2021 refonte en une seule application
|
||||||
|
amélioration saisie des fichiers
|
||||||
|
ajout fonction modification des personnes
|
||||||
|
|
||||||
Outil web de sauvegarde des noms des personnes sur les photos et d'identification automatique des visages.
|
Outil web de sauvegarde des noms des personnes sur les photos et d'identification automatique des visages.
|
||||||
|
|
||||||
Fait à l'origine pour redonner vie à des photos anciennes, principalement des photos de mariage ou de classe.
|
Fait à l'origine pour redonner vie à des photos anciennes, principalement des photos de mariage ou de classe.
|
||||||
@ -9,17 +13,22 @@ Ce programme peut être utilisé aussi pour vos photos de classe, équipe de foo
|
|||||||
|
|
||||||
Utilisation :
|
Utilisation :
|
||||||
Mettez vos photos à traiter dans un répertoire, avec le programme Photo_mem_cv et les fichiers opencv.js et haarcascade*.xml
|
Mettez vos photos à traiter dans un répertoire, avec le programme Photo_mem_cv et les fichiers opencv.js et haarcascade*.xml
|
||||||
Lancer la page photo_mem_cv.html dans un navigateur, c'est avec firefox que ça marche le mieux. je crois que chromium passe mais IE pas du tout.
|
Lancer la page photo_mem.html dans un navigateur, c'est avec firefox que ça marche le mieux. je crois que chromium passe mais IE pas du tout.
|
||||||
- Bouton "Détection des visages" : selectionnez un fichier image et un fichier haarcascade. Le programme affiche tous les visages détectés et crée un fichier xml, du même nom que l'image, qui répertorie les coordonnées des visages trouvés. Pour modifier les noms, vous devrez éditer le xml, car la fonction "modification" n'est pas encore faite.
|
Pour commencer, cliquez sur le bouton bleu "choix de la photo", trois cas possibles :
|
||||||
- Bouton "Choix de la photo : saisir un fichier image et un fichier xml, celui créé avec le bouton "Détection", ou un ancien fichier à modifier, ou le fichier photo_init.xml pour une première utilisation.
|
- Sélection d'un seul fichier, ce doit être une image, ajoutez des personnes en cliquant au centre du visage (le nez) et remplissez le petit formulaire.
|
||||||
Cliquez sur le nez d'un personnage, et remplissez le petit formulaire.
|
|
||||||
|
- "Détection des visages" : selectionnez un fichier image et un fichier haarcascade.xml. Le programme affiche tous les visages détectés et crée un fichier xml, du même nom que l'image, qui répertorie les coordonnées des visages trouvés. Pour modifier les noms, vous devrez éditer le xml ... en attendant la fonction "modification" qui n'est pas encore terminée.
|
||||||
|
|
||||||
|
- Modification d'un fichier existant : saisir un fichier image et un fichier xml, celui créé précédemment en détection, ou un ancien fichier à modifier.
|
||||||
|
|
||||||
Quand vous avez terminé de remplir et de positionner vos étiquettes, n'oubliez pas d'enregistrer le xml. Choisissez le même répertoire que la photo, le nom donné au xml est le même que celui de la photo. Il écrase le fichier en cours.
|
Quand vous avez terminé de remplir et de positionner vos étiquettes, n'oubliez pas d'enregistrer le xml. Choisissez le même répertoire que la photo, le nom donné au xml est le même que celui de la photo. Il écrase le fichier en cours.
|
||||||
Attention, il n'y a pas de sauvegarde automatique, et si vous oubliez de sauvegarder, tout est perdu !
|
Attention, il n'y a pas de sauvegarde automatique, et si vous oubliez de sauvegarder, tout est perdu !
|
||||||
|
|
||||||
Reste à faire :
|
Reste à faire :
|
||||||
modifier une personne
|
modifier une personne - en cours ...
|
||||||
saisir / modifier le titre (actuellement, il faut le saisir dans le fichier xml)
|
saisir / modifier le titre - en cours ...
|
||||||
adapter taille étiquettes à la résolution de l'image
|
adapter la taille des étiquettes et du cercle à la résolution de l'image
|
||||||
|
modifier la couleur des étiquettes et du texte
|
||||||
paramétrer un peu mieux toutes les valeurs de positionnement qui sont en dur.
|
paramétrer un peu mieux toutes les valeurs de positionnement qui sont en dur.
|
||||||
éviter d'avoir à re-saisir les noms que l'on retrouve sur plusieurs photos - pas facile simplement
|
éviter d'avoir à re-saisir les noms que l'on retrouve sur plusieurs photos - pas facile simplement
|
||||||
reconnaissance faciale pour retrouver les mêmes personnages sur plusieurs photos
|
reconnaissance faciale pour retrouver les mêmes personnages sur plusieurs photos
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<photo>
|
|
||||||
<titre></titre>
|
|
||||||
<date></date>
|
|
||||||
<lieu></lieu>
|
|
||||||
<auteur></auteur>
|
|
||||||
<commentaire></commentaire>
|
|
||||||
|
|
||||||
</photo>
|
|
362
photo_mem.html
362
photo_mem.html
@ -1,6 +1,13 @@
|
|||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<!-- Photo_mem v1.6
|
<!-- Photo_mem Version 2.1
|
||||||
Copyright © 2017-2021 J. PLISSON -->
|
Copyright © 2017-2021 J. PLISSON
|
||||||
|
Licence AGPL v3.0+
|
||||||
|
|
||||||
|
2.0 mai 2021 ajout détection de visages
|
||||||
|
2.1 juin 2021 refonte en une seule application
|
||||||
|
amélioration saisie des fichiers
|
||||||
|
ajout fonction modification des personnes
|
||||||
|
-->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
@ -11,6 +18,19 @@ circle {
|
|||||||
stroke: black;
|
stroke: black;
|
||||||
stroke-width: 2;
|
stroke-width: 2;
|
||||||
}
|
}
|
||||||
|
#bouton_image {background-color:blue;color:white;height: 30px;}
|
||||||
|
#menu_modif {
|
||||||
|
display: block;
|
||||||
|
color: black;
|
||||||
|
background-color: gainsboro;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
width: 80px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
#ajout {
|
#ajout {
|
||||||
border:2px solid red;
|
border:2px solid red;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@ -44,24 +64,14 @@ circle {
|
|||||||
left:-200px;
|
left:-200px;
|
||||||
top: 100px;
|
top: 100px;
|
||||||
}
|
}
|
||||||
#menu_modif {
|
|
||||||
display: block;
|
|
||||||
color: black;
|
|
||||||
background-color: gainsboro;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 2px solid;
|
|
||||||
border-radius: 6px;
|
|
||||||
text-align: center;
|
|
||||||
position: absolute;
|
|
||||||
width: 80px;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<input id="file" multiple type="file" class=cotecote onChange="lecfic(this.files);"/>
|
<input id="fichiers" multiple type="file" class=cotecote style="display:none"/>
|
||||||
|
<button id="bouton_image" onclick="fichiers.click()" title="Charger une image et le XML associé" >Choix de la photo</button>
|
||||||
<input id="file" type="button" class=cotecote value="Enregistrer xml" onclick="enregistrer_fichier(enreg_xml)"/>
|
<input id="file" type="button" class=cotecote value="Enregistrer xml" onclick="enregistrer_fichier(enreg_xml)"/>
|
||||||
<input id="file" type="button" class=cotecote value="Enregistrer image " onclick="image_finale()"/>
|
<input id="file" type="button" class=cotecote value="Enregistrer image " onclick="image_finale()"/>
|
||||||
|
<p id="status" class=cotecote >OpenCV.js chargement en cours...</p>
|
||||||
|
|
||||||
<div style="position: relative; ">
|
<div style="position: relative; ">
|
||||||
<img src="" id="ima_fond" style="position: absolute; left: 0; top: 0; z-index: 0;">
|
<img src="" id="ima_fond" style="position: absolute; left: 0; top: 0; z-index: 0;">
|
||||||
@ -72,7 +82,7 @@ circle {
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div id="ajout" class="invisible" style="position: relative; z-index: 1;">
|
<div id="ajout" class="invisible" style="position: relative; z-index: 1;">
|
||||||
<form name="ajout_personne">
|
<form name="ajout_personne" id="ajout_personne">
|
||||||
<center><font color="green">NOUVELLE PERSONNE</font></center>
|
<center><font color="green">NOUVELLE PERSONNE</font></center>
|
||||||
|
|
||||||
Nom : <INPUT type="text" name="nom" id="nom" autofocus><BR>
|
Nom : <INPUT type="text" name="nom" id="nom" autofocus><BR>
|
||||||
@ -80,76 +90,63 @@ circle {
|
|||||||
Prénom : <INPUT type="text" name="prénom" id="prenom"><BR>
|
Prénom : <INPUT type="text" name="prénom" id="prenom"><BR>
|
||||||
Année : <INPUT type="text" name="année" id="annee"><BR>
|
Année : <INPUT type="text" name="année" id="annee"><BR>
|
||||||
Note : <INPUT type="text" name="note" id="note"><BR>
|
Note : <INPUT type="text" name="note" id="note"><BR>
|
||||||
|
Titre photo : <INPUT type="text" name="titre" id="titre"><BR>
|
||||||
|
|
||||||
<INPUT type="reset" id="enreg" value="Ajouter" onClick=ajouter_personne_xml();>
|
<INPUT type="reset" id="enreg" value="Ajouter" onClick=ajouter_personne_xml("",souris_x,souris_y,"","");lecture_xml();>
|
||||||
<INPUT type="reset" value="Annuler" onClick='document.getElementById("ajout").className="invisible";'>
|
<INPUT type="reset" value="Annuler" onClick=document.getElementById("ajout").className="invisible";>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id="menu_modif" class="invisible">
|
<div id="menu_modif" class="invisible">
|
||||||
<div id="modifier" onClick="window.print();menu.style.visibility='hidden';">modifier </div>
|
<div id="modifier" onClick="modifier_personne();">modifier </div>
|
||||||
<div id="supprimer" onClick="supprimer_personne();menu.style.visibility='hidden';">supprimer</div>
|
<div id="supprimer" onClick="supprimer_personne();menu.style.visibility='hidden';">supprimer</div>
|
||||||
<div id="annuler" onClick="menu.style.visibility='hidden';">annuler</div>
|
<div id="annuler" onClick="menu.style.visibility='hidden';">annuler</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
var personnes=[],nom=[],nomjf=[],prenom=[],posx=[],posy=[],etx=[],ety=[], can_etiq=[];
|
var personnes=[],nom=[],nomjf=[],prenom=[],annee=[],note=[],posx=[],posy=[],etx=[],ety=[], can_etiq=[];
|
||||||
var ibac=0, tit={}, titre="";
|
var ibac=0, tit={}, titre="", fond=[];
|
||||||
|
var mode_saisie="true" // mode saisie true, mode modification false
|
||||||
var image = document.getElementById('ima_fond');
|
var image = document.getElementById('ima_fond');
|
||||||
var cercle = document.getElementById("cirsvg");
|
var cercle = document.getElementById("cirsvg");
|
||||||
var menu = document.getElementById("menu_modif");
|
var menu = document.getElementById("menu_modif");
|
||||||
|
var modif_titre = document.getElementById("nouveau_titre");
|
||||||
var cant = document.createElement("canvas");
|
var cant = document.createElement("canvas");
|
||||||
document.body.appendChild(cant);
|
document.body.appendChild(cant);
|
||||||
|
|
||||||
|
let inputElement = document.getElementById('fichiers');
|
||||||
|
inputElement.addEventListener('change', (e) => {
|
||||||
|
lecfic(e.target.files)
|
||||||
|
}, false);
|
||||||
|
|
||||||
function lecfic(fichier) {
|
function lecfic(fichier) {
|
||||||
i_xml=0;
|
nb_fichier=fichier.length
|
||||||
if (fichier.length==2) {
|
var i_xml=1, i_img=0;
|
||||||
for (var i = 0; i < fichier.length; i++) {
|
if (fichier[0].name.split('.').pop()=="xml") {i_xml=0; i_img=1};
|
||||||
var ext=fichier[i].name.split('.').pop();
|
|
||||||
if (ext=="xml") {i_xml=i};
|
|
||||||
} ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert("Choisissez deux fichiers : un .xml et un fichier image");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
i_img=((i_xml-1)<0 ? 1 : 0);
|
|
||||||
var fichier_xml=fichier[i_xml];
|
|
||||||
fond=fichier[i_img];
|
|
||||||
var src=fichier[i_img].name.substring(0,fichier[i_img].name.indexOf("."));
|
var src=fichier[i_img].name.substring(0,fichier[i_img].name.indexOf("."));
|
||||||
enreg_xml=src+".xml"
|
enreg_xml=src+".xml"
|
||||||
enreg_noms=src+"_noms.png"
|
enreg_noms=src+"_noms.png"
|
||||||
|
fichier_xml=fichier[i_xml];
|
||||||
|
fond=fichier[i_img];
|
||||||
|
affiche_fond();
|
||||||
|
|
||||||
|
if (nb_fichier==1) {creation_data_xml(); lecture_xml(); return} // Un seul fichier sélectionné : l'image à traiter
|
||||||
|
|
||||||
|
if (fichier_xml.name.startsWith("haar")) {creation_data_xml(); detection_de_visages();return} // deux fichiers selectionnés : l'image et haarcascade.xml
|
||||||
|
|
||||||
|
// deux fichiers selectionnés : l'image et le xml du même nom
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
reader.onload = function(evt) {lecture(evt.target.result);};
|
reader.onload = function(evt) {lecture(evt.target.result);};
|
||||||
reader.readAsText(fichier_xml);
|
reader.readAsText(fichier_xml);
|
||||||
|
|
||||||
function lecture(text) {
|
function lecture(text) {
|
||||||
var parser = new DOMParser();
|
var parser = new DOMParser();
|
||||||
data_xml = parser.parseFromString(text,"text/xml");
|
data_xml = parser.parseFromString(text,"text/xml");
|
||||||
affiche_fond();
|
lecture_xml();
|
||||||
lecture_xml();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function lecture_xml() {
|
|
||||||
personnes = data_xml.documentElement.getElementsByTagName("personne");
|
// Chargement et affichage de l'image background
|
||||||
tit = data_xml.documentElement.getElementsByTagName("titre")[0];
|
|
||||||
titre=tit.textContent
|
|
||||||
nb_pers=personnes.length
|
|
||||||
for (var i = 0; i < nb_pers; i++) {
|
|
||||||
nom[i] = personnes[i].getElementsByTagName( "nom")[0].textContent;
|
|
||||||
if (personnes[i].getElementsByTagName( "nom_jeune_fille")[0]) {
|
|
||||||
nomjf[i] = personnes[i].getElementsByTagName( "nom_jeune_fille")[0].textContent};
|
|
||||||
prenom[i] = personnes[i].getElementsByTagName( "prenom")[0].textContent;
|
|
||||||
posx[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['posx'].value);
|
|
||||||
posy[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['posy'].value);
|
|
||||||
etx[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['etx'].value);
|
|
||||||
ety[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['ety'].value);
|
|
||||||
}
|
|
||||||
if (titre!=='') {affiche_titre()}
|
|
||||||
else {affiche_etiquette()} ;
|
|
||||||
};
|
|
||||||
// Chargement et dessin de l'image background
|
|
||||||
function affiche_fond() {
|
function affiche_fond() {
|
||||||
var read_fond = new FileReader();
|
var read_fond = new FileReader();
|
||||||
read_fond.addEventListener("load", function (evt) {
|
read_fond.addEventListener("load", function (evt) {
|
||||||
@ -158,10 +155,32 @@ function affiche_fond() {
|
|||||||
read_fond.readAsDataURL(fond);
|
read_fond.readAsDataURL(fond);
|
||||||
}
|
}
|
||||||
|
|
||||||
function affiche_titre() {
|
function lecture_xml() {
|
||||||
|
tit = data_xml.documentElement.getElementsByTagName("titre")[0];
|
||||||
|
titre=tit.textContent
|
||||||
|
personnes = data_xml.documentElement.getElementsByTagName("personne");
|
||||||
|
nb_pers=personnes.length
|
||||||
|
for (var i = 0; i < nb_pers; i++) {
|
||||||
|
nom[i] = personnes[i].getElementsByTagName( "nom")[0].textContent;
|
||||||
|
if (personnes[i].getElementsByTagName( "nom_jeune_fille")[0]) {
|
||||||
|
nomjf[i] = personnes[i].getElementsByTagName( "nom_jeune_fille")[0].textContent;
|
||||||
|
}
|
||||||
|
prenom[i] = personnes[i].getElementsByTagName( "prenom")[0].textContent;
|
||||||
|
annee[i] = personnes[i].getElementsByTagName( "annee_naiss")[0].textContent;
|
||||||
|
note[i] = personnes[i].getElementsByTagName( "note")[0].textContent;
|
||||||
|
posx[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['posx'].value);
|
||||||
|
posy[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['posy'].value);
|
||||||
|
etx[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['etx'].value);
|
||||||
|
ety[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['ety'].value);
|
||||||
|
}
|
||||||
|
if (titre!=='') {affiche_titre(titre)}
|
||||||
|
affiche_etiquette() ;
|
||||||
|
};
|
||||||
|
|
||||||
|
function affiche_titre(titre_photo) {
|
||||||
cant.className="tit";
|
cant.className="tit";
|
||||||
cant.height=23;
|
cant.height=23;
|
||||||
var taille=titre.length;
|
var taille=titre_photo.length;
|
||||||
cant.width=taille*12;
|
cant.width=taille*12;
|
||||||
tx = parseFloat(tit.attributes['titx'].value);
|
tx = parseFloat(tit.attributes['titx'].value);
|
||||||
ty = parseFloat(tit.attributes['tity'].value);
|
ty = parseFloat(tit.attributes['tity'].value);
|
||||||
@ -170,9 +189,8 @@ function affiche_titre() {
|
|||||||
titre_ctx = cant.getContext("2d");
|
titre_ctx = cant.getContext("2d");
|
||||||
titre_ctx.font = '21px Arial';
|
titre_ctx.font = '21px Arial';
|
||||||
titre_ctx.fillStyle = 'Maroon';
|
titre_ctx.fillStyle = 'Maroon';
|
||||||
titre_ctx.fillText(titre, 20, 18);
|
titre_ctx.fillText(titre_photo, 20, 18);
|
||||||
|
affiche_etiquette() ;
|
||||||
affiche_etiquette();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function affiche_etiquette() {
|
function affiche_etiquette() {
|
||||||
@ -190,7 +208,7 @@ function affiche_etiquette() {
|
|||||||
etiq_ctx = can_etiq[i].getContext("2d");
|
etiq_ctx = can_etiq[i].getContext("2d");
|
||||||
var taille=Math.max(nom[i].length,prenom[i].length,nomjf[i].length+5);
|
var taille=Math.max(nom[i].length,prenom[i].length,nomjf[i].length+5);
|
||||||
can_etiq[i].width=taille*7+10
|
can_etiq[i].width=taille*7+10
|
||||||
if (nomjf[i].length>1) {can_etiq[i].height=45};
|
if (nomjf[i].replace(/\t/g, '').length>1) {can_etiq[i].height=45};
|
||||||
etiq_ctx.font = '13px Arial';
|
etiq_ctx.font = '13px Arial';
|
||||||
etiq_ctx.fillStyle = 'chocolate';
|
etiq_ctx.fillStyle = 'chocolate';
|
||||||
can_etiq[i].style.left = etx[i] + "px";
|
can_etiq[i].style.left = etx[i] + "px";
|
||||||
@ -199,7 +217,7 @@ function affiche_etiquette() {
|
|||||||
etiq_ctx.fillText(prenom[i], 7, 25);
|
etiq_ctx.fillText(prenom[i], 7, 25);
|
||||||
if (nomjf[i].length>1) {etiq_ctx.fillText("née : "+nomjf[i], 7, 38)};
|
if (nomjf[i].length>1) {etiq_ctx.fillText("née : "+nomjf[i], 7, 38)};
|
||||||
};
|
};
|
||||||
gestion_souris(); // enregistre la position de l'étiquette
|
gestion_souris();
|
||||||
};
|
};
|
||||||
|
|
||||||
function gestion_souris() {
|
function gestion_souris() {
|
||||||
@ -238,6 +256,128 @@ function supprimer_personne() {
|
|||||||
cercle.style.visibility="hidden";
|
cercle.style.visibility="hidden";
|
||||||
lecture_xml();
|
lecture_xml();
|
||||||
}
|
}
|
||||||
|
function creation_data_xml() {
|
||||||
|
var x, i;
|
||||||
|
var txt = "";
|
||||||
|
var text = "<photo>" +
|
||||||
|
"<titre titx='50px' tity='50px'>Titre "+ fond.name + "</titre>" +
|
||||||
|
"<date> </date>" +
|
||||||
|
"<lieu> </lieu>" +
|
||||||
|
"<commentaire> </commentaire>" +
|
||||||
|
"</photo>";
|
||||||
|
|
||||||
|
var parser_face = new DOMParser();
|
||||||
|
data_xml = parser_face.parseFromString(text,"text/xml");
|
||||||
|
// documentElement always represents the root node
|
||||||
|
x = data_xml.documentElement.childNodes;
|
||||||
|
for (i = 0; i < x.length ;i++) {
|
||||||
|
txt += x[i].nodeName + ": " + x[i].childNodes[0].nodeValue + "<br>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function detection_de_visages() {
|
||||||
|
// alert pour temporiser
|
||||||
|
alert("Ok pour continuer")
|
||||||
|
src = cv.imread(ima_fond);
|
||||||
|
gray = new cv.Mat();
|
||||||
|
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||||
|
chargement_haarcascade();
|
||||||
|
}
|
||||||
|
function chargement_haarcascade() {
|
||||||
|
var reader_haar = new FileReader();
|
||||||
|
reader_haar.onload = function(ev) {
|
||||||
|
function str2ab(text) {
|
||||||
|
return new TextEncoder().encode(text);
|
||||||
|
}
|
||||||
|
faceCascadeFile = fichier_xml.name;
|
||||||
|
let data=str2ab(reader_haar.result)
|
||||||
|
cv.FS_createDataFile('/', faceCascadeFile, data, true, false, false);
|
||||||
|
detect_faces();
|
||||||
|
};
|
||||||
|
reader_haar.readAsText(fichier_xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
function detect_faces() {
|
||||||
|
|
||||||
|
let faces = new cv.RectVector();
|
||||||
|
let faceCascade = new cv.CascadeClassifier();
|
||||||
|
// load pre-trained classifiers
|
||||||
|
faceCascade.load(faceCascadeFile);
|
||||||
|
// detect faces
|
||||||
|
let msize = new cv.Size(0, 0);
|
||||||
|
faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, msize, msize);
|
||||||
|
console.log("Il y a "+ faces.size()+" visage(s)")
|
||||||
|
for (let i = 0; i < faces.size(); ++i) {
|
||||||
|
ajouter_personne_xml("nom_"+parseInt(i)+" ",faces.get(i).x,faces.get(i).y,faces.get(i).width,faces.get(i).height)
|
||||||
|
}
|
||||||
|
// cv.imshow('ima_fond', src);
|
||||||
|
src.delete(); gray.delete(); faceCascade.delete();
|
||||||
|
faces.delete();
|
||||||
|
lecture_xml();
|
||||||
|
|
||||||
|
;}
|
||||||
|
function ajouter_personne_xml(nom_face,fx,fy,fw,fh) {
|
||||||
|
var nomform=nom_face
|
||||||
|
var nomjfform=""
|
||||||
|
var prenomform=""
|
||||||
|
var anneeform=""
|
||||||
|
var noteform=""
|
||||||
|
var posxx=fx+fw/2
|
||||||
|
var posyy=fy+fh/2
|
||||||
|
var etxx=fx+10
|
||||||
|
var etyy=fy+fh*2
|
||||||
|
document.getElementById('ajout').className='invisible';
|
||||||
|
|
||||||
|
if (!nom_face) {
|
||||||
|
posxx=fx
|
||||||
|
posyy=fy
|
||||||
|
etxx=fx-30
|
||||||
|
etyy=fy+80
|
||||||
|
nomform=document.getElementById("nom").value
|
||||||
|
nomjfform=document.getElementById("nom_jeune_fille").value
|
||||||
|
prenomform=document.getElementById("prenom").value
|
||||||
|
anneeform=document.getElementById("annee").value
|
||||||
|
noteform=document.getElementById("note").value
|
||||||
|
}
|
||||||
|
// création d'un nouvel élément <personne> dans data_xml
|
||||||
|
var personne_ = data_xml.createElement("personne");
|
||||||
|
var nom_ = data_xml.createElement("nom");
|
||||||
|
nom_.appendChild(data_xml.createTextNode(nomform));
|
||||||
|
var nom_jf_ = data_xml.createElement("nom_jeune_fille");
|
||||||
|
nom_jf_.appendChild(data_xml.createTextNode(nomjfform));
|
||||||
|
var prenom_ = data_xml.createElement("prenom");
|
||||||
|
prenom_.appendChild(data_xml.createTextNode(prenomform));
|
||||||
|
var annee_ = data_xml.createElement("annee_naiss");
|
||||||
|
annee_.appendChild(data_xml.createTextNode(anneeform));
|
||||||
|
var note_ = data_xml.createElement("note");
|
||||||
|
note_.appendChild(data_xml.createTextNode(noteform));
|
||||||
|
var position_ = data_xml.createElement("position");
|
||||||
|
position_.setAttribute("posx", posxx);
|
||||||
|
position_.setAttribute("posy", posyy);
|
||||||
|
position_.setAttribute("etx", etxx);
|
||||||
|
position_.setAttribute("ety", etyy);
|
||||||
|
personne_.appendChild(nom_);
|
||||||
|
personne_.appendChild(nom_jf_);
|
||||||
|
personne_.appendChild(prenom_);
|
||||||
|
personne_.appendChild(annee_);
|
||||||
|
personne_.appendChild(note_);
|
||||||
|
personne_.appendChild(position_);
|
||||||
|
data_xml.getElementsByTagName("photo")[0].appendChild(personne_)
|
||||||
|
};
|
||||||
|
|
||||||
|
function modifier_personne() {
|
||||||
|
mode_saisie="false";
|
||||||
|
afficher_formulaire(this);
|
||||||
|
document.getElementById('nom').setAttribute('value', nom[ibac]);
|
||||||
|
document.getElementById('nom_jeune_fille').setAttribute('value', nomjf[ibac]);
|
||||||
|
document.getElementById('prenom').setAttribute('value', prenom[ibac]);
|
||||||
|
document.getElementById('annee').setAttribute('value', annee[ibac]);
|
||||||
|
document.getElementById('note').setAttribute('value', note[ibac]);
|
||||||
|
document.getElementById('titre').setAttribute('value', titre);
|
||||||
|
menu.style.visibility='hidden';
|
||||||
|
document.getElementById("enreg").style.visibility="hidden";
|
||||||
|
alert("Fonction en cours de développement")
|
||||||
|
};
|
||||||
|
|
||||||
function position_souris(canvas, evt) {
|
function position_souris(canvas, evt) {
|
||||||
var rect = canvas.getBoundingClientRect();
|
var rect = canvas.getBoundingClientRect();
|
||||||
@ -260,7 +400,6 @@ function tracer_cercle(e) {
|
|||||||
|
|
||||||
if (dist2 < rayon2) {
|
if (dist2 < rayon2) {
|
||||||
ibac=i
|
ibac=i
|
||||||
bac=can_etiq[i].style.backgroundColor;
|
|
||||||
can_etiq[i].style.background = "palegreen"
|
can_etiq[i].style.background = "palegreen"
|
||||||
cercle.setAttribute("cx",posx[i]);
|
cercle.setAttribute("cx",posx[i]);
|
||||||
cercle.setAttribute("cy",posy[i]);
|
cercle.setAttribute("cy",posy[i]);
|
||||||
@ -275,58 +414,31 @@ function tracer_cercle(e) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
cercle.style.visibility="hidden";
|
cercle.style.visibility="hidden";
|
||||||
can_etiq[ibac].style.backgroundColor = "oldlace";
|
if (nb_pers!=0) {can_etiq[ibac].style.backgroundColor = "oldlace";}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function afficher_formulaire(e) {
|
function afficher_formulaire(e) {
|
||||||
|
var formul=document.getElementById('ajout')
|
||||||
souris_x = position_souris(ima_fond, e).x ;
|
souris_x = position_souris(ima_fond, e).x ;
|
||||||
souris_y = position_souris(ima_fond, e).y;
|
souris_y = position_souris(ima_fond, e).y;
|
||||||
if (souris_y-document.getElementById('ajout').height<0) sourisy=50;
|
if (souris_y-document.getElementById('ajout').height<0) {sourisy=50};
|
||||||
document.getElementById('ajout').style.top=souris_y+40+"px";
|
formul.style.top=souris_y+40+"px";
|
||||||
document.getElementById('ajout').style.left=souris_x-80+"px";
|
formul.style.left=souris_x-80+"px";
|
||||||
setTimeout(function () { document.getElementById("nom").focus(); },10);
|
setTimeout(function () { document.getElementById("nom").focus(); },10);
|
||||||
document.getElementById('ajout').className='visible';
|
formul.className='visible';
|
||||||
|
|
||||||
|
// document.getElementById('ajout_personne').reset(); // ne fonctioone pas !
|
||||||
|
if (mode_saisie) {
|
||||||
|
document.getElementById('nom').setAttribute('value', "");
|
||||||
|
document.getElementById('nom_jeune_fille').setAttribute('value', "");
|
||||||
|
document.getElementById('prenom').setAttribute('value', "");
|
||||||
|
document.getElementById('annee').setAttribute('value', "");
|
||||||
|
document.getElementById('note').setAttribute('value', "");
|
||||||
|
}
|
||||||
|
mode_saisie="true";
|
||||||
};
|
};
|
||||||
|
|
||||||
function ajouter_personne_xml() {
|
|
||||||
// création d'un nouvel élément <personne> dans data_xml
|
|
||||||
var nomform=document.getElementById("nom").value
|
|
||||||
var nomjfform=document.getElementById("nom_jeune_fille").value
|
|
||||||
var prenomform=document.getElementById("prenom").value
|
|
||||||
var surnomform=""
|
|
||||||
var anneeform=document.getElementById("annee").value
|
|
||||||
var noteform=document.getElementById("note").value
|
|
||||||
document.getElementById('ajout').className='invisible';
|
|
||||||
console.log(nomform+" "+prenomform+" "+anneeform)
|
|
||||||
var personne_ = data_xml.createElement("personne");
|
|
||||||
var nom_ = data_xml.createElement("nom");
|
|
||||||
nom_.appendChild(data_xml.createTextNode(nomform));
|
|
||||||
var nom_jf_ = data_xml.createElement("nom_jeune_fille");
|
|
||||||
nom_jf_.appendChild(data_xml.createTextNode(nomjfform));
|
|
||||||
var prenom_ = data_xml.createElement("prenom");
|
|
||||||
prenom_.appendChild(data_xml.createTextNode(prenomform));
|
|
||||||
var surnom_ = data_xml.createElement("surnom");
|
|
||||||
surnom_.appendChild(data_xml.createTextNode(surnomform));
|
|
||||||
var annee_ = data_xml.createElement("annee_naiss");
|
|
||||||
annee_.appendChild(data_xml.createTextNode(anneeform));
|
|
||||||
var note_ = data_xml.createElement("note");
|
|
||||||
note_.appendChild(data_xml.createTextNode(noteform));
|
|
||||||
var position_ = data_xml.createElement("position");
|
|
||||||
position_.setAttribute("posx", souris_x);
|
|
||||||
position_.setAttribute("posy", souris_y);
|
|
||||||
position_.setAttribute("etx", souris_x-30);
|
|
||||||
position_.setAttribute("ety", souris_y+60);
|
|
||||||
personne_.appendChild(nom_);
|
|
||||||
personne_.appendChild(nom_jf_);
|
|
||||||
personne_.appendChild(prenom_);
|
|
||||||
personne_.appendChild(surnom_);
|
|
||||||
personne_.appendChild(annee_);
|
|
||||||
personne_.appendChild(note_);
|
|
||||||
personne_.appendChild(position_);
|
|
||||||
data_xml.getElementsByTagName("photo")[0].appendChild(personne_)
|
|
||||||
lecture_xml();
|
|
||||||
};
|
|
||||||
|
|
||||||
function misajour_xml(){
|
function misajour_xml(){
|
||||||
tit.setAttribute("titx",cant.style.left);
|
tit.setAttribute("titx",cant.style.left);
|
||||||
@ -343,12 +455,7 @@ function misajour_xml(){
|
|||||||
function enregistrer_fichier(fichier) {
|
function enregistrer_fichier(fichier) {
|
||||||
misajour_xml()
|
misajour_xml()
|
||||||
var texte_xml=(new XMLSerializer()).serializeToString(data_xml)
|
var texte_xml=(new XMLSerializer()).serializeToString(data_xml)
|
||||||
var reg = /(>)\s*(<)(\/*)/g;
|
texte_xml=formatXml(texte_xml)
|
||||||
// règle pour enlever id="etiqnn" dans les versions précédentes du fichier xml
|
|
||||||
var rex=/<personne(.*?)>/g;
|
|
||||||
texte_xml = texte_xml.replace(rex,'<personne>');
|
|
||||||
texte_xml = texte_xml.replace(/\r|\n/g, '');
|
|
||||||
texte_xml = texte_xml.replace(reg, '$1\r\n$2$3');
|
|
||||||
var blob = new Blob([texte_xml], {type: "text/plain;charset=utf-8"});
|
var blob = new Blob([texte_xml], {type: "text/plain;charset=utf-8"});
|
||||||
if (navigator.msSaveBlob) {
|
if (navigator.msSaveBlob) {
|
||||||
navigator.msSaveBlob(blob, fichier);
|
navigator.msSaveBlob(blob, fichier);
|
||||||
@ -363,6 +470,18 @@ function enregistrer_fichier(fichier) {
|
|||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatXml(xml, tab) { // tab = optional indent value, default is tab (\t)
|
||||||
|
var formatted = '', indent= '';
|
||||||
|
tab = tab || '\t';
|
||||||
|
xml.split(/>\s*</).forEach(function(node) {
|
||||||
|
if (node.match( /^\/\w/ )) indent = indent.substring(tab.length); // decrease indent by one 'tab'
|
||||||
|
formatted += indent + '<' + node + '>\r\n';
|
||||||
|
if (node.match( /^<?\w[^>]*[^\/]$/ )) indent += tab; // increase indent
|
||||||
|
});
|
||||||
|
return formatted.substring(1, formatted.length-3);
|
||||||
|
}
|
||||||
|
|
||||||
function image_finale() {
|
function image_finale() {
|
||||||
misajour_xml()
|
misajour_xml()
|
||||||
var decalx=5;
|
var decalx=5;
|
||||||
@ -382,7 +501,8 @@ function image_finale() {
|
|||||||
for (var i = 0; i < nb_pers; i++) {
|
for (var i = 0; i < nb_pers; i++) {
|
||||||
var taille=Math.max(nom[i].length,prenom[i].length,nomjf[i].length+5);
|
var taille=Math.max(nom[i].length,prenom[i].length,nomjf[i].length+5);
|
||||||
hauteur=30
|
hauteur=30
|
||||||
if (nomjf[i].length>1) {hauteur=45};
|
if (nomjf[i].replace(/\t/g, '').length>1) {hauteur=45};
|
||||||
|
// if (!nomjf[i].charCodeAt(1)==9) {hauteur=45};
|
||||||
roundedRect(imf_ctx,etx[i]-decalx,ety[i]-decaly,taille*7+10,hauteur,15,'oldlace','blue');
|
roundedRect(imf_ctx,etx[i]-decalx,ety[i]-decaly,taille*7+10,hauteur,15,'oldlace','blue');
|
||||||
imf_ctx.drawImage(can_etiq[i],etx[i]-decalx,ety[i]-decaly)
|
imf_ctx.drawImage(can_etiq[i],etx[i]-decalx,ety[i]-decaly)
|
||||||
}
|
}
|
||||||
@ -415,5 +535,11 @@ function image_finale() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
function onOpenCvReady() {
|
||||||
|
document.getElementById('status').innerHTML = 'OpenCV.js est chargé !';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script src="opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,544 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<!-- Photo_mem
|
|
||||||
Version 2.0 avec détection de visages
|
|
||||||
Copyright © 2017-2021 J. PLISSON
|
|
||||||
Licence AGPL v3.0+
|
|
||||||
-->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
circle {
|
|
||||||
fill: transparent;
|
|
||||||
stroke: black;
|
|
||||||
stroke-width: 2;
|
|
||||||
}
|
|
||||||
#bouton_image {background-color:green;color:white;height: 30px;}
|
|
||||||
#bouton_faces {background-color:blue;color:white;height: 30px;}
|
|
||||||
#menu_modif {
|
|
||||||
display: block;
|
|
||||||
color: black;
|
|
||||||
background-color: gainsboro;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 2px solid;
|
|
||||||
border-radius: 6px;
|
|
||||||
text-align: center;
|
|
||||||
position: absolute;
|
|
||||||
width: 80px;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
#ajout {
|
|
||||||
border:2px solid red;
|
|
||||||
border-radius: 10px;
|
|
||||||
top: 100px;
|
|
||||||
left: 200px;
|
|
||||||
padding-top: 0.5em;
|
|
||||||
padding-bottom: 0.5em;
|
|
||||||
padding-left: 1em;
|
|
||||||
background-color: Azure;
|
|
||||||
width: 230px;
|
|
||||||
}
|
|
||||||
#ajout input:focus {border: solid 2px green;}
|
|
||||||
.cotecote {display: inline;}
|
|
||||||
.visible { visibility:visible; }
|
|
||||||
.invisible { visibility:hidden; }
|
|
||||||
.etiq {
|
|
||||||
background-color:oldlace;
|
|
||||||
border:1px solid blue;
|
|
||||||
border-radius: 10px;
|
|
||||||
position:absolute;
|
|
||||||
font-family: Arial;
|
|
||||||
font-size: 13px;
|
|
||||||
left:-200px;
|
|
||||||
top: 100px;
|
|
||||||
}
|
|
||||||
.tit {
|
|
||||||
background-color:LightYellow;
|
|
||||||
border: 2px solid Yellow;
|
|
||||||
border-radius: 5px;
|
|
||||||
position:absolute;
|
|
||||||
left:-200px;
|
|
||||||
top: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<input id="file_image" multiple type="file" class=cotecote style="display:none"/>
|
|
||||||
<button id="bouton_image" onclick="file_image.click()" title="Charger une image et le XML associé" >Choix de la photo</button>
|
|
||||||
<input id="file" type="button" class=cotecote value="Enregistrer xml" onclick="enregistrer_fichier(enreg_xml)"/>
|
|
||||||
<input id="file" type="button" class=cotecote value="Enregistrer image " onclick="image_finale()"/>
|
|
||||||
<button id="bouton_faces" onclick="file_image.click()" title="Charger une image et le XML haarcascade">Détection des visages</button>
|
|
||||||
<p id="status" class=cotecote >OpenCV.js chargement en cours...</p>
|
|
||||||
|
|
||||||
<div style="position: relative; ">
|
|
||||||
<img src="" id="ima_fond" style="position: absolute; left: 0; top: 0; z-index: 0;">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<svg class="invisible" style="position: absolute" ;>
|
|
||||||
<circle id="cirsvg" cx="30" cy="30" r="28" />
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<div id="ajout" class="invisible" style="position: relative; z-index: 1;">
|
|
||||||
<form name="ajout_personne">
|
|
||||||
<center><font color="green">NOUVELLE PERSONNE</font></center>
|
|
||||||
|
|
||||||
Nom : <INPUT type="text" name="nom" id="nom" autofocus><BR>
|
|
||||||
Née : <INPUT type="text" name="nom_jf" id="nom_jeune_fille"><BR>
|
|
||||||
Prénom : <INPUT type="text" name="prénom" id="prenom"><BR>
|
|
||||||
Année : <INPUT type="text" name="année" id="annee"><BR>
|
|
||||||
Note : <INPUT type="text" name="note" id="note"><BR>
|
|
||||||
|
|
||||||
<INPUT type="reset" id="enreg" value="Ajouter" onClick=ajouter_personne_xml();>
|
|
||||||
<INPUT type="reset" value="Annuler" onClick=document.getElementById("ajout").className="invisible";>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div id="menu_modif" class="invisible">
|
|
||||||
<div id="modifier" onClick="window.print();menu.style.visibility='hidden';">modifier </div>
|
|
||||||
<div id="supprimer" onClick="supprimer_personne();menu.style.visibility='hidden';">supprimer</div>
|
|
||||||
<div id="annuler" onClick="menu.style.visibility='hidden';">annuler</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
var personnes=[],nom=[],nomjf=[],prenom=[],posx=[],posy=[],etx=[],ety=[], can_etiq=[];
|
|
||||||
var ibac=0, tit={}, titre="";
|
|
||||||
var image = document.getElementById('ima_fond');
|
|
||||||
var cercle = document.getElementById("cirsvg");
|
|
||||||
var menu = document.getElementById("menu_modif");
|
|
||||||
var cant = document.createElement("canvas");
|
|
||||||
document.body.appendChild(cant);
|
|
||||||
let inputElement = document.getElementById('file_image');
|
|
||||||
inputElement.addEventListener('change', (e) => {
|
|
||||||
lecfic(e.target.files)
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
function lecfic(fichier) {
|
|
||||||
i_xml=0;
|
|
||||||
if (fichier.length==2) {
|
|
||||||
for (var i = 0; i < fichier.length; i++) {
|
|
||||||
var ext=fichier[i].name.split('.').pop();
|
|
||||||
if (ext=="xml") {i_xml=i};
|
|
||||||
} ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
alert("Choisissez deux fichiers : un .xml et un fichier image");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
i_img=((i_xml-1)<0 ? 1 : 0);
|
|
||||||
fichier_xml=fichier[i_xml];
|
|
||||||
fond=fichier[i_img];
|
|
||||||
var src=fichier[i_img].name.substring(0,fichier[i_img].name.indexOf("."));
|
|
||||||
enreg_xml=src+".xml"
|
|
||||||
enreg_noms=src+"_noms.png"
|
|
||||||
|
|
||||||
if (fichier_xml.name.startsWith("haar")) { detection_de_visages()}
|
|
||||||
else {
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onload = function(evt) {lecture(evt.target.result);};
|
|
||||||
reader.readAsText(fichier_xml);
|
|
||||||
|
|
||||||
function lecture(text) {
|
|
||||||
var parser = new DOMParser();
|
|
||||||
data_xml = parser.parseFromString(text,"text/xml");
|
|
||||||
affiche_fond();
|
|
||||||
lecture_xml();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function detection_de_visages() {
|
|
||||||
affiche_fond();
|
|
||||||
alert("Ok pour continuer")
|
|
||||||
src = cv.imread(ima_fond);
|
|
||||||
|
|
||||||
// cv.imshow('canvasOutput', src);
|
|
||||||
gray = new cv.Mat();
|
|
||||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
|
||||||
// cv.imshow('canvasOutput', gray);
|
|
||||||
chargement_haarcascade();
|
|
||||||
}
|
|
||||||
function chargement_haarcascade() {
|
|
||||||
var reader_haar = new FileReader();
|
|
||||||
reader_haar.onload = function(ev) {
|
|
||||||
function str2ab(text) {
|
|
||||||
return new TextEncoder().encode(text);
|
|
||||||
}
|
|
||||||
faceCascadeFile = 'haarcascade_frontalface_alt2.xml';
|
|
||||||
let data=str2ab(reader_haar.result)
|
|
||||||
//console.log("array "+data);
|
|
||||||
cv.FS_createDataFile('/', faceCascadeFile, data, true, false, false);
|
|
||||||
creation_data_xml()
|
|
||||||
};
|
|
||||||
reader_haar.readAsText(fichier_xml);
|
|
||||||
}
|
|
||||||
|
|
||||||
function creation_data_xml() {
|
|
||||||
var x, i;
|
|
||||||
var txt = "";
|
|
||||||
var text = "<photo>" +
|
|
||||||
"<titre titx='50px' tity='50px'>Titre "+ fond.name + "</titre>" +
|
|
||||||
"<date> </date>" +
|
|
||||||
"<lieu> </lieu>" +
|
|
||||||
"<commentaire> </commentaire>" +
|
|
||||||
"</photo>";
|
|
||||||
|
|
||||||
var parser_face = new DOMParser();
|
|
||||||
data_xml = parser_face.parseFromString(text,"text/xml");
|
|
||||||
// documentElement always represents the root node
|
|
||||||
x = data_xml.documentElement.childNodes;
|
|
||||||
for (i = 0; i < x.length ;i++) {
|
|
||||||
txt += x[i].nodeName + ": " + x[i].childNodes[0].nodeValue + "<br>";
|
|
||||||
}
|
|
||||||
let faces = new cv.RectVector();
|
|
||||||
let faceCascade = new cv.CascadeClassifier();
|
|
||||||
// load pre-trained classifiers
|
|
||||||
faceCascade.load(faceCascadeFile);
|
|
||||||
// detect faces
|
|
||||||
let msize = new cv.Size(0, 0);
|
|
||||||
faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, msize, msize);
|
|
||||||
console.log("Il y a "+ faces.size()+" visage(s)")
|
|
||||||
for (let i = 0; i < faces.size(); ++i) {
|
|
||||||
ajouter_face_xml("nom_"+parseInt(i)+" ",faces.get(i).x,faces.get(i).y,faces.get(i).width,faces.get(i).height)
|
|
||||||
}
|
|
||||||
// cv.imshow('ima_fond', src);
|
|
||||||
src.delete(); gray.delete(); faceCascade.delete();
|
|
||||||
faces.delete();
|
|
||||||
lecture_xml();
|
|
||||||
|
|
||||||
;}
|
|
||||||
|
|
||||||
// detect faces
|
|
||||||
|
|
||||||
function ajouter_face_xml(nom_face,fx,fy,fw,fh) {
|
|
||||||
// création d'un nouvel élément <personne> dans data_xml
|
|
||||||
var personne_ = data_xml.createElement("personne");
|
|
||||||
var nom_ = data_xml.createElement("nom");
|
|
||||||
nom_.appendChild(data_xml.createTextNode(nom_face));
|
|
||||||
var nom_jf_ = data_xml.createElement("nom_jeune_fille");
|
|
||||||
nom_jf_.appendChild(data_xml.createTextNode(""));
|
|
||||||
var prenom_ = data_xml.createElement("prenom");
|
|
||||||
prenom_.appendChild(data_xml.createTextNode("prenom"));
|
|
||||||
var surnom_ = data_xml.createElement("surnom");
|
|
||||||
surnom_.appendChild(data_xml.createTextNode(" "));
|
|
||||||
var annee_ = data_xml.createElement("annee_naiss");
|
|
||||||
annee_.appendChild(data_xml.createTextNode(" "));
|
|
||||||
var note_ = data_xml.createElement("note");
|
|
||||||
note_.appendChild(data_xml.createTextNode(" "));
|
|
||||||
var position_ = data_xml.createElement("position");
|
|
||||||
position_.setAttribute("posx", fx+fw/2);
|
|
||||||
position_.setAttribute("posy", fy+fh/2);
|
|
||||||
position_.setAttribute("etx", fx+10);
|
|
||||||
position_.setAttribute("ety", fy+fh*2);
|
|
||||||
personne_.appendChild(nom_);
|
|
||||||
personne_.appendChild(nom_jf_);
|
|
||||||
personne_.appendChild(prenom_);
|
|
||||||
personne_.appendChild(surnom_);
|
|
||||||
personne_.appendChild(annee_);
|
|
||||||
personne_.appendChild(note_);
|
|
||||||
personne_.appendChild(position_);
|
|
||||||
data_xml.getElementsByTagName("photo")[0].appendChild(personne_)
|
|
||||||
};
|
|
||||||
|
|
||||||
function lecture_xml() {
|
|
||||||
personnes = data_xml.documentElement.getElementsByTagName("personne");
|
|
||||||
tit = data_xml.documentElement.getElementsByTagName("titre")[0];
|
|
||||||
titre=tit.textContent
|
|
||||||
nb_pers=personnes.length
|
|
||||||
for (var i = 0; i < nb_pers; i++) {
|
|
||||||
nom[i] = personnes[i].getElementsByTagName( "nom")[0].textContent;
|
|
||||||
if (personnes[i].getElementsByTagName( "nom_jeune_fille")[0]) {
|
|
||||||
nomjf[i] = personnes[i].getElementsByTagName( "nom_jeune_fille")[0].textContent};
|
|
||||||
prenom[i] = personnes[i].getElementsByTagName( "prenom")[0].textContent;
|
|
||||||
posx[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['posx'].value);
|
|
||||||
posy[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['posy'].value);
|
|
||||||
etx[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['etx'].value);
|
|
||||||
ety[i] = parseFloat(personnes[i].getElementsByTagName( "position")[0].attributes['ety'].value);
|
|
||||||
}
|
|
||||||
if (titre!=='') {affiche_titre()}
|
|
||||||
else {affiche_etiquette()} ;
|
|
||||||
};
|
|
||||||
// Chargement et dessin de l'image background
|
|
||||||
function affiche_fond() {
|
|
||||||
var read_fond = new FileReader();
|
|
||||||
read_fond.addEventListener("load", function (evt) {
|
|
||||||
image.src = evt.target.result;
|
|
||||||
}, false);
|
|
||||||
read_fond.readAsDataURL(fond);
|
|
||||||
}
|
|
||||||
|
|
||||||
function affiche_titre() {
|
|
||||||
cant.className="tit";
|
|
||||||
cant.height=23;
|
|
||||||
var taille=titre.length;
|
|
||||||
cant.width=taille*12;
|
|
||||||
tx = parseFloat(tit.attributes['titx'].value);
|
|
||||||
ty = parseFloat(tit.attributes['tity'].value);
|
|
||||||
cant.style.left = tx + "px";
|
|
||||||
cant.style.top = ty + "px";
|
|
||||||
titre_ctx = cant.getContext("2d");
|
|
||||||
titre_ctx.font = '21px Arial';
|
|
||||||
titre_ctx.fillStyle = 'Maroon';
|
|
||||||
titre_ctx.fillText(titre, 20, 18);
|
|
||||||
|
|
||||||
affiche_etiquette();
|
|
||||||
}
|
|
||||||
|
|
||||||
function affiche_etiquette() {
|
|
||||||
// affichage du texte nom/prénom dans des canvas etiquette
|
|
||||||
rayon=28
|
|
||||||
for (var i = 0; i < nb_pers; i++) {
|
|
||||||
var id="can"+i;
|
|
||||||
if (document.getElementById(id)) continue ;
|
|
||||||
var canv = document.createElement("canvas");
|
|
||||||
canv.id=id;
|
|
||||||
document.body.appendChild(canv);
|
|
||||||
can_etiq[i] = document.getElementById(canv.id);
|
|
||||||
can_etiq[i].className="etiq";
|
|
||||||
can_etiq[i].height=30;
|
|
||||||
etiq_ctx = can_etiq[i].getContext("2d");
|
|
||||||
var taille=Math.max(nom[i].length,prenom[i].length,nomjf[i].length+5);
|
|
||||||
can_etiq[i].width=taille*7+10
|
|
||||||
//alert("nomjf ="+nomjf[i]+" code :"+nomjf[i].charCodeAt(1))
|
|
||||||
// if (!nomjf[i].charCodeAt(1)==9) {can_etiq[i].height=45};
|
|
||||||
if (nomjf[i].replace(/\t/g, '').length>1) {can_etiq[i].height=45};
|
|
||||||
etiq_ctx.font = '13px Arial';
|
|
||||||
etiq_ctx.fillStyle = 'chocolate';
|
|
||||||
can_etiq[i].style.left = etx[i] + "px";
|
|
||||||
can_etiq[i].style.top = ety[i] + "px";
|
|
||||||
etiq_ctx.fillText(nom[i], 7, 12);
|
|
||||||
etiq_ctx.fillText(prenom[i], 7, 25);
|
|
||||||
if (nomjf[i].length>1) {etiq_ctx.fillText("née : "+nomjf[i], 7, 38)};
|
|
||||||
};
|
|
||||||
gestion_souris(); // enregistre la position de l'étiquette
|
|
||||||
};
|
|
||||||
|
|
||||||
function gestion_souris() {
|
|
||||||
if (titre!=='') { // pour déplacer le titre
|
|
||||||
cant.addEventListener("mousedown", function(e){this.addEventListener("mousemove", deplace_etiquette);});
|
|
||||||
cant.addEventListener("mouseup", function(e){this.removeEventListener("mousemove", deplace_etiquette);});
|
|
||||||
}
|
|
||||||
for (var i = 0; i < nb_pers; i++) { // pour déplacer les étiquettes nom,prénom ...
|
|
||||||
can_etiq[i].addEventListener("mousedown", function(e){this.addEventListener("mousemove", deplace_etiquette);});
|
|
||||||
can_etiq[i].addEventListener("mouseup", function(e){this.removeEventListener("mousemove", deplace_etiquette);});
|
|
||||||
};
|
|
||||||
ima_fond.addEventListener('mousedown', afficher_formulaire); // pour afficher le formulaire de saisie personne
|
|
||||||
ima_fond.addEventListener('mousemove', tracer_cercle); // pour afficher cercle personne
|
|
||||||
cercle.addEventListener('contextmenu', function (e) { menu_modif(e); e.preventDefault();}, false); // menu modif personne
|
|
||||||
};
|
|
||||||
|
|
||||||
function deplace_etiquette(e){
|
|
||||||
e.target.style.top = e.pageY-15+"px";
|
|
||||||
e.target.style.left = e.pageX-30+"px";
|
|
||||||
};
|
|
||||||
|
|
||||||
function menu_modif(){
|
|
||||||
menu.style.left = parseFloat(cercle.getAttribute("cx"))+10 +"px";
|
|
||||||
menu.style.top = parseFloat(cercle.getAttribute("cy"))+40 +"px";
|
|
||||||
menu.style.visibility="visible";
|
|
||||||
}
|
|
||||||
|
|
||||||
function supprimer_personne() {
|
|
||||||
misajour_xml();
|
|
||||||
x = data_xml.getElementsByTagName("personne")[ibac];
|
|
||||||
x.parentNode.removeChild(x);
|
|
||||||
for (var i = 0; i < nb_pers; i++) {
|
|
||||||
x = can_etiq[i];
|
|
||||||
x.parentNode.removeChild(x);
|
|
||||||
};
|
|
||||||
cercle.style.visibility="hidden";
|
|
||||||
lecture_xml();
|
|
||||||
}
|
|
||||||
|
|
||||||
function position_souris(canvas, evt) {
|
|
||||||
var rect = canvas.getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
x: evt.clientX - rect.left,
|
|
||||||
y: evt.clientY - rect.top
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function tracer_cercle(e) {
|
|
||||||
document.getElementsByTagName("svg")[0].setAttribute('height', image.naturalHeight);
|
|
||||||
document.getElementsByTagName("svg")[0].setAttribute('width',image.naturalWidth);
|
|
||||||
var pos_x=position_souris(ima_fond, e).x;
|
|
||||||
var pos_y=position_souris(ima_fond, e).y;
|
|
||||||
for (var i = 0; i < nb_pers; i++) {
|
|
||||||
var dx = posx[i] - pos_x;
|
|
||||||
var dy = posy[i] - pos_y;
|
|
||||||
var dist2 = dx * dx + dy * dy;
|
|
||||||
var rayon2 = rayon * rayon;
|
|
||||||
|
|
||||||
if (dist2 < rayon2) {
|
|
||||||
ibac=i
|
|
||||||
// bac=can_etiq[i].style.backgroundColor;
|
|
||||||
can_etiq[i].style.background = "palegreen"
|
|
||||||
cercle.setAttribute("cx",posx[i]);
|
|
||||||
cercle.setAttribute("cy",posy[i]);
|
|
||||||
cercle.setAttribute("r",rayon);
|
|
||||||
cercle.style.visibility="visible";
|
|
||||||
// grossir ou diminuer la taille du cercle
|
|
||||||
// cercle.addEventListener("wheel", function(e) {
|
|
||||||
// rayon=rayon + (e.deltaY>0 ? -1 : +1);
|
|
||||||
// cercle.setAttribute("r",rayon );
|
|
||||||
// } , false);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cercle.style.visibility="hidden";
|
|
||||||
can_etiq[ibac].style.backgroundColor = "oldlace";
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function afficher_formulaire(e) {
|
|
||||||
souris_x = position_souris(ima_fond, e).x ;
|
|
||||||
souris_y = position_souris(ima_fond, e).y;
|
|
||||||
if (souris_y-document.getElementById('ajout').height<0) sourisy=50;
|
|
||||||
document.getElementById('ajout').style.top=souris_y+40+"px";
|
|
||||||
document.getElementById('ajout').style.left=souris_x-80+"px";
|
|
||||||
setTimeout(function () { document.getElementById("nom").focus(); },10);
|
|
||||||
document.getElementById('ajout').className='visible';
|
|
||||||
};
|
|
||||||
|
|
||||||
function ajouter_personne_xml() {
|
|
||||||
// création d'un nouvel élément <personne> dans data_xml
|
|
||||||
var nomform=document.getElementById("nom").value
|
|
||||||
var nomjfform=document.getElementById("nom_jeune_fille").value
|
|
||||||
var prenomform=document.getElementById("prenom").value
|
|
||||||
var surnomform=""
|
|
||||||
var anneeform=document.getElementById("annee").value
|
|
||||||
var noteform=document.getElementById("note").value
|
|
||||||
document.getElementById('ajout').className='invisible';
|
|
||||||
console.log(nomform+" "+prenomform+" "+anneeform)
|
|
||||||
var personne_ = data_xml.createElement("personne");
|
|
||||||
var nom_ = data_xml.createElement("nom");
|
|
||||||
nom_.appendChild(data_xml.createTextNode(nomform));
|
|
||||||
var nom_jf_ = data_xml.createElement("nom_jeune_fille");
|
|
||||||
nom_jf_.appendChild(data_xml.createTextNode(nomjfform));
|
|
||||||
var prenom_ = data_xml.createElement("prenom");
|
|
||||||
prenom_.appendChild(data_xml.createTextNode(prenomform));
|
|
||||||
var surnom_ = data_xml.createElement("surnom");
|
|
||||||
surnom_.appendChild(data_xml.createTextNode(surnomform));
|
|
||||||
var annee_ = data_xml.createElement("annee_naiss");
|
|
||||||
annee_.appendChild(data_xml.createTextNode(anneeform));
|
|
||||||
var note_ = data_xml.createElement("note");
|
|
||||||
note_.appendChild(data_xml.createTextNode(noteform));
|
|
||||||
var position_ = data_xml.createElement("position");
|
|
||||||
position_.setAttribute("posx", souris_x);
|
|
||||||
position_.setAttribute("posy", souris_y);
|
|
||||||
position_.setAttribute("etx", souris_x-30);
|
|
||||||
position_.setAttribute("ety", souris_y+60);
|
|
||||||
personne_.appendChild(nom_);
|
|
||||||
personne_.appendChild(nom_jf_);
|
|
||||||
personne_.appendChild(prenom_);
|
|
||||||
personne_.appendChild(surnom_);
|
|
||||||
personne_.appendChild(annee_);
|
|
||||||
personne_.appendChild(note_);
|
|
||||||
personne_.appendChild(position_);
|
|
||||||
data_xml.getElementsByTagName("photo")[0].appendChild(personne_)
|
|
||||||
lecture_xml();
|
|
||||||
};
|
|
||||||
|
|
||||||
function misajour_xml(){
|
|
||||||
tit.setAttribute("titx",cant.style.left);
|
|
||||||
tit.setAttribute("tity",cant.style.top);
|
|
||||||
for (var i = 0; i < nb_pers; i++) {
|
|
||||||
position=data_xml.getElementsByTagName( "position")[i];
|
|
||||||
position.setAttribute("etx",can_etiq[i].style.left);
|
|
||||||
position.setAttribute("ety",can_etiq[i].style.top);
|
|
||||||
};
|
|
||||||
lecture_xml();
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
function enregistrer_fichier(fichier) {
|
|
||||||
misajour_xml()
|
|
||||||
var texte_xml=(new XMLSerializer()).serializeToString(data_xml)
|
|
||||||
texte_xml=formatXml(texte_xml)
|
|
||||||
var blob = new Blob([texte_xml], {type: "text/plain;charset=utf-8"});
|
|
||||||
if (navigator.msSaveBlob) {
|
|
||||||
navigator.msSaveBlob(blob, fichier);
|
|
||||||
} else {
|
|
||||||
var a = document.createElement('a');
|
|
||||||
if (a.download === '');
|
|
||||||
a.setAttribute('download', fichier);
|
|
||||||
a.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(texte_xml));
|
|
||||||
a.style.display = 'none';
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
document.body.removeChild(a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatXml(xml, tab) { // tab = optional indent value, default is tab (\t)
|
|
||||||
var formatted = '', indent= '';
|
|
||||||
tab = tab || '\t';
|
|
||||||
xml.split(/>\s*</).forEach(function(node) {
|
|
||||||
if (node.match( /^\/\w/ )) indent = indent.substring(tab.length); // decrease indent by one 'tab'
|
|
||||||
formatted += indent + '<' + node + '>\r\n';
|
|
||||||
if (node.match( /^<?\w[^>]*[^\/]$/ )) indent += tab; // increase indent
|
|
||||||
});
|
|
||||||
return formatted.substring(1, formatted.length-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
function image_finale() {
|
|
||||||
misajour_xml()
|
|
||||||
var decalx=5;
|
|
||||||
var decaly=29;
|
|
||||||
var can_imf = document.createElement("canvas");
|
|
||||||
document.body.appendChild(can_imf);
|
|
||||||
imf_ctx = can_imf.getContext("2d");
|
|
||||||
can_imf.width=ima_fond.width;
|
|
||||||
can_imf.height=ima_fond.height;
|
|
||||||
imf_ctx.drawImage(ima_fond,0,0)
|
|
||||||
if (titre!=='') {
|
|
||||||
var taille=titre.length;
|
|
||||||
hauteur=25
|
|
||||||
roundedRect(imf_ctx,tx-decalx,ty-decaly,taille*11,hauteur,5,'lightyellow','yellow');
|
|
||||||
imf_ctx.drawImage(cant, tx-decalx, ty-decaly)
|
|
||||||
};
|
|
||||||
for (var i = 0; i < nb_pers; i++) {
|
|
||||||
var taille=Math.max(nom[i].length,prenom[i].length,nomjf[i].length+5);
|
|
||||||
hauteur=30
|
|
||||||
if (nomjf[i].replace(/\t/g, '').length>1) {hauteur=45};
|
|
||||||
// if (!nomjf[i].charCodeAt(1)==9) {hauteur=45};
|
|
||||||
roundedRect(imf_ctx,etx[i]-decalx,ety[i]-decaly,taille*7+10,hauteur,15,'oldlace','blue');
|
|
||||||
imf_ctx.drawImage(can_etiq[i],etx[i]-decalx,ety[i]-decaly)
|
|
||||||
}
|
|
||||||
var a = document.createElement('a');
|
|
||||||
if (a.download === '');
|
|
||||||
a.setAttribute('download', enreg_noms);
|
|
||||||
a.setAttribute('href', can_imf.toDataURL("image/png").replace("image/png", "image/octet-stream"));
|
|
||||||
a.style.display = 'none';
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
document.body.removeChild(a);
|
|
||||||
document.body.removeChild(can_imf);
|
|
||||||
|
|
||||||
function roundedRect(ctx, x, y, width, height, radius ,couleur_fond ,couleur_trait) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.strokeStyle = couleur_trait;
|
|
||||||
ctx.moveTo(x, y + radius);
|
|
||||||
ctx.lineTo(x, y + height - radius);
|
|
||||||
ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
|
|
||||||
ctx.lineTo(x + width - radius, y + height);
|
|
||||||
ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
|
|
||||||
ctx.lineTo(x + width, y + radius);
|
|
||||||
ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
|
|
||||||
ctx.lineTo(x + radius, y);
|
|
||||||
ctx.quadraticCurveTo(x, y, x, y + radius);
|
|
||||||
ctx.closePath();
|
|
||||||
ctx.fillStyle = couleur_fond;
|
|
||||||
ctx.fill();
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
function onOpenCvReady() {
|
|
||||||
document.getElementById('status').innerHTML = 'OpenCV.js est chargé !';
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Reference in New Issue
Block a user