Created
March 18, 2014 02:20
-
-
Save agustinhaller/9612430 to your computer and use it in GitHub Desktop.
face_cropper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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