Skip to content

Instantly share code, notes, and snippets.

@agustinhaller
Created March 18, 2014 02:20
Show Gist options
  • Save agustinhaller/9612430 to your computer and use it in GitHub Desktop.
Save agustinhaller/9612430 to your computer and use it in GitHub Desktop.
face_cropper
var face_cropper = (function(){
var crop_faces = function(rects, sc, max, imageObj, imageType){
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;
// 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);
// Now get image data from auxiliar context
// var type = image_type,
// var type = "image/jpeg",
var type = imageType,
// 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>');
return cropped_image_data;
}
},
extract = function ($dfd, image_data, image_type){
var $canvas_aux = $("<canvas/>", {"class":"canvas_aux"}),
canvas_aux = $canvas_aux[0],
$img_aux = $("<img/>", {"class":"img_aux"}),
img_aux = $img_aux[0],
context_aux = canvas_aux.getContext('2d'),
// JSFeat stuff
max_work_size = 160,
classifier = jsfeat.haar.frontalface;
$img_aux.on({
"load" : function(event, data){
var img = $(this)[0],
img_width = img.width,
img_height = 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);
// Now crop the face and convert the image to gray scale
dest_image_data = crop_faces(rects, img_width/img_u8.cols, 1, img, image_type);
$dfd.resolve(dest_image_data);
}
});
$img_aux.attr("src", image_data);
return $dfd.promise();
};
return {
extract: function(image_data, image_type) {
var $dfd_face_extraction = $.Deferred(),
$extraction_promise = extract($dfd_face_extraction, image_data, image_type);
return $extraction_promise.promise();
}
}
} ());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment