Skip to content

Instantly share code, notes, and snippets.

@agustinhaller
Created March 18, 2014 01:54
Show Gist options
  • Select an option

  • Save agustinhaller/9612151 to your computer and use it in GitHub Desktop.

Select an option

Save agustinhaller/9612151 to your computer and use it in GitHub Desktop.
face-crop
{% extends "layout.html" %}
{% block main_content %}
<div class="test-content">
<div class="main-wrapper">
{# Slogan #}
<div class="slogan-container row">
<h2 class="main-slogan">Face Crop TESTS</h2>
</div>
{# Call to action #}
<div class="test-container row">
<h2>Canvas Magic</h2>
<canvas id="magic-canvas" width="300" height="300"></canvas>
<h2>Faces</h2>
<br>
<ul class="cropped-faces-list">
</ul>
<h2>Original Images</h2>
<br>
{% if IMAGES|length > 0 %}
<ul class="results-list">
{% for image in IMAGES %}
{% include "templates/website/face-crop-image.html" with { IMAGE: image} %}
{% endfor %}
</ul>
{% else %}
{% endif %}
</div>
</div>
</div>
{% endblock %}
{% block scripts_bottom %}
<script type="text/javascript" src="http://{{ DOMAIN_BASE }}/static/js/vendor/JSFeat/jsfeat-min.js"></script>
<script type="text/javascript" src="http://{{ DOMAIN_BASE }}/static/js/vendor/JSFeat/frontalface.js"></script>
<script>
// Here goes the magic!
$(document).ready(function(){
// Vamos a tener que tener un canvas auxiliar en donde vamos a ir cargando las imagenes a medida que iteramos
var magic_canvas = $("#magic-canvas")[0],
canvas_context = magic_canvas.getContext('2d'),
$original_images = $(".results-list > li.sample-item img"),
max_work_size = 160,
canvasWidth = magic_canvas.width,
canvasHeight = magic_canvas.height,
classifier = jsfeat.haar.frontalface;
canvas_context.fillStyle = "rgb(0,255,0)";
canvas_context.strokeStyle = "rgb(0,255,0)";
// Iterate over the images and try to crop the faces
$original_images.each(function(){
var $original_image = $(this),
original_image = $original_image[0],
$img_aux = $("<img/>", {"class":"img_aux"}),
img_aux = $img_aux[0];
$img_aux.on({
"load" : function(event, data){
var img = $(this)[0],
img_width = img.width,
img_height = img.height;
// debugger;
console.log("image:", $original_image.attr("src"));
// Set canvas width and height equals to the image sizes
magic_canvas.setAttribute('width', img_width);
magic_canvas.setAttribute('height', img_height);
// Fill canvas with image data
canvas_context.drawImage(img, 0, 0, img_width, img_height);
// Do JSFeat magic face cropping
var scale = Math.min(max_work_size/img_width, max_work_size/img_height);
var w = (img_width*scale)|0;
var h = (img_height*scale)|0;
img_u8 = new jsfeat.matrix_t(w, h, jsfeat.U8_t | jsfeat.C1_t);
edg = new jsfeat.matrix_t(w, h, jsfeat.U8_t | jsfeat.C1_t);
work_canvas = document.createElement('canvas');
work_canvas.width = w;
work_canvas.height = h;
work_ctx = work_canvas.getContext('2d');
ii_sum = new Int32Array((w+1)*(h+1));
ii_sqsum = new Int32Array((w+1)*(h+1));
ii_tilted = new Int32Array((w+1)*(h+1));
ii_canny = new Int32Array((w+1)*(h+1));
options = function(){
this.min_scale = 2;
this.scale_factor = 1.15;
this.use_canny = false;
this.edges_density = 0.13;
this.equalize_histogram = true;
};
work_ctx.drawImage(img, 0, 0, work_canvas.width, work_canvas.height);
var imageData = work_ctx.getImageData(0, 0, work_canvas.width, work_canvas.height);
jsfeat.imgproc.grayscale(imageData.data, img_u8.data);
// possible options
if(options.equalize_histogram)
{
jsfeat.imgproc.equalize_histogram(img_u8, img_u8);
}
jsfeat.imgproc.compute_integral_image(img_u8, ii_sum, ii_sqsum, classifier.tilted ? ii_tilted : null);
if(options.use_canny)
{
jsfeat.imgproc.canny(img_u8, edg, 10, 50);
jsfeat.imgproc.compute_integral_image(edg, ii_canny, null, null);
}
jsfeat.haar.edges_density = options.edges_density;
var rects = jsfeat.haar.detect_multi_scale(ii_sum, ii_sqsum, ii_tilted, options.use_canny? ii_canny : null, img_u8.cols, img_u8.rows, classifier, options.scale_factor, options.min_scale);
rects = jsfeat.haar.group_rectangles(rects, 1);
// debugger;
// draw_faces(canvas_context, rects, canvasWidth/img_u8.cols, 1);
crop_faces(canvas_context, rects, img_width/img_u8.cols, 1, img);
}
});
// First we need to get base64 iamge in order to avoid cross origin issues
$.ajax({
url: 'http://{{ DOMAIN_BASE }}/parse-image-url',
data: { image_url: $original_image.attr("src") },
type: 'POST',
success: function (result) {
// debugger;
var result_json = JSON.parse(result);
if(result_json.result == "OK")
{
$img_aux.attr("src", result_json.image_base64);
}
else
{
}
},
complete: function()
{
}
});
function crop_faces(ctx, rects, sc, max, imageObj)
{
var on = rects.length;
if(on && max)
{
jsfeat.math.qsort(rects, 0, on-1, function(a,b){return (b.confidence<a.confidence);})
}
var n = max || on;
n = Math.min(n, on);
var r;
for(var i = 0; i < n; ++i)
{
r = rects[i];
var pos_x = (r.x*sc)|0,
pos_y = (r.y*sc)|0,
crop_width = (r.width*sc)|0,
crop_height = (r.height*sc)|0;
ctx.strokeRect(pos_x, pos_y, crop_width, crop_height);
// Now create a new auxiliar canvas to crop the image
var $canvas_aux = $("<canvas/>", {"class":"canvas_aux"}),
canvas_aux = $canvas_aux[0],
// $img_aux = $("<img/>", {"class":"cropped_img"}),
// img_aux = $img_aux[0],
context_aux = canvas_aux.getContext('2d');
var dest_width = 200,
dest_height = 200;
canvas_aux.width = dest_width;
canvas_aux.height = dest_height;
context_aux.drawImage(imageObj, pos_x, pos_y, crop_width, crop_height, 0, 0, dest_width, dest_height);
// Convert image to gray scale
var image_data = context_aux.getImageData(0, 0, dest_width, dest_height);
for(var y = 0; y < image_data.height; y++)
{
for(var x = 0; x < image_data.width; x++)
{
var i = (y * 4) * image_data.width + x * 4;
var avg = (image_data.data[i] + image_data.data[i + 1] + image_data.data[i + 2]) / 3;
image_data.data[i] = avg;
image_data.data[i + 1] = avg;
image_data.data[i + 2] = avg;
}
}
context_aux.putImageData(image_data, 0, 0, 0, 0, image_data.width, image_data.height);
// var gray_img = new jsfeat.matrix_t(dest_width, dest_height, jsfeat.U8_t | jsfeat.C1_t);
// jsfeat.imgproc.grayscale(image_data.data, gray_img.data);
// render result back to canvas
// var data_u32 = new Uint32Array(image_data.data.buffer);
// var alpha = (0xff << 24);
// var i = img_u8.cols*img_u8.rows, pix = 0;
// debugger;
// while(--i >= 0) {
// pix = img_u8.data[i];
// data_u32[i] = alpha | (pix << 16) | (pix << 8) | pix;
// }
// context_aux.putImageData(image_data, 0, 0);
// debugger;
// Now get image data from auxiliar context
// var type = image_type,
var type = "image/jpeg",
// Compress image to 85%
// compress_ratio = 0.85,
compress_ratio = 1,
cropped_image_data = canvas_aux.toDataURL(type, compress_ratio);
// Now set the image data as image source
// $img_aux.attr("src", cropped_image_data);
$(".cropped-faces-list").append('<li><img src="'+cropped_image_data+'"/></li>');
}
}
});
});
</script>
{% endblock %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment