Sobel + contraste ok [FONCTIONNEL]

This commit is contained in:
xdrm-brackets 2016-10-07 17:48:53 +02:00
parent 7984c2712b
commit 46145645a5
9 changed files with 195 additions and 107 deletions

View File

@ -11,8 +11,8 @@ body {
#canvas {
display: block;
position: relative;
width: calc( 300px - 2*2px);
height: calc( 300px - 2*2px);
width: calc( 500px - 2*2px);
height: calc( 500px - 2*2px);
margin: 20px;
border: 2px solid #000;
}
@ -20,7 +20,7 @@ body {
#log {
display: block;
position: relative;
width: calc( 300px - 2*2px - 2*10px);
width: calc( 500px - 2*2px - 2*10px);
margin: 10px 20px;
padding: 10px;
border: 2px solid #555;
@ -30,4 +30,4 @@ body {
display: block;
}
/*# sourceMappingURL=data:application/json;base64,ewoJInZlcnNpb24iOiAzLAoJImZpbGUiOiAibGF5b3V0LmNzcyIsCgkic291cmNlcyI6IFsKCQkiLi4vbGF5b3V0LnNjc3MiCgldLAoJInNvdXJjZXNDb250ZW50IjogWwoJCSIkaW1hZ2Utc2l6ZTogMzAwcHg7XG5cblxuYm9keXtcblx0YmFja2dyb3VuZC1jb2xvcjogI2NjYztcblxuXHRmb250LWZhbWlseTogJ0NvdXJpZXInO1xuXHRmb250LXNpemU6IDEycHg7XG59XG5cblxuXG4jaW1hZ2UtbG9hZGVye1xuXHRkaXNwbGF5OiBub25lO1xufVxuXG4jY2FudmFze1xuXHRkaXNwbGF5OiBibG9jaztcblx0cG9zaXRpb246IHJlbGF0aXZlO1xuXHRcdHdpZHRoOiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cdFx0aGVpZ2h0OiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cblx0bWFyZ2luOiAyMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICMwMDA7XG59XG5cblxuI2xvZ3tcblx0ZGlzcGxheTogYmxvY2s7XG5cdHBvc2l0aW9uOiByZWxhdGl2ZTtcblx0XHR3aWR0aDogY2FsYyggI3skaW1hZ2Utc2l6ZX0gLSAyKjJweCAtIDIqMTBweCApO1xuXG5cdG1hcmdpbjogMTBweCAyMHB4O1xuXHRwYWRkaW5nOiAxMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICM1NTU7XG5cblx0c3Bhbntcblx0XHRkaXNwbGF5OiBibG9jaztcblx0fVxuXG59XG4iCgldLAoJIm1hcHBpbmdzIjogIkFBR0EsQUFBQSxJQUFJLENBQUE7RUFDSCxnQkFBZ0IsRUFBRSxJQUFLO0VBRXZCLFdBQVcsRUFBRSxTQUFVO0VBQ3ZCLFNBQVMsRUFBRSxJQUFLO0NBQ2hCOztBQUlELEFBQUEsYUFBYSxDQUFBO0VBQ1osT0FBTyxFQUFFLElBQUs7Q0FDZDs7QUFFRCxBQUFBLE9BQU8sQ0FBQTtFQUNOLE9BQU8sRUFBRSxLQUFNO0VBQ2YsUUFBUSxFQUFFLFFBQVM7RUFDbEIsS0FBSyxFQUFFLG9CQUFJO0VBQ1gsTUFBTSxFQUFFLG9CQUFJO0VBRWIsTUFBTSxFQUFFLElBQUs7RUFFYixNQUFNLEVBQUUsY0FBZTtDQUN2Qjs7QUFHRCxBQUFBLElBQUksQ0FBQTtFQUNILE9BQU8sRUFBRSxLQUFNO0VBQ2YsUUFBUSxFQUFFLFFBQVM7RUFDbEIsS0FBSyxFQUFFLDZCQUFJO0VBRVosTUFBTSxFQUFFLFNBQVU7RUFDbEIsT0FBTyxFQUFFLElBQUs7RUFFZCxNQUFNLEVBQUUsY0FBZTtDQU12Qjs7QUFkRCxBQVVDLElBVkcsQ0FVSCxJQUFJLENBQUE7RUFDSCxPQUFPLEVBQUUsS0FBTTtDQUNmIiwKCSJuYW1lcyI6IFtdCn0= */
/*# sourceMappingURL=data:application/json;base64,ewoJInZlcnNpb24iOiAzLAoJImZpbGUiOiAibGF5b3V0LmNzcyIsCgkic291cmNlcyI6IFsKCQkiLi4vbGF5b3V0LnNjc3MiCgldLAoJInNvdXJjZXNDb250ZW50IjogWwoJCSIkaW1hZ2Utc2l6ZTogNTAwcHg7XG5cblxuYm9keXtcblx0YmFja2dyb3VuZC1jb2xvcjogI2NjYztcblxuXHRmb250LWZhbWlseTogJ0NvdXJpZXInO1xuXHRmb250LXNpemU6IDEycHg7XG59XG5cblxuXG4jaW1hZ2UtbG9hZGVye1xuXHRkaXNwbGF5OiBub25lO1xufVxuXG4jY2FudmFze1xuXHRkaXNwbGF5OiBibG9jaztcblx0cG9zaXRpb246IHJlbGF0aXZlO1xuXHRcdHdpZHRoOiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cdFx0aGVpZ2h0OiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cblx0bWFyZ2luOiAyMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICMwMDA7XG59XG5cblxuI2xvZ3tcblx0ZGlzcGxheTogYmxvY2s7XG5cdHBvc2l0aW9uOiByZWxhdGl2ZTtcblx0XHR3aWR0aDogY2FsYyggI3skaW1hZ2Utc2l6ZX0gLSAyKjJweCAtIDIqMTBweCApO1xuXG5cdG1hcmdpbjogMTBweCAyMHB4O1xuXHRwYWRkaW5nOiAxMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICM1NTU7XG5cblx0c3Bhbntcblx0XHRkaXNwbGF5OiBibG9jaztcblx0fVxuXG59XG4iCgldLAoJIm1hcHBpbmdzIjogIkFBR0EsQUFBQSxJQUFJLENBQUE7RUFDSCxnQkFBZ0IsRUFBRSxJQUFLO0VBRXZCLFdBQVcsRUFBRSxTQUFVO0VBQ3ZCLFNBQVMsRUFBRSxJQUFLO0NBQ2hCOztBQUlELEFBQUEsYUFBYSxDQUFBO0VBQ1osT0FBTyxFQUFFLElBQUs7Q0FDZDs7QUFFRCxBQUFBLE9BQU8sQ0FBQTtFQUNOLE9BQU8sRUFBRSxLQUFNO0VBQ2YsUUFBUSxFQUFFLFFBQVM7RUFDbEIsS0FBSyxFQUFFLG9CQUFJO0VBQ1gsTUFBTSxFQUFFLG9CQUFJO0VBRWIsTUFBTSxFQUFFLElBQUs7RUFFYixNQUFNLEVBQUUsY0FBZTtDQUN2Qjs7QUFHRCxBQUFBLElBQUksQ0FBQTtFQUNILE9BQU8sRUFBRSxLQUFNO0VBQ2YsUUFBUSxFQUFFLFFBQVM7RUFDbEIsS0FBSyxFQUFFLDZCQUFJO0VBRVosTUFBTSxFQUFFLFNBQVU7RUFDbEIsT0FBTyxFQUFFLElBQUs7RUFFZCxNQUFNLEVBQUUsY0FBZTtDQU12Qjs7QUFkRCxBQVVDLElBVkcsQ0FVSCxJQUFJLENBQUE7RUFDSCxPQUFPLEVBQUUsS0FBTTtDQUNmIiwKCSJuYW1lcyI6IFtdCn0= */

View File

@ -5,7 +5,7 @@
"../layout.scss"
],
"sourcesContent": [
"$image-size: 300px;\n\n\nbody{\n\tbackground-color: #ccc;\n\n\tfont-family: 'Courier';\n\tfont-size: 12px;\n}\n\n\n\n#image-loader{\n\tdisplay: none;\n}\n\n#canvas{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px );\n\t\theight: calc( #{$image-size} - 2*2px );\n\n\tmargin: 20px;\n\n\tborder: 2px solid #000;\n}\n\n\n#log{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px - 2*10px );\n\n\tmargin: 10px 20px;\n\tpadding: 10px;\n\n\tborder: 2px solid #555;\n\n\tspan{\n\t\tdisplay: block;\n\t}\n\n}\n"
"$image-size: 500px;\n\n\nbody{\n\tbackground-color: #ccc;\n\n\tfont-family: 'Courier';\n\tfont-size: 12px;\n}\n\n\n\n#image-loader{\n\tdisplay: none;\n}\n\n#canvas{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px );\n\t\theight: calc( #{$image-size} - 2*2px );\n\n\tmargin: 20px;\n\n\tborder: 2px solid #000;\n}\n\n\n#log{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px - 2*10px );\n\n\tmargin: 10px 20px;\n\tpadding: 10px;\n\n\tborder: 2px solid #555;\n\n\tspan{\n\t\tdisplay: block;\n\t}\n\n}\n"
],
"mappings": "AAGA,AAAA,IAAI,CAAA;EACH,gBAAgB,EAAE,IAAK;EAEvB,WAAW,EAAE,SAAU;EACvB,SAAS,EAAE,IAAK;CAChB;;AAID,AAAA,aAAa,CAAA;EACZ,OAAO,EAAE,IAAK;CACd;;AAED,AAAA,OAAO,CAAA;EACN,OAAO,EAAE,KAAM;EACf,QAAQ,EAAE,QAAS;EAClB,KAAK,EAAE,oBAAI;EACX,MAAM,EAAE,oBAAI;EAEb,MAAM,EAAE,IAAK;EAEb,MAAM,EAAE,cAAe;CACvB;;AAGD,AAAA,IAAI,CAAA;EACH,OAAO,EAAE,KAAM;EACf,QAAQ,EAAE,QAAS;EAClB,KAAK,EAAE,6BAAI;EAEZ,MAAM,EAAE,SAAU;EAClB,OAAO,EAAE,IAAK;EAEd,MAAM,EAAE,cAAe;CAMvB;;AAdD,AAUC,IAVG,CAUH,IAAI,CAAA;EACH,OAAO,EAAE,KAAM;CACf",
"names": []

View File

@ -1,4 +1,4 @@
$image-size: 300px;
$image-size: 500px;
body{

View File

@ -1,3 +1,3 @@
body{background-color:#ccc;font-family:'Courier';font-size:12px}#image-loader{display:none}#canvas{display:block;position:relative;width:calc( 300px - 2*2px);height:calc( 300px - 2*2px);margin:20px;border:2px solid #000}#log{display:block;position:relative;width:calc( 300px - 2*2px - 2*10px);margin:10px 20px;padding:10px;border:2px solid #555}#log span{display:block}
body{background-color:#ccc;font-family:'Courier';font-size:12px}#image-loader{display:none}#canvas{display:block;position:relative;width:calc( 500px - 2*2px);height:calc( 500px - 2*2px);margin:20px;border:2px solid #000}#log{display:block;position:relative;width:calc( 500px - 2*2px - 2*10px);margin:10px 20px;padding:10px;border:2px solid #555}#log span{display:block}
/*# sourceMappingURL=data:application/json;base64,ewoJInZlcnNpb24iOiAzLAoJImZpbGUiOiAibGF5b3V0LmNzcyIsCgkic291cmNlcyI6IFsKCQkiLi4vbGF5b3V0LnNjc3MiCgldLAoJInNvdXJjZXNDb250ZW50IjogWwoJCSIkaW1hZ2Utc2l6ZTogMzAwcHg7XG5cblxuYm9keXtcblx0YmFja2dyb3VuZC1jb2xvcjogI2NjYztcblxuXHRmb250LWZhbWlseTogJ0NvdXJpZXInO1xuXHRmb250LXNpemU6IDEycHg7XG59XG5cblxuXG4jaW1hZ2UtbG9hZGVye1xuXHRkaXNwbGF5OiBub25lO1xufVxuXG4jY2FudmFze1xuXHRkaXNwbGF5OiBibG9jaztcblx0cG9zaXRpb246IHJlbGF0aXZlO1xuXHRcdHdpZHRoOiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cdFx0aGVpZ2h0OiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cblx0bWFyZ2luOiAyMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICMwMDA7XG59XG5cblxuI2xvZ3tcblx0ZGlzcGxheTogYmxvY2s7XG5cdHBvc2l0aW9uOiByZWxhdGl2ZTtcblx0XHR3aWR0aDogY2FsYyggI3skaW1hZ2Utc2l6ZX0gLSAyKjJweCAtIDIqMTBweCApO1xuXG5cdG1hcmdpbjogMTBweCAyMHB4O1xuXHRwYWRkaW5nOiAxMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICM1NTU7XG5cblx0c3Bhbntcblx0XHRkaXNwbGF5OiBibG9jaztcblx0fVxuXG59XG4iCgldLAoJIm1hcHBpbmdzIjogIkFBR0EsQUFBQSxJQUFJLEFBQUEsQ0FDSCxnQkFBZ0IsQ0FBRSxJQUFLLENBRXZCLFdBQVcsQ0FBRSxTQUFVLENBQ3ZCLFNBQVMsQ0FBRSxJQUFLLENBQ2hCLEFBSUQsQUFBQSxhQUFhLEFBQUEsQ0FDWixPQUFPLENBQUUsSUFBSyxDQUNkLEFBRUQsQUFBQSxPQUFPLEFBQUEsQ0FDTixPQUFPLENBQUUsS0FBTSxDQUNmLFFBQVEsQ0FBRSxRQUFTLENBQ2xCLEtBQUssQ0FBRSxvQkFBSSxDQUNYLE1BQU0sQ0FBRSxvQkFBSSxDQUViLE1BQU0sQ0FBRSxJQUFLLENBRWIsTUFBTSxDQUFFLGNBQWUsQ0FDdkIsQUFHRCxBQUFBLElBQUksQUFBQSxDQUNILE9BQU8sQ0FBRSxLQUFNLENBQ2YsUUFBUSxDQUFFLFFBQVMsQ0FDbEIsS0FBSyxDQUFFLDZCQUFJLENBRVosTUFBTSxDQUFFLFNBQVUsQ0FDbEIsT0FBTyxDQUFFLElBQUssQ0FFZCxNQUFNLENBQUUsY0FBZSxDQU12QixBQWRELEFBVUMsSUFWRyxDQVVILElBQUksQUFBQSxDQUNILE9BQU8sQ0FBRSxLQUFNLENBQ2YiLAoJIm5hbWVzIjogW10KfQ== */
/*# sourceMappingURL=data:application/json;base64,ewoJInZlcnNpb24iOiAzLAoJImZpbGUiOiAibGF5b3V0LmNzcyIsCgkic291cmNlcyI6IFsKCQkiLi4vbGF5b3V0LnNjc3MiCgldLAoJInNvdXJjZXNDb250ZW50IjogWwoJCSIkaW1hZ2Utc2l6ZTogNTAwcHg7XG5cblxuYm9keXtcblx0YmFja2dyb3VuZC1jb2xvcjogI2NjYztcblxuXHRmb250LWZhbWlseTogJ0NvdXJpZXInO1xuXHRmb250LXNpemU6IDEycHg7XG59XG5cblxuXG4jaW1hZ2UtbG9hZGVye1xuXHRkaXNwbGF5OiBub25lO1xufVxuXG4jY2FudmFze1xuXHRkaXNwbGF5OiBibG9jaztcblx0cG9zaXRpb246IHJlbGF0aXZlO1xuXHRcdHdpZHRoOiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cdFx0aGVpZ2h0OiBjYWxjKCAjeyRpbWFnZS1zaXplfSAtIDIqMnB4ICk7XG5cblx0bWFyZ2luOiAyMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICMwMDA7XG59XG5cblxuI2xvZ3tcblx0ZGlzcGxheTogYmxvY2s7XG5cdHBvc2l0aW9uOiByZWxhdGl2ZTtcblx0XHR3aWR0aDogY2FsYyggI3skaW1hZ2Utc2l6ZX0gLSAyKjJweCAtIDIqMTBweCApO1xuXG5cdG1hcmdpbjogMTBweCAyMHB4O1xuXHRwYWRkaW5nOiAxMHB4O1xuXG5cdGJvcmRlcjogMnB4IHNvbGlkICM1NTU7XG5cblx0c3Bhbntcblx0XHRkaXNwbGF5OiBibG9jaztcblx0fVxuXG59XG4iCgldLAoJIm1hcHBpbmdzIjogIkFBR0EsQUFBQSxJQUFJLEFBQUEsQ0FDSCxnQkFBZ0IsQ0FBRSxJQUFLLENBRXZCLFdBQVcsQ0FBRSxTQUFVLENBQ3ZCLFNBQVMsQ0FBRSxJQUFLLENBQ2hCLEFBSUQsQUFBQSxhQUFhLEFBQUEsQ0FDWixPQUFPLENBQUUsSUFBSyxDQUNkLEFBRUQsQUFBQSxPQUFPLEFBQUEsQ0FDTixPQUFPLENBQUUsS0FBTSxDQUNmLFFBQVEsQ0FBRSxRQUFTLENBQ2xCLEtBQUssQ0FBRSxvQkFBSSxDQUNYLE1BQU0sQ0FBRSxvQkFBSSxDQUViLE1BQU0sQ0FBRSxJQUFLLENBRWIsTUFBTSxDQUFFLGNBQWUsQ0FDdkIsQUFHRCxBQUFBLElBQUksQUFBQSxDQUNILE9BQU8sQ0FBRSxLQUFNLENBQ2YsUUFBUSxDQUFFLFFBQVMsQ0FDbEIsS0FBSyxDQUFFLDZCQUFJLENBRVosTUFBTSxDQUFFLFNBQVUsQ0FDbEIsT0FBTyxDQUFFLElBQUssQ0FFZCxNQUFNLENBQUUsY0FBZSxDQU12QixBQWRELEFBVUMsSUFWRyxDQVVILElBQUksQUFBQSxDQUNILE9BQU8sQ0FBRSxLQUFNLENBQ2YiLAoJIm5hbWVzIjogW10KfQ== */

View File

@ -5,7 +5,7 @@
"../layout.scss"
],
"sourcesContent": [
"$image-size: 300px;\n\n\nbody{\n\tbackground-color: #ccc;\n\n\tfont-family: 'Courier';\n\tfont-size: 12px;\n}\n\n\n\n#image-loader{\n\tdisplay: none;\n}\n\n#canvas{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px );\n\t\theight: calc( #{$image-size} - 2*2px );\n\n\tmargin: 20px;\n\n\tborder: 2px solid #000;\n}\n\n\n#log{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px - 2*10px );\n\n\tmargin: 10px 20px;\n\tpadding: 10px;\n\n\tborder: 2px solid #555;\n\n\tspan{\n\t\tdisplay: block;\n\t}\n\n}\n"
"$image-size: 500px;\n\n\nbody{\n\tbackground-color: #ccc;\n\n\tfont-family: 'Courier';\n\tfont-size: 12px;\n}\n\n\n\n#image-loader{\n\tdisplay: none;\n}\n\n#canvas{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px );\n\t\theight: calc( #{$image-size} - 2*2px );\n\n\tmargin: 20px;\n\n\tborder: 2px solid #000;\n}\n\n\n#log{\n\tdisplay: block;\n\tposition: relative;\n\t\twidth: calc( #{$image-size} - 2*2px - 2*10px );\n\n\tmargin: 10px 20px;\n\tpadding: 10px;\n\n\tborder: 2px solid #555;\n\n\tspan{\n\t\tdisplay: block;\n\t}\n\n}\n"
],
"mappings": "AAGA,AAAA,IAAI,AAAA,CACH,gBAAgB,CAAE,IAAK,CAEvB,WAAW,CAAE,SAAU,CACvB,SAAS,CAAE,IAAK,CAChB,AAID,AAAA,aAAa,AAAA,CACZ,OAAO,CAAE,IAAK,CACd,AAED,AAAA,OAAO,AAAA,CACN,OAAO,CAAE,KAAM,CACf,QAAQ,CAAE,QAAS,CAClB,KAAK,CAAE,oBAAI,CACX,MAAM,CAAE,oBAAI,CAEb,MAAM,CAAE,IAAK,CAEb,MAAM,CAAE,cAAe,CACvB,AAGD,AAAA,IAAI,AAAA,CACH,OAAO,CAAE,KAAM,CACf,QAAQ,CAAE,QAAS,CAClB,KAAK,CAAE,6BAAI,CAEZ,MAAM,CAAE,SAAU,CAClB,OAAO,CAAE,IAAK,CAEd,MAAM,CAAE,cAAe,CAMvB,AAdD,AAUC,IAVG,CAUH,IAAI,AAAA,CACH,OAAO,CAAE,KAAM,CACf",
"names": []

View File

@ -23,6 +23,7 @@
var process;
var exec = false;
var last;
var trackerTask;
}
@ -46,7 +47,12 @@
var zones;
/* (3) Gestion du track de l'image */
var track = {update: true};
var track = new (function(){
this._update = false;
this.__defineGetter__('update', function( ){ return this._update; });
this.__defineSetter__('update', function(v){ this._update = v; process.bind(DOM.imageLoader)(); });
})();
var tracker = new tracking.ObjectTracker(['face', 'eye', 'mouth']);
tracker.setStepSize(1.5);
@ -69,6 +75,7 @@ process = function(){
/* [0.0] Gestion du changement d'image
=========================================================*/
if( this.src != last ){
zones = [];
exec = false;
last = this.src;
}
@ -84,22 +91,27 @@ process = function(){
this.defaultHeight = this.height;
log('Image copied', '[Canvas]');
/* (3) Si `track.update` est TRUE, on lance `Tracking.js`
---------------------------------------------------------*/
if( track.update ){
// On change la valeur de `exec` pour qu'il n'entre plus dans ce `if`
exec = true;
}
/* [0.2] Si `track.update` et aucun résultat
=========================================================*/
if( zones.length === 0 && track.update ){
/* (1) On initialise la liste des zones */
zones = [];
trakerTask = tracking.track(DOM.imageLoader, tracker);
/* (2) On lance le tracking */
tracking.track(DOM.imageLoader, tracker);
/* (3) Routine exécutée quand le tracking est terminé */
tracker.on('track', function(event){
event.data.forEach(function(rect){ zones.push({ x: rect.x / DOM.imageLoader.width, y: rect.y / DOM.imageLoader.height,
w: rect.width / DOM.imageLoader.width, h: rect.height / DOM.imageLoader.height }); });
// On enregistre dans `zones` les zones trackées
event.data.forEach(function(rect){ zones.push({ x: rect.x / DOM.imageLoader.defaultWidth, y: rect.y / DOM.imageLoader.defaultHeight,
w: rect.width / DOM.imageLoader.defaultWidth, h: rect.height / DOM.imageLoader.defaultHeight }); });
log('Recognition done', '[Tracking.js]');
// On met à jour le rendu (affichage des zones)
@ -107,10 +119,8 @@ process = function(){
});
}
// On change la valeur de `exec` pour qu'il n'entre plus dans ce `if`
exec = true;
}
// sinon on supprime le tracking
!track.update && (zones = []);
/* [1] On initialise/efface le `<canvas>`
@ -118,6 +128,9 @@ process = function(){
_CON.clearRect(0, 0, _CAN.width, _CAN.height);
{ /* [2] Copie sur le `<canvas>`
=========================================================*/
/* (1) Ratio */
@ -130,6 +143,9 @@ process = function(){
=========================================================*/
/* (1) Contraste */
filterManager.get('contrast').apply();
/* (2) Sobel */
filterManager.get('sobel').apply();
}
@ -172,6 +188,7 @@ process = function(){
/* (2) Ajout des filtres */
filterManager.add('ratio', reactiveRatio);
filterManager.add('contrast', reactiveContrast);
filterManager.add('sobel', reactiveSobel);
/* (3) On attache tout à dat.GUI */
Controller.addFolder('Image Ratio');
@ -179,6 +196,7 @@ process = function(){
Controller.add(filterManager.get('ratio'), 'height', 0, 2).listen();
Controller.addFolder('Image Processing');
Controller.add(filterManager.get('contrast'), 'contrast', 0, 100).listen();
Controller.add(filterManager.get('sobel'), 'sobelActive').listen();
}

View File

@ -1,6 +1,8 @@
var ReactiveFilter=function(a){this._manager={_process:function(){}};this._attr=a instanceof Object?a:{};for(var b in this._attr)this.__defineGetter__(b,function(a){return this._attr[a]}.bind(this,b)),this.__defineSetter__(b,function(a,b){return function(e){a._attr[b]=e;a._manager.process()}}(this,b));this.apply=function(){}},ReactiveFilterManager=function(a,b,c){this._target=a instanceof HTMLImageElement?a:null;if(!this._target)throw Error("Param 1 expected to be an HTMLImageElement (<img>), but "+
a.constructor.name+" received");this._canvas=b instanceof HTMLCanvasElement?b:null;if(!this._canvas)throw Error("Param 2 expected to be an HTMLCanvasElement (<canvas>), but "+b.constructor.name+" received");this._context=this._canvas.getContext("2d");this._process=c instanceof Function?c:null;if(!this._process)throw Error("Param 3 expected to be a Function, but "+c.constructor.name+" received");this._filter={}};
var ReactiveFilter=function(a){this._manager={_process:function(){}};this._attr=a instanceof Object?a:{};for(var b in this._attr)this.__defineGetter__(b,function(a){return this._attr[a]}.bind(this,b)),this.__defineSetter__(b,function(a,b){return function(e){a._attr[b]=e;a._manager.process()}}(this,b));this.apply=function(){}},ReactiveFilterManager=function(a,b,d){this._target=a instanceof HTMLImageElement?a:null;if(!this._target)throw Error("Param 1 expected to be an HTMLImageElement (<img>), but "+
a.constructor.name+" received");this._canvas=b instanceof HTMLCanvasElement?b:null;if(!this._canvas)throw Error("Param 2 expected to be an HTMLCanvasElement (<canvas>), but "+b.constructor.name+" received");this._context=this._canvas.getContext("2d");this._process=d instanceof Function?d:null;if(!this._process)throw Error("Param 3 expected to be a Function, but "+d.constructor.name+" received");this._filter={}};
ReactiveFilterManager.prototype.add=function(a,b){a="string"===typeof a?a:null;if(!a)throw Error("Param 1 expected to be a `string`, but "+a.constructor.name+" received");b=b instanceof ReactiveFilter?b:null;if(!b)throw Error("Param 2 expected to be a `ReactiveFilter`, but "+b.constructor.name+" received");if(null!=this._filter[a])return!0;this._filter[a]=b;b._manager=this};
ReactiveFilterManager.prototype.get=function(a){a="string"===typeof a?a:null;if(!a)throw Error("Param 1 expected to be a `string`, but "+a.constructor.name+" received");return null!=this._filter[a]?this._filter[a]:!1};ReactiveFilterManager.prototype.process=function(){this._process.bind(this._target)()};var reactiveRatio=new ReactiveFilter({width:.95,height:.95});
reactiveRatio.apply=function(){if(this._manager instanceof ReactiveFilterManager){var a=this._manager._target,b=this._manager._canvas,c=this._manager._context;a.width=this.width*b.width/a.defaultWidth*a.defaultWidth;a.height=this.height*b.height/a.defaultHeight*a.defaultHeight;c.drawImage(a,0,0,a.width,a.height)}};var reactiveContrast=new ReactiveFilter({contrast:50});
reactiveContrast.apply=function(){if(this._manager instanceof ReactiveFilterManager&&!(100>this.contrast)){var a=this._manager._canvas,b=this._manager._context,a=b.getImageData(0,0,a.width,a.height),c=new Uint32Array(a.data.buffer),d;for(d in c)c[d]=4278190080|16777215-c[d]<<8>>8;b.putImageData(a,0,0)}};
ReactiveFilterManager.prototype.get=function(a){a="string"===typeof a?a:null;if(!a)throw Error("Param 1 expected to be a `string`, but "+a.constructor.name+" received");return null!=this._filter[a]?this._filter[a]:!1};ReactiveFilterManager.prototype.process=function(){this._process.bind(this._target)()};
ConvolutionFilter=function(a,b,d,c){var e,g,h,q,r=parseInt(c.length/2),t=parseInt(c[0].length/2),u=d.slice(0),k,l,f,m,n,p;for(l=r;l<b;l++)for(k=t;k<a;k++){q=h=g=e=0;for(m=-r;m<=r;m++)for(f=-t;f<=t;f++)n=c[r+m][t+f],p=4*((l+m)*a+(k+f)),e+=u[p+0]*n,g+=u[p+1]*n,h+=u[p+2]*n,q+=u[p+3]*n;f=4*(l*a+k);d[f+0]=e;d[f+1]=g;d[f+2]=h;d[f+3]=q}};var reactiveRatio=new ReactiveFilter({width:.95,height:.95});
reactiveRatio.apply=function(){if(this._manager instanceof ReactiveFilterManager){var a=this._manager._target,b=this._manager._canvas,d=this._manager._context;a.width=this.width*b.width/a.defaultWidth*a.defaultWidth;a.height=this.height*b.height/a.defaultHeight*a.defaultHeight;d.drawImage(a,0,0,a.width,a.height)}};var reactiveContrast=new ReactiveFilter({contrast:0});
reactiveContrast.apply=function(){if(this._manager instanceof ReactiveFilterManager){for(var a=this._manager._canvas,b=this._manager._context,a=b.getImageData(0,0,a.width,a.height),d=a.data,c=this.contrast;1<c;)c/=100;for(var c=127*(1-c),e=0,g=d.length;e<g;e++)0!=e%3&&(d[e]>=127+c&&(d[e]=255),d[e]<=127-c&&(d[e]=0));b.putImageData(a,0,0)}};var reactiveSobel=new ReactiveFilter({sobelActive:!1});
reactiveSobel.apply=function(){if(this._manager instanceof ReactiveFilterManager&&this.sobelActive){var a=this._manager._canvas,b=this._manager._context,d=b.getImageData(0,0,a.width,a.height),c=d.data,e=c.slice(0);ConvolutionFilter(a.width,a.height,e,[[-1,0,1],[-2,0,2],[-1,0,1]]);var g=c.slice(0);ConvolutionFilter(a.width,a.height,g,[[1,2,1],[0,0,0],[-1,-2,-1]]);for(var a=0,h=c.length;a<h;a+=4)c[a]=Math.abs(g[a]),c[a+1]=Math.abs(e[a+1]),c[a+2]=(c[a]+c[a+1])/4,c[a+3]=255;b.putImageData(d,0,0)}};

View File

@ -132,6 +132,64 @@ ReactiveFilterManager.prototype.process = function(){
};
/* PRODUIT DE CONVOLUTION
*
*/
ConvolutionFilter = function(width, height, imageData, kernel){
/* [0] Initialisation
=========================================================*/
// Offset pour ne pas dépasser
var offset = {
y: parseInt(kernel.length/2), // On calcule l'offset sur y (pour que le kernel ne déborde pas)
x: parseInt(kernel[0].length/2) // On calcule l'offset sur x (pour que le kernel ne déborde pas)
};
// Front buffer (copie buffer)
var original = imageData.slice(0);
var x, y, kx, ky, convolved, coeff, sIndex, dIndex;
/* [1] Pour chaque pixel de la map
=========================================================*/
for( y = offset.y ; y < height ; y++ ){
for( x = offset.x ; x < width ; x++ ){
/* [2] Pour chaque pixel du @kernel
=========================================================*/
/* (1) Contiendra le compte final */
convolved = {
r: 0x00,
g: 0x00,
b: 0x00,
a: 0x00
};
for( ky = -offset.y ; ky <= offset.y ; ky++ ){
for( kx = -offset.x ; kx <= offset.x ; kx++ ){
coeff = kernel[offset.y+ky][offset.x+kx]; // Valeur du kernel
sIndex = 4*( (y+ky)*width + (x+kx)); // indice source
convolved.r += original[sIndex+0] * coeff;
convolved.g += original[sIndex+1] * coeff;
convolved.b += original[sIndex+2] * coeff;
convolved.a += original[sIndex+3] * coeff;
}
}
/* (2) On applique la valeur sur le buffer de destination */
dIndex = 4*(y*width + x); // indice destination
imageData[dIndex+0] = convolved.r;
imageData[dIndex+1] = convolved.g;
imageData[dIndex+2] = convolved.b;
imageData[dIndex+3] = convolved.a;
}
}
};
@ -164,23 +222,17 @@ reactiveRatio.apply = function(){
};
/************************************************
**** Gestion du contraste ****
************************************************/
var reactiveContrast = new ReactiveFilter({ contrast: 50 });
var reactiveContrast = new ReactiveFilter({ contrast: 0 });
reactiveContrast.apply = function(){
/* [1] Si pas de manager, on exit
=========================================================*/
if( !(this._manager instanceof ReactiveFilterManager) )
return;
// Condition, contraste == 100
if( this.contrast < 100 )
return;
/* [2] On recupère notre back-buffer (32Uint)
/* [2] On recupère notre back-buffer (8Uint)
=========================================================*/
var o = {
image: this._manager._target,
@ -190,14 +242,29 @@ reactiveContrast.apply = function(){
var imageData = o.context.getImageData(0, 0, o.canvas.width, o.canvas.height);
var buffer = imageData.data;
var buffer32 = new Uint32Array( imageData.data.buffer );
// var buffer32 = new Uint32Array( imageData.imageData );
/* [3] On effectue notre modification
=========================================================*/
/* (1) On récupère la valeur du contraste */
var thresold = this.contrast;
while( thresold > 1 ) thresold /= 100;
thresold = (1-thresold) * 127;
/* (1) Gestion du contraste */
for( var i in buffer32 )
buffer32[i] = 0xff000000 | ( 0xffffff - buffer32[i] << 8 ) >> 8;
for( var i = 0, len = buffer.length ; i < len ; i++ ){
// si pixel `alpha`, on ne fait rien
if( i%3 == 0 ) continue;
// Marge Sup.
buffer[i] >= 127+thresold && ( buffer[i] = 255 );
// Marge Inf.
buffer[i] <= 127-thresold && ( buffer[i] = 0 );
}
/* (2) Copie le résultat sur le `<canvas>` */
o.context.putImageData(imageData, 0, 0);
@ -205,66 +272,65 @@ reactiveContrast.apply = function(){
/* PRODUIT DE CONVOLUTION
*
*/
Filter.convolution = function(data, options){
options.kernel = !options.hasOwnProperty('kernel') ? [] : options.kernel;
console.log(options.kernel);
/* [0] Initialisation
/************************************************
**** Gestion du Sobel ****
************************************************/
var reactiveSobel = new ReactiveFilter({ sobelActive: false });
reactiveSobel.apply = function(){
/* [1] Si pas de manager, on exit
=========================================================*/
// Offset pour ne pas dépasser
var offset = {
y: parseInt(options.kernel.length/2), // On calcule l'offset sur y (pour que le kernel ne déborde pas)
x: parseInt(options.kernel[0].length/2) // On calcule l'offset sur x (pour que le kernel ne déborde pas)
if( !(this._manager instanceof ReactiveFilterManager) )
return;
// Si actif uniquement
if( !this.sobelActive )
return;
/* [2] On recupère notre back-buffer (8Uint)
=========================================================*/
var o = {
image: this._manager._target,
canvas: this._manager._canvas,
context: this._manager._context
};
// Front buffer (copie buffer)
var original = data.buffer.slice(0);
var imageData = o.context.getImageData(0, 0, o.canvas.width, o.canvas.height);
var buffer = imageData.data;
// var buffer32 = new Uint32Array( imageData.buffer );
/* [1] Pour chaque pixel de la map
/* [3] On effectue notre modification
=========================================================*/
for( var y = offset.y ; y < data.height ; y++ ){
for( var x = offset.x ; x < data.width ; x++ ){
/* (1) On calcule la convolution horizontale */
var Gx = buffer.slice(0);
ConvolutionFilter(o.canvas.width, o.canvas.height, Gx, [
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
]);
/* [2] Pour chaque pixel du @kernel
=========================================================*/
/* (1) Contiendra le compte final */
var convolved = {
r: 0x00,
g: 0x00,
b: 0x00,
a: 0x00
};
/* (2) On calcule la convolution verticale */
var Gy = buffer.slice(0);
ConvolutionFilter(o.canvas.width, o.canvas.height, Gy, [
[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]
]);
for( var ky = -offset.y ; ky <= offset.y ; ky++ ){
for( var kx = -offset.x ; kx <= offset.x ; kx++ ){
/* (3) On mixe les 2 */
for( var i = 0, len = buffer.length ; i < len ; i += 4 ){
var coeff = options.kernel[offset.y+ky][offset.x+kx]; // Valeur du kernel
var sIndex = 4*( (y+ky)*data.width + (x+kx)); // indice source
/* (4.1) On ajoute la convolution horizontale en rouge */
buffer[i] = Math.abs(Gy[i]);
convolved.r += original[sIndex+0] * coeff;
convolved.g += original[sIndex+1] * coeff;
convolved.b += original[sIndex+2] * coeff;
convolved.a += original[sIndex+3] * coeff;
/* (4.2) On ajoute la convolution verticale en vert */
buffer[i+1] = Math.abs(Gx[i+1]);
}
buffer[i+2] = (buffer[i]+buffer[i+1]) / 4;
buffer[i+3] = 0xff;
}
/* (2) On applique la valeur sur le buffer de destination */
var dIndex = 4*(y*data.width + x); // indice destination
data.buffer[dIndex+0] = convolved.r;
data.buffer[dIndex+1] = convolved.g;
data.buffer[dIndex+2] = convolved.b;
data.buffer[dIndex+3] = convolved.a;
}
}
/* (2) Copie le résultat sur le `<canvas>` */
o.context.putImageData(imageData, 0, 0);
};

View File

@ -1,5 +1,7 @@
var DOM={body:$("body"),canvas:$("canvas"),imageLoader:$("#image-loader")},Controller=new dat.GUI,_CAN=DOM.canvas;_CAN.width=_CAN.height=1E3;var _CON=_CAN.getContext("2d"),iL,filterManager,process,exec=!1,last,init=function(){this.src="front:male:1.jpg";Controller.addFolder("image source");Controller.add(this,"src",this._images).listen();last=this.src},zones,track={update:!0},tracker=new tracking.ObjectTracker(["face","eye","mouth"]);tracker.setStepSize(1.5);Controller.addFolder("Tracking.js");
Controller.add(track,"update");
process=function(){if(this instanceof HTMLImageElement){console.time("PROCESS");this.src!=last&&(exec=!1,last=this.src);exec||(this.defaultWidth=this.width,this.defaultHeight=this.height,log("Image copied","[Canvas]"),track.update&&(zones=[],tracking.track(DOM.imageLoader,tracker),tracker.on("track",function(a){a.data.forEach(function(a){zones.push({x:a.x/DOM.imageLoader.defaultWidth,y:a.y/DOM.imageLoader.defaultHeight,w:a.width/DOM.imageLoader.defaultWidth,h:a.height/DOM.imageLoader.defaultHeight})});
log("Recognition done","[Tracking.js]");process.bind(DOM.imageLoader)()})),exec=!0);_CON.clearRect(0,0,_CAN.width,_CAN.height);filterManager.get("ratio").apply();filterManager.get("contrast").apply();for(var c in zones){var a=zones[c].x*this.width,b=zones[c].y*this.height,d=zones[c].w*this.width,e=zones[c].h*this.height;_CON.beginPath();_CON.moveTo(a,b);_CON.lineTo(a,b+e);_CON.lineTo(a+d,b+e);_CON.lineTo(a+d,b);_CON.lineTo(a,b);_CON.lineWidth=5;_CON.stroke()}console.timeEnd("PROCESS")}};
filterManager=new ReactiveFilterManager(DOM.imageLoader,_CAN,process);filterManager.add("ratio",reactiveRatio);filterManager.add("contrast",reactiveContrast);Controller.addFolder("Image Ratio");Controller.add(filterManager.get("ratio"),"width",0,2).listen();Controller.add(filterManager.get("ratio"),"height",0,2).listen();Controller.addFolder("Image Processing");Controller.add(filterManager.get("contrast"),"contrast",0,100).listen();iL=new ImageLoader(DOM.imageLoader,init,process);
var DOM={body:$("body"),canvas:$("canvas"),imageLoader:$("#image-loader")},Controller=new dat.GUI,_CAN=DOM.canvas;_CAN.width=_CAN.height=1E3;
var _CON=_CAN.getContext("2d"),iL,filterManager,process,exec=!1,last,trackerTask,init=function(){this.src="front:male:1.jpg";Controller.addFolder("image source");Controller.add(this,"src",this._images).listen();last=this.src},zones,track=new function(){this._update=!1;this.__defineGetter__("update",function(){return this._update});this.__defineSetter__("update",function(a){this._update=a;process.bind(DOM.imageLoader)()})},tracker=new tracking.ObjectTracker(["face","eye","mouth"]);tracker.setStepSize(1.5);
Controller.addFolder("Tracking.js");Controller.add(track,"update");
process=function(){if(this instanceof HTMLImageElement){console.time("PROCESS");this.src!=last&&(zones=[],exec=!1,last=this.src);exec||(this.defaultWidth=this.width,this.defaultHeight=this.height,log("Image copied","[Canvas]"),exec=!0);0===zones.length&&track.update&&(zones=[],trakerTask=tracking.track(DOM.imageLoader,tracker),tracker.on("track",function(a){a.data.forEach(function(a){zones.push({x:a.x/DOM.imageLoader.width,y:a.y/DOM.imageLoader.height,w:a.width/DOM.imageLoader.width,h:a.height/DOM.imageLoader.height})});
log("Recognition done","[Tracking.js]");process.bind(DOM.imageLoader)()}));!track.update&&(zones=[]);_CON.clearRect(0,0,_CAN.width,_CAN.height);filterManager.get("ratio").apply();filterManager.get("contrast").apply();filterManager.get("sobel").apply();for(var a in zones){var b=zones[a].x*this.width,c=zones[a].y*this.height,d=zones[a].w*this.width,e=zones[a].h*this.height;_CON.beginPath();_CON.moveTo(b,c);_CON.lineTo(b,c+e);_CON.lineTo(b+d,c+e);_CON.lineTo(b+d,c);_CON.lineTo(b,c);_CON.lineWidth=5;
_CON.stroke()}console.timeEnd("PROCESS")}};filterManager=new ReactiveFilterManager(DOM.imageLoader,_CAN,process);filterManager.add("ratio",reactiveRatio);filterManager.add("contrast",reactiveContrast);filterManager.add("sobel",reactiveSobel);Controller.addFolder("Image Ratio");Controller.add(filterManager.get("ratio"),"width",0,2).listen();Controller.add(filterManager.get("ratio"),"height",0,2).listen();Controller.addFolder("Image Processing");
Controller.add(filterManager.get("contrast"),"contrast",0,100).listen();Controller.add(filterManager.get("sobel"),"sobelActive").listen();iL=new ImageLoader(DOM.imageLoader,init,process);