-
Notifications
You must be signed in to change notification settings - Fork 5
/
aflw_example.py
140 lines (125 loc) · 5.46 KB
/
aflw_example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env python
##
# Massimiliano Patacchiola, Plymouth University 2016
# website: http://mpatacchiola.github.io/
# email: [email protected]
# 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
import os
os.mkdir('positive_ann')
#Change this paths according to your directories
images_path = "./flickr/"
storing_path = "./positive_ann/"
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
s = ''
#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 + row[0]
output_path = storing_path + str(counter) + ".png"
out = open('output.txt', 'w')
#If the file exist then open it
if(os.path.isfile(input_path) == True):
image = cv2.imread(input_path) #load in grayscale
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #load the colour version
#Image dimensions
image_h, image_w = image.shape[0], image.shape[1]
#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 = 32
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_normalised)
#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 ""
'''
s = s + str(counter) + "," + input_path + ","+str(face_x) + ","+str(face_y)+","+str(face_w)+","+str(face_h)+"\n"
#Increasing the counter
counter = counter + 1
if counter > 5000:
break
print(input_path)
#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()
out.write(s)
if __name__ == "__main__":
main()
out.close()