Compare commits
2 Commits
df37fd2b63
...
7b17f7ad50
Author | SHA1 | Date |
---|---|---|
Tykayn | 7b17f7ad50 | |
Tykayn | 4d87064a79 |
28
README.md
28
README.md
|
@ -25,15 +25,25 @@ Quand vous avez terminé de remplir et de positionner vos étiquettes, n'oubliez
|
||||||
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 - en cours ...
|
* TODO modifier une personne - en cours ...
|
||||||
saisir / modifier le titre - en cours ...
|
* TODO saisir / modifier le titre - en cours ...
|
||||||
adapter la taille des étiquettes et du cercle à la résolution de l'image
|
- autofocus sur le premier champ
|
||||||
modifier la couleur des étiquettes et du texte
|
- changer l'entrée dans le XML correspondant
|
||||||
paramétrer un peu mieux toutes les valeurs de positionnement qui sont en dur.
|
* TODO adapter la taille des étiquettes et du cercle à la résolution de l'image
|
||||||
éviter d'avoir à re-saisir les noms que l'on retrouve sur plusieurs photos - pas facile simplement
|
* TODO modifier la couleur des étiquettes et du texte
|
||||||
reconnaissance faciale pour retrouver les mêmes personnages sur plusieurs photos
|
- avoir un input de type color
|
||||||
barre d'outils ??
|
|
||||||
...... etc et sans compliquer le programme !!!
|
* TODO éviter d'avoir à re-saisir les noms que l'on retrouve sur plusieurs photos - pas facile simplement
|
||||||
|
- utiliser le localstorage pour stocker nos entrées et une library d'autocomplétion à la saisie
|
||||||
|
* TODO reconnaissance faciale pour retrouver les mêmes personnages sur plusieurs photos
|
||||||
|
* TODO barre d'outils ??
|
||||||
|
- à définir
|
||||||
|
...... etc et sans compliquer le programme !!! (ha ha!)
|
||||||
|
|
||||||
Désolé si le code n'est pas très aux normes, mais je ne connaissais pas javascript avant ce programme!
|
Désolé si le code n'est pas très aux normes, mais je ne connaissais pas javascript avant ce programme!
|
||||||
|
|
||||||
|
## Fait
|
||||||
|
* ajouter des personnes dans le xml
|
||||||
|
* télécharger un export des données en xml
|
||||||
|
* importer un xml
|
||||||
|
* paramétrer un peu mieux toutes les valeurs de positionnement, qui sont maintenant relatives à la place de l'image, qui n'est plus obligée d'être absolue à 0, 0.
|
Before Width: | Height: | Size: 898 KiB After Width: | Height: | Size: 898 KiB |
|
@ -13,8 +13,11 @@ Licence AGPL v3.0+
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<title>Photo mem</title>
|
<title>Photo mem</title>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/bulma.min.css"></link>
|
<link rel="stylesheet" type="text/css" href="styles/bulma.min.css"></link>
|
||||||
<link rel="stylesheet" type="text/css" href="/style_photomem.css"></link>
|
<link rel="stylesheet" type="text/css" href="styles/style_photomem.css"></link>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="scripts/lib/opencv.js" onload="onOpenCvReady();"></script>
|
||||||
|
<script type="application/javascript" src="scripts/main.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
@ -28,7 +31,7 @@ Licence AGPL v3.0+
|
||||||
</p>
|
</p>
|
||||||
<div id="actions">
|
<div id="actions">
|
||||||
|
|
||||||
<input id="fichiers" multiple type="file" class="cotecote button is-primary" value="zizou.png"/>
|
<input id="fichiers" multiple type="file" class="cotecote button is-primary" value="assets/zizou.png"/>
|
||||||
<button class="button is-secondary" id="bouton_image" onclick="fichiers.click()"
|
<button class="button is-secondary" id="bouton_image" onclick="fichiers.click()"
|
||||||
title="Charger une image et le XML associé">
|
title="Charger une image et le XML associé">
|
||||||
Choix de la
|
Choix de la
|
||||||
|
@ -46,7 +49,7 @@ Licence AGPL v3.0+
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</header>
|
</header>
|
||||||
<main class="section is-large">
|
<main class="section is-medium">
|
||||||
|
|
||||||
|
|
||||||
<!-- cercle indiquant la position où on a cliqué-->
|
<!-- cercle indiquant la position où on a cliqué-->
|
||||||
|
@ -54,25 +57,51 @@ Licence AGPL v3.0+
|
||||||
|
|
||||||
<!-- formulaire d'ajout ou de modification d'une personne-->
|
<!-- formulaire d'ajout ou de modification d'une personne-->
|
||||||
<div id="ajout" class="invisible" style="position: absolute; z-index: 1;">
|
<div id="ajout" class="invisible" style="position: absolute; z-index: 1;">
|
||||||
<form class="content" name="ajout_personne" id="ajout_personne" onsubmit="envoi_formulaire_ajout">
|
<form class="content " name="ajout_personne" id="ajout_personne" onsubmit="envoi_formulaire_ajout">
|
||||||
<h2 class="title">
|
<h2 class="title">
|
||||||
NOUVELLE PERSONNE
|
NOUVELLE PERSONNE
|
||||||
</h2>
|
</h2>
|
||||||
<label for="nom">Nom : </label><input type="text" name="nom" id="nom" autofocus><BR>
|
<div class="field is-horizontal">
|
||||||
<label for="nom_jeune_fille">Née : </label><input type="text" name="nom_jf" id="nom_jeune_fille"><BR>
|
<label for="nom">Nom : </label><input class="input" type="text" name="nom" id="nom" autofocus>
|
||||||
<label for="prenom">Prénom : </label><input type="text" name="prénom" id="prenom"><BR>
|
</div>
|
||||||
<label for="annee">Année : </label><input type="text" name="année" id="annee"><BR>
|
<div class="field is-horizontal">
|
||||||
<label for="note">Note : </label><input type="text" name="note" id="note"><BR>
|
<label for="nom_jeune_fille">Née : </label><input class="input" type="text" name="nom_jf" id="nom_jeune_fille">
|
||||||
<label for="titre">Titre photo : </label><input type="text" name="titre" id="titre"><BR>
|
</div>
|
||||||
<input id="reset" type="reset" value="Annuler"
|
<div class="field is-horizontal">
|
||||||
onClick=document.getElementById("ajout").className="invisible";>
|
<label for="prenom">Prénom : </label><input class="input"type="text" name="prénom" id="prenom">
|
||||||
<input id="enreg" type="reset" value="Ajouter"
|
</div>
|
||||||
onClick=envoi_formulaire_ajout()>
|
<div class="field is-horizontal">
|
||||||
|
<label for="annee">Année : </label><input class="input" type="text" name="année" id="annee">
|
||||||
|
</div>
|
||||||
|
<div class="field is-horizontal">
|
||||||
|
<label for="note">Note : </label><input class="input" type="text" name="note" id="note">
|
||||||
|
</div>
|
||||||
|
<div class="field is-horizontal">
|
||||||
|
<label for="titre">Titre photo : </label><input class="input" type="text" name="titre" id="titre">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<input class="button is-warning" id="reset" type="reset" value="Annuler"
|
||||||
|
onClick=document.getElementById("ajout").className="invisible";>
|
||||||
|
</div>
|
||||||
|
<div class="column has-text-right">
|
||||||
|
<input class="button is-primary" id="enreg" type="reset" value="Ajouter"
|
||||||
|
onClick=envoi_formulaire_ajout()>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- photo de fond-->
|
<!-- photo de fond-->
|
||||||
<img src="zizou.png" id="ima_fond" />
|
<img src="assets/zizou.png" id="ima_fond" />
|
||||||
<div id="menu_modif" class="invisible">
|
<div id="menu_modif" class="invisible">
|
||||||
<div id="modifier" onClick="modifier_personne();">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>
|
||||||
|
@ -88,7 +117,5 @@ Licence AGPL v3.0+
|
||||||
<p id="status" class=cotecote>OpenCV.js chargement en cours...</p>
|
<p id="status" class=cotecote>OpenCV.js chargement en cours...</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<script type="application/javascript" src="main.js"></script>
|
|
||||||
<script src="opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
* détection de visages avec openCV
|
||||||
|
******************************************/
|
||||||
|
function onOpenCvReady() {
|
||||||
|
console.info('OpenCV.js est chargé !');
|
||||||
|
document.getElementById('status').remove()
|
||||||
|
gestion_souris();
|
||||||
|
}
|
||||||
|
|
||||||
|
function detection_de_visages() {
|
||||||
|
src = cv.imread(ima_fond);
|
||||||
|
gray = new cv.Mat();
|
||||||
|
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
||||||
|
chargement_haarcascade();
|
||||||
|
}
|
||||||
|
|
||||||
|
function chargement_haarcascade() {
|
||||||
|
let 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)
|
||||||
|
}
|
||||||
|
src.delete();
|
||||||
|
gray.delete();
|
||||||
|
faceCascade.delete();
|
||||||
|
faces.delete();
|
||||||
|
lecture_xml();
|
||||||
|
|
||||||
|
;
|
||||||
|
}
|
|
@ -307,31 +307,31 @@ function position_souris(canvas, evt) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function tracer_cercle(e) {
|
function tracer_cercle(e) {
|
||||||
document.getElementsByTagName("svg")[0].setAttribute('height', image.naturalHeight);
|
// document.getElementsByTagName("svg")[0].setAttribute('height', image.naturalHeight);
|
||||||
document.getElementsByTagName("svg")[0].setAttribute('width', image.naturalWidth);
|
// document.getElementsByTagName("svg")[0].setAttribute('width', image.naturalWidth);
|
||||||
let pos_x = position_souris(ima_fond, e).x;
|
// let pos_x = position_souris(ima_fond, e).x;
|
||||||
let pos_y = position_souris(ima_fond, e).y;
|
// let pos_y = position_souris(ima_fond, e).y;
|
||||||
for (let i = 0; i < nb_pers; i++) {
|
// for (let i = 0; i < nb_pers; i++) {
|
||||||
let dx = posx[i] - pos_x;
|
// let dx = posx[i] - pos_x;
|
||||||
let dy = posy[i] - pos_y;
|
// let dy = posy[i] - pos_y;
|
||||||
let dist2 = dx * dx + dy * dy;
|
// let dist2 = dx * dx + dy * dy;
|
||||||
let rayon2 = rayon * rayon;
|
// let rayon2 = rayon * rayon;
|
||||||
|
//
|
||||||
if (dist2 < rayon2) {
|
// if (dist2 < rayon2) {
|
||||||
ibac = i
|
// ibac = i
|
||||||
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]);
|
||||||
cercle.setAttribute("r", rayon);
|
// cercle.setAttribute("r", rayon);
|
||||||
cercle.style.visibility = "visible";
|
// cercle.style.visibility = "visible";
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
;
|
// ;
|
||||||
cercle.style.visibility = "hidden";
|
// cercle.style.visibility = "hidden";
|
||||||
if (nb_pers != 0) {
|
// if (nb_pers != 0) {
|
||||||
can_etiq[ibac].style.backgroundColor = "oldlace";
|
// can_etiq[ibac].style.backgroundColor = "oldlace";
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -342,8 +342,8 @@ function tracer_cercle(e) {
|
||||||
function afficher_formulaire(e) {
|
function afficher_formulaire(e) {
|
||||||
let formulaire_ajout = document.getElementById('ajout')
|
let formulaire_ajout = document.getElementById('ajout')
|
||||||
let highlight_circle = document.getElementById('circle_svg')
|
let highlight_circle = document.getElementById('circle_svg')
|
||||||
souris_x = e.clientX;
|
souris_x = e.clientX ;
|
||||||
souris_y = e.clientY;
|
souris_y = e.clientY + document.documentElement.scrollTop;
|
||||||
if (souris_y - document.getElementById('ajout').height < 0) {
|
if (souris_y - document.getElementById('ajout').height < 0) {
|
||||||
sourisy = 50
|
sourisy = 50
|
||||||
}
|
}
|
||||||
|
@ -472,56 +472,3 @@ function image_finale() {
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************
|
|
||||||
* détection de visages avec openCV
|
|
||||||
******************************************/
|
|
||||||
function onOpenCvReady() {
|
|
||||||
console.info('OpenCV.js est chargé !');
|
|
||||||
document.getElementById('status').remove()
|
|
||||||
gestion_souris();
|
|
||||||
}
|
|
||||||
|
|
||||||
function detection_de_visages() {
|
|
||||||
src = cv.imread(ima_fond);
|
|
||||||
gray = new cv.Mat();
|
|
||||||
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
|
|
||||||
chargement_haarcascade();
|
|
||||||
}
|
|
||||||
|
|
||||||
function chargement_haarcascade() {
|
|
||||||
let 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)
|
|
||||||
}
|
|
||||||
src.delete();
|
|
||||||
gray.delete();
|
|
||||||
faceCascade.delete();
|
|
||||||
faces.delete();
|
|
||||||
lecture_xml();
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
|
|
@ -37,11 +37,9 @@ circle {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
top: 100px;
|
top: 100px;
|
||||||
left: 200px;
|
left: 200px;
|
||||||
padding-top: 0.5em;
|
padding: 1em 2em ;
|
||||||
padding-bottom: 0.5em;
|
|
||||||
padding-left: 1em;
|
|
||||||
background-color: Azure;
|
background-color: Azure;
|
||||||
width: 24em;
|
width: 30em;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue