From 3252956e2ba46786a09f2908f556796827494d7e Mon Sep 17 00:00:00 2001 From: AirballTest Date: Wed, 9 May 2012 19:07:19 +0200 Subject: [PATCH 1/3] Adds cropping feature/. Crop function to be implemented --- facemovie/Facemovie.py | 52 ++++++++++++++++++++++++++++++++++++-- facemovie/Facemoviefier.py | 23 ++++++++++++----- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/facemovie/Facemovie.py b/facemovie/Facemovie.py index ffce1c9..aa51d78 100644 --- a/facemovie/Facemovie.py +++ b/facemovie/Facemovie.py @@ -41,6 +41,11 @@ class FaceMovie(object): self.dim_x = 0 self.dim_y = 0 + # thumbmails + self.crop = False + self.width = [0, 0] + self.height = [0, 0] + def list_guys(self): """ Aims at populating the guys list, using the source folder as an input. @@ -81,6 +86,7 @@ class FaceMovie(object): """ Creates new images, normalized by face size """ + # FIXME: May be enhanced by choosing a more educated reference if reference == 0: reference = self.guys[0].faces[0][0][3] # catch face size (width) @@ -88,6 +94,37 @@ class FaceMovie(object): if a_guy.has_face(): a_guy.normalize_face(reference) + def find_crop_dims(self): + """ + Calculates smallest output image that can be used to avoid adding black borders on image + """ + ht = 1000000 # space left above eyes + hb = 1000000 # space left beneath eyes + wl = 1000000 # space left left of eyes + wr = 1000000 # space left right of eyes + + for a_guy in self.guys: + if a_guy.has_face(): + xc = a_guy.x_center + yc = a_guy.y_center + inx = a_guy.in_x + iny = a_guy.in_y + + # finding width + if xc < wl: + wl = xc + if (inx - xc) < wr: + wr = inx - xc + # finding height + if yc < ht: + ht = yc + if (iny - yc) < hb: + hb = iny - yc + + self.width = [wl, wr] + self.height = [ht, hb] + self.crop = True + def find_out_dims(self): """ Calculates best output image size and position depending on @@ -114,7 +151,12 @@ class FaceMovie(object): self.dim_x = self.x_af + self.x_center self.dim_y = self.y_af + self.y_center - + + def crop_im(self, image): + """ + If needed, crops the image to avoid having black borders. + """ + def show_faces(self, mytime=1000, equalize=True): """ Show all faces that have been found for the guys. @@ -127,6 +169,8 @@ class FaceMovie(object): self.dim_y, self.x_center, self.y_center) + if self.crop: + out_im = self.crop_im(out_im) self.out_display(out_im, a_guy.name, time=mytime) def save_faces(self, out_folder, im_format="png"): @@ -140,6 +184,8 @@ class FaceMovie(object): self.dim_y, self.x_center, self.y_center) + if self.crop: + out_im = self.crop_im(out_im) self.save_result(out_im, a_guy.name, out_folder, im_format) def save_movie(self, out_folder, equalize=True): @@ -169,7 +215,9 @@ class FaceMovie(object): out_im = a_guy.create_video_output(self.dim_x, self.dim_y, self.x_center, - self.y_center) + self.y_center) + if self.crop: + out_im = self.crop_im(out_im) cv.WriteFrame(my_video, out_im) def number_guys(self): diff --git a/facemovie/Facemoviefier.py b/facemovie/Facemoviefier.py index 37edfb9..88d58de 100644 --- a/facemovie/Facemoviefier.py +++ b/facemovie/Facemoviefier.py @@ -49,6 +49,13 @@ class Facemoviefier(): help='If this option is activated, images will NOT be resized so that all faces have the same size', action='store_false', default=True) + + # expand images or crop ? Default should be crop + parser.add_argument('-c', + '--crop', + help='If this option is activated, images will be cropped and black borders will not be added' , + action='store_true', + default=False) # type of output wanted (image, video, show) parser.add_argument('-t', @@ -79,16 +86,18 @@ class Facemoviefier(): # I want to change images so that all faces have the same size if self.args['equalize']: self.facemovie.normalize_faces() # sets all faces to the same size - # I want to know the size of the output frame, knowing initial conditions + # I want to know the size of the output frame, knowing initial conditions self.facemovie.find_out_dims() # finds output minimal size to get all eyes in the same place + if self.args['crop']: + self.facemovie.find_crop_dims() # finds output minimal size to get all eyes in the same place #choose your final step - if self.args['type'] == 's': - self.facemovie.show_faces(1000) - elif self.args['type'] == 'i': - self.facemovie.save_faces(self.args['output']) - elif self.args['type'] == 'v': - self.facemovie.save_movie(self.args['output']) + #if self.args['type'] == 's': + # self.facemovie.show_faces(1000) + #elif self.args['type'] == 'i': + # self.facemovie.save_faces(self.args['output']) + #elif self.args['type'] == 'v': + # self.facemovie.save_movie(self.args['output']) if __name__ == '__main__': my_job = Facemoviefier() From 95f66ae51907ffc1313c1ffa655791e11fa9032c Mon Sep 17 00:00:00 2001 From: AirballTest Date: Fri, 11 May 2012 17:57:17 +0200 Subject: [PATCH 2/3] First step of thumbmail feature finished. TODO: Allow user input --- facemovie/Facemovie.py | 19 +++++++++++++++++++ facemovie/Facemoviefier.py | 12 ++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/facemovie/Facemovie.py b/facemovie/Facemovie.py index aa51d78..c510004 100644 --- a/facemovie/Facemovie.py +++ b/facemovie/Facemovie.py @@ -156,6 +156,25 @@ class FaceMovie(object): """ If needed, crops the image to avoid having black borders. """ + # TODO : implement + width = self.width#[0, 0] + height = self.height#[0, 0] + out_im = cv.CreateImage((width[0] + width[1], height[0] + height[1]),cv.IPL_DEPTH_8U, image.nChannels) + cv.Zero(out_im) + + xtl = self.x_center - width[0] + ytl = self.y_center - height[0] + w = width[0] + width[1] + h = height[0] + height[1] + + rect = (xtl, ytl, w, h) + + cv.SetImageROI(image, rect) + print cv.GetSize(out_im), cv.GetSize(image) + cv.Copy(image, out_im) + cv.ResetImageROI(image) + + return out_im def show_faces(self, mytime=1000, equalize=True): """ diff --git a/facemovie/Facemoviefier.py b/facemovie/Facemoviefier.py index 88d58de..5b91b83 100644 --- a/facemovie/Facemoviefier.py +++ b/facemovie/Facemoviefier.py @@ -92,12 +92,12 @@ class Facemoviefier(): self.facemovie.find_crop_dims() # finds output minimal size to get all eyes in the same place #choose your final step - #if self.args['type'] == 's': - # self.facemovie.show_faces(1000) - #elif self.args['type'] == 'i': - # self.facemovie.save_faces(self.args['output']) - #elif self.args['type'] == 'v': - # self.facemovie.save_movie(self.args['output']) + if self.args['type'] == 's': + self.facemovie.show_faces(1000) + elif self.args['type'] == 'i': + self.facemovie.save_faces(self.args['output']) + elif self.args['type'] == 'v': + self.facemovie.save_movie(self.args['output']) if __name__ == '__main__': my_job = Facemoviefier() From b40b38d996c00505e54c6c4c38c67cf6e403909c Mon Sep 17 00:00:00 2001 From: AirballTest Date: Fri, 11 May 2012 18:08:24 +0200 Subject: [PATCH 3/3] Adds user interaction for cropping. TODO : Add corresponding option in command line. Change pixels to number of face size --- facemovie/Facemovie.py | 54 ++++++++++++++++++++++++-------------- facemovie/Facemoviefier.py | 3 +++ 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/facemovie/Facemovie.py b/facemovie/Facemovie.py index c510004..b935931 100644 --- a/facemovie/Facemovie.py +++ b/facemovie/Facemovie.py @@ -43,9 +43,16 @@ class FaceMovie(object): # thumbmails self.crop = False + self.cropdims = [0, 0] # user defined desired dimensions for cropping self.width = [0, 0] self.height = [0, 0] + def set_crop_dims(self, crop_x, crop_y): + """ + Sets the cropping dimension in case they have been provided by the end user + """ + self.cropdims = [crop_x, crop_y] + def list_guys(self): """ Aims at populating the guys list, using the source folder as an input. @@ -103,26 +110,33 @@ class FaceMovie(object): wl = 1000000 # space left left of eyes wr = 1000000 # space left right of eyes - for a_guy in self.guys: - if a_guy.has_face(): - xc = a_guy.x_center - yc = a_guy.y_center - inx = a_guy.in_x - iny = a_guy.in_y - - # finding width - if xc < wl: - wl = xc - if (inx - xc) < wr: - wr = inx - xc - # finding height - if yc < ht: - ht = yc - if (iny - yc) < hb: - hb = iny - yc - - self.width = [wl, wr] - self.height = [ht, hb] + if self.cropdims != [0, 0]: + w = int(self.cropdims[0] / 2) + self.width = [w, w] + h = int(self.cropdims[1] / 2) + self.height = [h, h] + else: + for a_guy in self.guys: + if a_guy.has_face(): + xc = a_guy.x_center + yc = a_guy.y_center + inx = a_guy.in_x + iny = a_guy.in_y + + # finding width + if xc < wl: + wl = xc + if (inx - xc) < wr: + wr = inx - xc + # finding height + if yc < ht: + ht = yc + if (iny - yc) < hb: + hb = iny - yc + + self.width = [wl, wr] + self.height = [ht, hb] + self.crop = True def find_out_dims(self): diff --git a/facemovie/Facemoviefier.py b/facemovie/Facemoviefier.py index 5b91b83..df618de 100644 --- a/facemovie/Facemoviefier.py +++ b/facemovie/Facemoviefier.py @@ -89,6 +89,9 @@ class Facemoviefier(): # I want to know the size of the output frame, knowing initial conditions self.facemovie.find_out_dims() # finds output minimal size to get all eyes in the same place if self.args['crop']: + # TODO: additional parameters (2) may be added here. Add support for this + self.facemovie.set_crop_dims(100, 100) # TODO : do we need something else than pixel here ? It stinks due to face normalization. + # TODO : Change to number of face size self.facemovie.find_crop_dims() # finds output minimal size to get all eyes in the same place #choose your final step