#!/usr/bin/env python ## # Massimiliano Patacchiola, Plymouth University 2016 # website: http://mpatacchiola.github.io/ # email: massimiliano.patacchiola@plymouth.ac.uk # Python code for information retrieval from the Annotated Facial Landmarks in the Wild (AFLW) dataset. # In this example the faces are isolated and saved in a specified output folder. # Some information (roll, pitch, yaw) are returned, they can be used to filter the images. # This code requires OpenCV and Numpy. You can easily bypass the OpenCV calls if you want to use # a different library. In order to use the code you have to unzip the images and store them in # the directory "flickr" mantaining the original folders name (0, 2, 3). # # The following are the database properties available (last updated version 2012-11-28): # # databases: db_id, path, description # faceellipse: face_id, x, y, ra, rb, theta, annot_type_id, upsidedown # faceimages: image_id, db_id, file_id, filepath, bw, widht, height # facemetadata: face_id, sex, occluded, glasses, bw, annot_type_id # facepose: face_id, roll, pitch, yaw, annot_type_id # facerect: face_id, x, y, w, h, annot_type_id # faces: face_id, file_id, db_id # featurecoords: face_id, feature_id, x, y # featurecoordtype: feature_id, descr, code, x, y, z import sqlite3 import cv2 import os.path import numpy as np #Change this paths according to your directories images_path = "./flickr/" storing_path = "./output/" def main(): #Image counter counter = 1 #Open the sqlite database conn = sqlite3.connect('aflw.sqlite') c = conn.cursor() #Creating the query string for retriving: roll, pitch, yaw and faces position #Change it according to what you want to retrieve select_string = "faceimages.filepath, faces.face_id, facepose.roll, facepose.pitch, facepose.yaw, facerect.x, facerect.y, facerect.w, facerect.h" from_string = "faceimages, faces, facepose, facerect" where_string = "faces.face_id = facepose.face_id and faces.file_id = faceimages.file_id and faces.face_id = facerect.face_id" query_string = "SELECT " + select_string + " FROM " + from_string + " WHERE " + where_string #It iterates through the rows returned from the query for row in c.execute(query_string): #Using our specific query_string, the "row" variable will contain: # row[0] = image path # row[1] = face id # row[2] = roll # row[3] = pitch # row[4] = yaw # row[5] = face coord x # row[6] = face coord y # row[7] = face width # row[8] = face heigh #Creating the full path names for input and output input_path = images_path + str(row[0]) output_path = storing_path + str(row[0]) #If the file exist then open it if(os.path.isfile(input_path) == True): #image = cv2.imread(input_path, 0) #load in grayscale image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #load the colour version #Image dimensions image_h, image_w = image.shape #Roll, pitch and yaw roll = row[2] pitch = row[3] yaw = row[4] #Face rectangle coords face_x = row[5] face_y = row[6] face_w = row[7] face_h = row[8] #Error correction if(face_x < 0): face_x = 0 if(face_y < 0): face_y = 0 if(face_w > image_w): face_w = image_w face_h = image_w if(face_h > image_h): face_h = image_h face_w = image_h #Crop the face from the image image_cropped = np.copy(image[face_y:face_y+face_h, face_x:face_x+face_w]) #Uncomment the lines below if you want to rescale the image to a particular size #to_size = 64 #image_rescaled = cv2.resize(image_cropped, (to_size,to_size), interpolation = cv2.INTER_AREA) #Uncomment the line below if you want to use adaptive histogram normalisation #clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(5,5)) #image_normalised = clahe.apply(image_rescaled) #Save the image #change "image_cropped" with the last uncommented variable name above cv2.imwrite(output_path, image_cropped) #Printing the information print "Counter: " + str(counter) print "iPath: " + input_path print "oPath: " + output_path print "Roll: " + str(roll) print "Pitch: " + str(pitch) print "Yaw: " + str(yaw) print "x: " + str(face_x) print "y: " + str(face_y) print "w: " + str(face_w) print "h: " + str(face_h) print "" #Increasing the counter counter = counter + 1 #if the file does not exits it return an exception else: raise ValueError('Error: I cannot find the file specified: ' + str(input_path)) #Once finished the iteration it closes the database c.close() if __name__ == "__main__": main()