Add augmentation
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"python.pythonPath": "C:\\Users\\fayer\\anaconda3\\envs\\cv-env\\python.exe"
|
||||||
|
}
|
57
Facial_Image_Augmentation.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import sys
|
||||||
|
import cv2
|
||||||
|
import os
|
||||||
|
import numpy as np
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def facial_recognition_augmentation(label):
|
||||||
|
aug = 5
|
||||||
|
image_path = sys.path[0] + '/Facial_images/face_rec/train/' + label + '/'
|
||||||
|
imagelist = os.listdir(image_path)
|
||||||
|
|
||||||
|
for file_name in imagelist:
|
||||||
|
(nameWithoutExtention, extention) = os.path.splitext(os.path.basename(file_name))
|
||||||
|
|
||||||
|
if (extention==".jpg"):
|
||||||
|
|
||||||
|
#print(image_path+file_name)
|
||||||
|
inputImage = cv2.imread(image_path+file_name)
|
||||||
|
|
||||||
|
for i in range(aug):
|
||||||
|
rotate = random.randint(-8,8)
|
||||||
|
brightness = random.randint(-30, +30)
|
||||||
|
clahe = random.uniform(0.0, 1.0)
|
||||||
|
|
||||||
|
choice = random.randint(0, 10)
|
||||||
|
|
||||||
|
(h, w) = inputImage.shape[:2] #10
|
||||||
|
center = (w // 2, h // 2) #11
|
||||||
|
|
||||||
|
M = cv2.getRotationMatrix2D(center, rotate, 1.0) #12
|
||||||
|
inputImage = cv2.warpAffine(inputImage, M, (w, h)) #13
|
||||||
|
|
||||||
|
if (choice%3 == 1):
|
||||||
|
clahe = cv2.createCLAHE(clipLimit=clahe, tileGridSize=(8,8))
|
||||||
|
inputImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2LAB) # convert from BGR to LAB color space
|
||||||
|
l, a, b = cv2.split(inputImage) # split on 3 different channels
|
||||||
|
l2 = clahe.apply(l) # apply CLAHE to the L-channel
|
||||||
|
inputImage = cv2.merge((l2,a,b)) # merge channels
|
||||||
|
inputImage = cv2.cvtColor(inputImage, cv2.COLOR_LAB2BGR) # convert from LAB to BGR
|
||||||
|
elif(choice%3 == 2):
|
||||||
|
fI = inputImage/255.0
|
||||||
|
gamma = random.uniform(0.2, 0.4)
|
||||||
|
#inputImage = np.power(fI, gamma)
|
||||||
|
else:
|
||||||
|
cv2.addWeighted( inputImage, 0.5, inputImage, 0.5, brightness, inputImage)
|
||||||
|
|
||||||
|
choice_1 = random.randint(0, 10)
|
||||||
|
if (choice_1%2 == 1):
|
||||||
|
gauss = random.randint(1, 2)*2-1
|
||||||
|
|
||||||
|
inputImage = cv2.GaussianBlur(inputImage, (gauss,gauss), 0)
|
||||||
|
|
||||||
|
cv2.imwrite(image_path+nameWithoutExtention+"_aug"+str(i)+".jpg", inputImage)
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,11 @@ import os
|
||||||
import math
|
import math
|
||||||
import cv2
|
import cv2
|
||||||
import Facial_Recognition_Enrollment
|
import Facial_Recognition_Enrollment
|
||||||
|
import Facial_Image_Augmentation
|
||||||
|
|
||||||
|
|
||||||
def register_your_face(label):
|
def register_your_face(label):
|
||||||
num_cap = 50
|
num_cap = 10
|
||||||
|
|
||||||
path = sys.path[0] + '/Facial_images/face_rec/train/' + label
|
path = sys.path[0] + '/Facial_images/face_rec/train/' + label
|
||||||
|
|
||||||
|
@ -30,14 +31,4 @@ def register_your_face(label):
|
||||||
cap.release()
|
cap.release()
|
||||||
cv2.destroyAllWindows()
|
cv2.destroyAllWindows()
|
||||||
|
|
||||||
|
Facial_Image_Augmentation.facial_recognition_augmentation(label)
|
||||||
if __name__ == "__main__":
|
|
||||||
print("Face registration start...")
|
|
||||||
print()
|
|
||||||
label = input('Pleas enter your Name/Label: ')
|
|
||||||
register_your_face(label)
|
|
||||||
print("Data saved! Starting enrollment...")
|
|
||||||
print()
|
|
||||||
Facial_Recognition_Enrollment.enroll_face_dataset() # Need discuss and modify after intergrate with database.
|
|
||||||
print("Face registration completed!")
|
|
||||||
print()
|
|
||||||
|
|
|
@ -1,298 +0,0 @@
|
||||||
import cv2
|
|
||||||
import dlib
|
|
||||||
import numpy as np
|
|
||||||
import math
|
|
||||||
|
|
||||||
# Returns 8 points on the boundary of a rectangle
|
|
||||||
def getEightBoundaryPoints(h, w):
|
|
||||||
boundaryPts = []
|
|
||||||
boundaryPts.append((0,0))
|
|
||||||
boundaryPts.append((w/2, 0))
|
|
||||||
boundaryPts.append((w-1,0))
|
|
||||||
boundaryPts.append((w-1, h/2))
|
|
||||||
boundaryPts.append((w-1, h-1))
|
|
||||||
boundaryPts.append((w/2, h-1))
|
|
||||||
boundaryPts.append((0, h-1))
|
|
||||||
boundaryPts.append((0, h/2))
|
|
||||||
return np.array(boundaryPts, dtype=np.float)
|
|
||||||
|
|
||||||
|
|
||||||
# Constrains points to be inside boundary
|
|
||||||
def constrainPoint(p, w, h):
|
|
||||||
p = (min(max(p[0], 0), w - 1), min(max(p[1], 0), h - 1))
|
|
||||||
return p
|
|
||||||
|
|
||||||
# convert Dlib shape detector object to list of tuples
|
|
||||||
def dlibLandmarksToPoints(shape):
|
|
||||||
points = []
|
|
||||||
for p in shape.parts():
|
|
||||||
pt = (p.x, p.y)
|
|
||||||
points.append(pt)
|
|
||||||
return points
|
|
||||||
|
|
||||||
# Compute similarity transform given two sets of two points.
|
|
||||||
# OpenCV requires 3 pairs of corresponding points.
|
|
||||||
# We are faking the third one.
|
|
||||||
def similarityTransform(inPoints, outPoints):
|
|
||||||
s60 = math.sin(60*math.pi/180)
|
|
||||||
c60 = math.cos(60*math.pi/180)
|
|
||||||
|
|
||||||
inPts = np.copy(inPoints).tolist()
|
|
||||||
outPts = np.copy(outPoints).tolist()
|
|
||||||
|
|
||||||
# The third point is calculated so that the three points make an equilateral triangle
|
|
||||||
xin = c60*(inPts[0][0] - inPts[1][0]) - s60*(inPts[0][1] - inPts[1][1]) + inPts[1][0]
|
|
||||||
yin = s60*(inPts[0][0] - inPts[1][0]) + c60*(inPts[0][1] - inPts[1][1]) + inPts[1][1]
|
|
||||||
|
|
||||||
inPts.append([np.int(xin), np.int(yin)])
|
|
||||||
|
|
||||||
xout = c60*(outPts[0][0] - outPts[1][0]) - s60*(outPts[0][1] - outPts[1][1]) + outPts[1][0]
|
|
||||||
yout = s60*(outPts[0][0] - outPts[1][0]) + c60*(outPts[0][1] - outPts[1][1]) + outPts[1][1]
|
|
||||||
|
|
||||||
outPts.append([np.int(xout), np.int(yout)])
|
|
||||||
# Now we can use estimateRigidTransform for calculating the similarity transform.
|
|
||||||
tform = cv2.estimateAffinePartial2D(np.array([inPts]), np.array([outPts]))
|
|
||||||
return tform[0]
|
|
||||||
|
|
||||||
# Normalizes a facial image to a standard size given by outSize.
|
|
||||||
# Normalization is done based on Dlib's landmark points passed as pointsIn
|
|
||||||
# After normalization, left corner of the left eye is at (0.3 * w, h/3 )
|
|
||||||
# and right corner of the right eye is at ( 0.7 * w, h / 3) where w and h
|
|
||||||
# are the width and height of outSize.
|
|
||||||
def normalizeImagesAndLandmarks(outSize, imIn, pointsIn):
|
|
||||||
h, w = outSize
|
|
||||||
|
|
||||||
# Corners of the eye in input image
|
|
||||||
if len(pointsIn) == 68:
|
|
||||||
eyecornerSrc = [pointsIn[36], pointsIn[45]]
|
|
||||||
elif len(pointsIn) == 5:
|
|
||||||
eyecornerSrc = [pointsIn[2], pointsIn[0]]
|
|
||||||
|
|
||||||
# Corners of the eye in normalized image
|
|
||||||
eyecornerDst = [(np.int(0.3 * w), np.int(h/3)),
|
|
||||||
(np.int(0.7 * w), np.int(h/3))]
|
|
||||||
|
|
||||||
# Calculate similarity transform
|
|
||||||
tform = similarityTransform(eyecornerSrc, eyecornerDst)
|
|
||||||
imOut = np.zeros(imIn.shape, dtype=imIn.dtype)
|
|
||||||
|
|
||||||
# Apply similarity transform to input image
|
|
||||||
imOut = cv2.warpAffine(imIn, tform, (w, h))
|
|
||||||
|
|
||||||
# reshape pointsIn from numLandmarks x 2 to numLandmarks x 1 x 2
|
|
||||||
points2 = np.reshape(pointsIn, (pointsIn.shape[0], 1, pointsIn.shape[1]))
|
|
||||||
|
|
||||||
# Apply similarity transform to landmarks
|
|
||||||
pointsOut = cv2.transform(points2, tform)
|
|
||||||
|
|
||||||
# reshape pointsOut to numLandmarks x 2
|
|
||||||
pointsOut = np.reshape(pointsOut, (pointsIn.shape[0], pointsIn.shape[1]))
|
|
||||||
|
|
||||||
return imOut, pointsOut
|
|
||||||
|
|
||||||
def alignFace(imIn, faceRect, landmarkDetector, outSize):
|
|
||||||
# Corners of the eye in input image
|
|
||||||
(w, h) = outSize
|
|
||||||
landmarks = landmarkDetector(cv2.cvtColor(imIn, cv2.COLOR_BGR2RGB), faceRect)
|
|
||||||
pointsIn = np.array(dlibLandmarksToPoints(landmarks))
|
|
||||||
|
|
||||||
eyecornerSrc = [pointsIn[2], pointsIn[0]]
|
|
||||||
|
|
||||||
# Corners of the eye in normalized image
|
|
||||||
eyecornerDst = [(np.int(0.2 * w), np.int(h/3)),
|
|
||||||
(np.int(0.8 * w), np.int(h/3))]
|
|
||||||
|
|
||||||
# Calculate similarity transform
|
|
||||||
tform = similarityTransform(eyecornerSrc, eyecornerDst)
|
|
||||||
|
|
||||||
imIn = np.float32(imIn)/255.0
|
|
||||||
imOut = np.zeros(imIn.shape, dtype=imIn.dtype)
|
|
||||||
|
|
||||||
# Apply similarity transform to input image
|
|
||||||
imOut = cv2.warpAffine(imIn, tform, outSize)
|
|
||||||
|
|
||||||
imOut = np.uint8(imOut*255)
|
|
||||||
|
|
||||||
return imOut
|
|
||||||
|
|
||||||
|
|
||||||
# find the point closest to an array of points
|
|
||||||
# pointsArray is a Nx2 and point is 1x2 ndarray
|
|
||||||
def findIndex(pointsArray, point):
|
|
||||||
dist = np.linalg.norm(pointsArray-point, axis=1)
|
|
||||||
minIndex = np.argmin(dist)
|
|
||||||
return minIndex
|
|
||||||
|
|
||||||
|
|
||||||
# Check if a point is inside a rectangle
|
|
||||||
def rectContains(rect, point):
|
|
||||||
if point[0] < rect[0]:
|
|
||||||
return False
|
|
||||||
elif point[1] < rect[1]:
|
|
||||||
return False
|
|
||||||
elif point[0] > rect[2]:
|
|
||||||
return False
|
|
||||||
elif point[1] > rect[3]:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
# Calculate Delaunay triangles for set of points
|
|
||||||
# Returns the vector of indices of 3 points for each triangle
|
|
||||||
def calculateDelaunayTriangles(rect, points):
|
|
||||||
|
|
||||||
# Create an instance of Subdiv2D
|
|
||||||
subdiv = cv2.Subdiv2D(rect)
|
|
||||||
|
|
||||||
# Insert points into subdiv
|
|
||||||
for p in points:
|
|
||||||
subdiv.insert((p[0], p[1]))
|
|
||||||
|
|
||||||
# Get Delaunay triangulation
|
|
||||||
triangleList = subdiv.getTriangleList()
|
|
||||||
|
|
||||||
# Find the indices of triangles in the points array
|
|
||||||
delaunayTri = []
|
|
||||||
|
|
||||||
for t in triangleList:
|
|
||||||
# The triangle returned by getTriangleList is
|
|
||||||
# a list of 6 coordinates of the 3 points in
|
|
||||||
# x1, y1, x2, y2, x3, y3 format.
|
|
||||||
# Store triangle as a list of three points
|
|
||||||
pt = []
|
|
||||||
pt.append((t[0], t[1]))
|
|
||||||
pt.append((t[2], t[3]))
|
|
||||||
pt.append((t[4], t[5]))
|
|
||||||
|
|
||||||
pt1 = (t[0], t[1])
|
|
||||||
pt2 = (t[2], t[3])
|
|
||||||
pt3 = (t[4], t[5])
|
|
||||||
|
|
||||||
if rectContains(rect, pt1) and rectContains(rect, pt2) and rectContains(rect, pt3):
|
|
||||||
# Variable to store a triangle as indices from list of points
|
|
||||||
ind = []
|
|
||||||
# Find the index of each vertex in the points list
|
|
||||||
for j in range(0, 3):
|
|
||||||
for k in range(0, len(points)):
|
|
||||||
if(abs(pt[j][0] - points[k][0]) < 1.0 and abs(pt[j][1] - points[k][1]) < 1.0):
|
|
||||||
ind.append(k)
|
|
||||||
# Store triangulation as a list of indices
|
|
||||||
if len(ind) == 3:
|
|
||||||
delaunayTri.append((ind[0], ind[1], ind[2]))
|
|
||||||
|
|
||||||
return delaunayTri
|
|
||||||
|
|
||||||
# Apply affine transform calculated using srcTri and dstTri to src and
|
|
||||||
# output an image of size.
|
|
||||||
def applyAffineTransform(src, srcTri, dstTri, size):
|
|
||||||
|
|
||||||
# Given a pair of triangles, find the affine transform.
|
|
||||||
warpMat = cv2.getAffineTransform(np.float32(srcTri), np.float32(dstTri))
|
|
||||||
|
|
||||||
# Apply the Affine Transform just found to the src image
|
|
||||||
dst = cv2.warpAffine(src, warpMat, (size[0], size[1]), None,
|
|
||||||
flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REFLECT_101)
|
|
||||||
|
|
||||||
return dst
|
|
||||||
|
|
||||||
# Warps and alpha blends triangular regions from img1 and img2 to img
|
|
||||||
def warpTriangle(img1, img2, t1, t2):
|
|
||||||
# Find bounding rectangle for each triangle
|
|
||||||
r1 = cv2.boundingRect(np.float32([t1]))
|
|
||||||
r2 = cv2.boundingRect(np.float32([t2]))
|
|
||||||
|
|
||||||
# Offset points by left top corner of the respective rectangles
|
|
||||||
t1Rect = []
|
|
||||||
t2Rect = []
|
|
||||||
t2RectInt = []
|
|
||||||
|
|
||||||
for i in range(0, 3):
|
|
||||||
t1Rect.append(((t1[i][0] - r1[0]), (t1[i][1] - r1[1])))
|
|
||||||
t2Rect.append(((t2[i][0] - r2[0]), (t2[i][1] - r2[1])))
|
|
||||||
t2RectInt.append(((t2[i][0] - r2[0]), (t2[i][1] - r2[1])))
|
|
||||||
|
|
||||||
# Get mask by filling triangle
|
|
||||||
mask = np.zeros((r2[3], r2[2], 3), dtype=np.float32)
|
|
||||||
cv2.fillConvexPoly(mask, np.int32(t2RectInt), (1.0, 1.0, 1.0), 16, 0)
|
|
||||||
|
|
||||||
# Apply warpImage to small rectangular patches
|
|
||||||
img1Rect = img1[r1[1]:r1[1] + r1[3], r1[0]:r1[0] + r1[2]]
|
|
||||||
|
|
||||||
size = (r2[2], r2[3])
|
|
||||||
|
|
||||||
img2Rect = applyAffineTransform(img1Rect, t1Rect, t2Rect, size)
|
|
||||||
|
|
||||||
img2Rect = img2Rect * mask
|
|
||||||
|
|
||||||
# Copy triangular region of the rectangular patch to the output image
|
|
||||||
img2[r2[1]:r2[1]+r2[3], r2[0]:r2[0]+r2[2]] = img2[r2[1]:r2[1]+r2[3], r2[0]:r2[0]+r2[2]] * ((1.0, 1.0, 1.0) - mask)
|
|
||||||
img2[r2[1]:r2[1]+r2[3], r2[0]:r2[0]+r2[2]] = img2[r2[1]:r2[1]+r2[3], r2[0]:r2[0]+r2[2]] + img2Rect
|
|
||||||
|
|
||||||
# detect facial landmarks in image
|
|
||||||
def getLandmarks(faceDetector, landmarkDetector, im, FACE_DOWNSAMPLE_RATIO = 1):
|
|
||||||
points = []
|
|
||||||
imSmall = cv2.resize(im,None,
|
|
||||||
fx=1.0/FACE_DOWNSAMPLE_RATIO,
|
|
||||||
fy=1.0/FACE_DOWNSAMPLE_RATIO,
|
|
||||||
interpolation = cv2.INTER_LINEAR)
|
|
||||||
|
|
||||||
faceRects = faceDetector(imSmall, 0)
|
|
||||||
|
|
||||||
if len(faceRects) > 0:
|
|
||||||
maxArea = 0
|
|
||||||
maxRect = None
|
|
||||||
# TODO: test on images with multiple faces
|
|
||||||
for face in faceRects:
|
|
||||||
if face.area() > maxArea:
|
|
||||||
maxArea = face.area()
|
|
||||||
maxRect = [face.left(),
|
|
||||||
face.top(),
|
|
||||||
face.right(),
|
|
||||||
face.bottom()
|
|
||||||
]
|
|
||||||
|
|
||||||
rect = dlib.rectangle(*maxRect)
|
|
||||||
scaledRect = dlib.rectangle(int(rect.left()*FACE_DOWNSAMPLE_RATIO),
|
|
||||||
int(rect.top()*FACE_DOWNSAMPLE_RATIO),
|
|
||||||
int(rect.right()*FACE_DOWNSAMPLE_RATIO),
|
|
||||||
int(rect.bottom()*FACE_DOWNSAMPLE_RATIO))
|
|
||||||
|
|
||||||
landmarks = landmarkDetector(im, scaledRect)
|
|
||||||
points = dlibLandmarksToPoints(landmarks)
|
|
||||||
return points
|
|
||||||
|
|
||||||
# Warps an image in a piecewise affine manner.
|
|
||||||
# The warp is defined by the movement of landmark points specified by pointsIn
|
|
||||||
# to a new location specified by pointsOut. The triangulation beween points is specified
|
|
||||||
# by their indices in delaunayTri.
|
|
||||||
def warpImage(imIn, pointsIn, pointsOut, delaunayTri):
|
|
||||||
h, w, ch = imIn.shape
|
|
||||||
# Output image
|
|
||||||
imOut = np.zeros(imIn.shape, dtype=imIn.dtype)
|
|
||||||
|
|
||||||
# Warp each input triangle to output triangle.
|
|
||||||
# The triangulation is specified by delaunayTri
|
|
||||||
for j in range(0, len(delaunayTri)):
|
|
||||||
# Input and output points corresponding to jth triangle
|
|
||||||
tin = []
|
|
||||||
tout = []
|
|
||||||
|
|
||||||
for k in range(0, 3):
|
|
||||||
# Extract a vertex of input triangle
|
|
||||||
pIn = pointsIn[delaunayTri[j][k]]
|
|
||||||
# Make sure the vertex is inside the image.
|
|
||||||
pIn = constrainPoint(pIn, w, h)
|
|
||||||
|
|
||||||
# Extract a vertex of the output triangle
|
|
||||||
pOut = pointsOut[delaunayTri[j][k]]
|
|
||||||
# Make sure the vertex is inside the image.
|
|
||||||
pOut = constrainPoint(pOut, w, h)
|
|
||||||
|
|
||||||
# Push the input vertex into input triangle
|
|
||||||
tin.append(pIn)
|
|
||||||
# Push the output vertex into output triangle
|
|
||||||
tout.append(pOut)
|
|
||||||
|
|
||||||
# Warp pixels inside input triangle to output triangle.
|
|
||||||
warpTriangle(imIn, imOut, tin, tout)
|
|
||||||
return imOut
|
|
|
@ -1,290 +0,0 @@
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import math
|
|
||||||
import cv2
|
|
||||||
import dlib
|
|
||||||
import numpy as np
|
|
||||||
import Facial_Recognition_Render as fr
|
|
||||||
import _pickle as cPickle
|
|
||||||
import glob
|
|
||||||
import DBHelper
|
|
||||||
|
|
||||||
faceWidth = 320
|
|
||||||
faceHeight = 320
|
|
||||||
SKIP_FRAMES = 1
|
|
||||||
|
|
||||||
|
|
||||||
def alignFace(imFace, landmarks):
|
|
||||||
l_x = landmarks[39][0]
|
|
||||||
l_y = landmarks[39][1]
|
|
||||||
r_x = landmarks[42][0]
|
|
||||||
r_y = landmarks[42][1]
|
|
||||||
dy = r_y - l_y
|
|
||||||
dx = r_x - l_x
|
|
||||||
# Convert from radians to degrees
|
|
||||||
angle = math.atan2(dy, dx) * 180.0 / math.pi
|
|
||||||
|
|
||||||
eyesCenter = ((l_x + r_x) * 0.5, (l_y + r_y) * 0.5)
|
|
||||||
rotMatrix = cv2.getRotationMatrix2D(eyesCenter, angle, 1)
|
|
||||||
alignedImFace = np.zeros(imFace.shape, dtype=np.uint8)
|
|
||||||
alignedImFace = cv2.warpAffine(imFace, rotMatrix, (imFace.shape[1], imFace.shape[0]))
|
|
||||||
return alignedImFace
|
|
||||||
|
|
||||||
|
|
||||||
def face_detector_haarcascade(image):
|
|
||||||
grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
||||||
|
|
||||||
resize_fx = 1
|
|
||||||
resize_fy = 1
|
|
||||||
grey = cv2.resize(grey, dsize=None, fx=resize_fx, fy=resize_fy, interpolation=cv2.INTER_AREA)
|
|
||||||
|
|
||||||
pwd = sys.path[0]
|
|
||||||
classfier = cv2.CascadeClassifier(pwd + "/Facial_models/haarcascade_frontalface_alt2.xml")
|
|
||||||
|
|
||||||
faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=1, minSize=(16, 16))
|
|
||||||
|
|
||||||
if len(faceRects) > 0:
|
|
||||||
for faceRect in faceRects:
|
|
||||||
x, y, w, h = faceRect
|
|
||||||
x = int(x / resize_fx)
|
|
||||||
y = int(y / resize_fy)
|
|
||||||
w = int(w / resize_fx)
|
|
||||||
h = int(h / resize_fy)
|
|
||||||
cv2.rectangle(image, (x - 10, y - 10), (x + w + 10, y + h + 10), (0, 255, 0), 5)
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def face_detector_ssd(image):
|
|
||||||
pwd = sys.path[0]
|
|
||||||
net = cv2.dnn.readNetFromCaffe(pwd + "/Facial_models/deploy.prototxt",
|
|
||||||
pwd + "/Facial_models/res10_300x300_ssd_iter_140000_fp16.caffemodel")
|
|
||||||
|
|
||||||
resize = (300, 300)
|
|
||||||
confidence_thres = 0.65
|
|
||||||
|
|
||||||
blob = cv2.dnn.blobFromImage(cv2.resize(image, dsize=resize), 1.0, resize, (104.0, 177.0, 123.0))
|
|
||||||
# blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0))
|
|
||||||
|
|
||||||
net.setInput(blob)
|
|
||||||
|
|
||||||
detections = net.forward()
|
|
||||||
|
|
||||||
h, w, c = image.shape
|
|
||||||
|
|
||||||
for i in range(0, detections.shape[2]):
|
|
||||||
confidence = detections[0, 0, i, 2]
|
|
||||||
if confidence > confidence_thres:
|
|
||||||
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
|
|
||||||
(startX, startY, endX, endY) = box.astype("int")
|
|
||||||
text = "{:.2f}%".format(confidence * 100)
|
|
||||||
y = startY - 10 if startY - 10 > 10 else startY + 10
|
|
||||||
cv2.rectangle(image, (startX, startY), (endX, endY), (0, 255, 0), 5)
|
|
||||||
cv2.putText(image, text, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 1.00, (0, 255, 0), 3)
|
|
||||||
|
|
||||||
return image
|
|
||||||
|
|
||||||
|
|
||||||
def training_data_loader():
|
|
||||||
imagesFolder = sys.path[0] + "/Facial_images/face_rec/train/"
|
|
||||||
subfolders = []
|
|
||||||
|
|
||||||
for x in os.listdir(imagesFolder):
|
|
||||||
xpath = os.path.join(imagesFolder, x)
|
|
||||||
if os.path.isdir(xpath):
|
|
||||||
subfolders.append(xpath)
|
|
||||||
|
|
||||||
imagePaths = []
|
|
||||||
labels = []
|
|
||||||
labelsMap = {}
|
|
||||||
labelsMap[-1] = "unknown"
|
|
||||||
|
|
||||||
for i, subfolder in enumerate(subfolders):
|
|
||||||
labelsMap[i] = DBHelper.get_firstname(os.path.basename(subfolder)) + "_" + DBHelper.get_lastname(
|
|
||||||
os.path.basename(subfolder))
|
|
||||||
for x in os.listdir(subfolder):
|
|
||||||
xpath = os.path.join(subfolder, x)
|
|
||||||
if x.endswith('jpg') or x.endswith('pgm'):
|
|
||||||
imagePaths.append(xpath)
|
|
||||||
labels.append(i)
|
|
||||||
|
|
||||||
imagesFaceTrain = []
|
|
||||||
labelsFaceTrain = []
|
|
||||||
|
|
||||||
faceDetector = dlib.get_frontal_face_detector()
|
|
||||||
landmarkDetector = dlib.shape_predictor(sys.path[0] + "/Facial_models/shape_predictor_68_face_landmarks.dat")
|
|
||||||
|
|
||||||
for j, imagePath in enumerate(imagePaths):
|
|
||||||
im = cv2.imread(imagePath, 0)
|
|
||||||
imHeight, imWidth = im.shape[:2]
|
|
||||||
|
|
||||||
landmarks = fr.getLandmarks(faceDetector, landmarkDetector, im)
|
|
||||||
|
|
||||||
landmarks = np.array(landmarks)
|
|
||||||
|
|
||||||
if len(landmarks) == 68:
|
|
||||||
x1Limit = landmarks[0][0] - (landmarks[36][0] - landmarks[0][0])
|
|
||||||
x2Limit = landmarks[16][0] + (landmarks[16][0] - landmarks[45][0])
|
|
||||||
y1Limit = landmarks[27][1] - 3 * (landmarks[30][1] - landmarks[27][1])
|
|
||||||
y2Limit = landmarks[8][1] + (landmarks[30][1] - landmarks[29][1])
|
|
||||||
|
|
||||||
x1 = max(x1Limit, 0)
|
|
||||||
x2 = min(x2Limit, imWidth)
|
|
||||||
y1 = max(y1Limit, 0)
|
|
||||||
y2 = min(y2Limit, imHeight)
|
|
||||||
imFace = im[y1:y2, x1:x2]
|
|
||||||
|
|
||||||
alignedFace = alignFace(imFace, landmarks)
|
|
||||||
alignedFace = cv2.resize(alignedFace, (faceHeight, faceWidth))
|
|
||||||
|
|
||||||
imagesFaceTrain.append(np.float32(alignedFace) / 255.0)
|
|
||||||
labelsFaceTrain.append(labels[j])
|
|
||||||
|
|
||||||
return imagesFaceTrain, labelsFaceTrain, labelsMap
|
|
||||||
|
|
||||||
|
|
||||||
def training_recognizer(rec_type):
|
|
||||||
imagesFaceTrain, labelsFaceTrain, labelsMap = training_data_loader()
|
|
||||||
|
|
||||||
if (rec_type == 'LBPH'):
|
|
||||||
faceRecognizer = cv2.face.LBPHFaceRecognizer_create()
|
|
||||||
print("Training using LBPH Faces")
|
|
||||||
elif (rec_type == 'Eigen'):
|
|
||||||
faceRecognizer = cv2.face.EigenFaceRecognizer_create()
|
|
||||||
print("Training using Eigen Faces")
|
|
||||||
elif (rec_type == 'Fisher'):
|
|
||||||
faceRecognizer = cv2.face.FisherFaceRecognizer_create()
|
|
||||||
print("Training using Fisher Faces")
|
|
||||||
|
|
||||||
faceRecognizer.train(imagesFaceTrain, np.array(labelsFaceTrain))
|
|
||||||
faceRecognizer.write(sys.path[0] + '/Facial_models/face_rec_model.yml')
|
|
||||||
|
|
||||||
with open(sys.path[0] + '/Facial_models/labels_map.pkl', 'wb') as f:
|
|
||||||
cPickle.dump(labelsMap, f)
|
|
||||||
|
|
||||||
|
|
||||||
def face_recognition_inference(rec_type):
|
|
||||||
# testFiles = glob.glob(sys.path[0]+'/Facial_test_images/face_rec/test/*.jpg')
|
|
||||||
# testFiles.sort()
|
|
||||||
i = 0
|
|
||||||
correct = 0
|
|
||||||
error = 0
|
|
||||||
faceDetector = dlib.get_frontal_face_detector()
|
|
||||||
print(sys.path[0])
|
|
||||||
landmarkDetector = dlib.shape_predictor(sys.path[0] + '/Facial_models/shape_predictor_68_face_landmarks.dat')
|
|
||||||
|
|
||||||
if rec_type == 'LBPH':
|
|
||||||
faceRecognizer = cv2.face.LBPHFaceRecognizer_create()
|
|
||||||
print("Test using LBPH Faces")
|
|
||||||
elif rec_type == 'Eigen':
|
|
||||||
faceRecognizer = cv2.face.EigenFaceRecognizer_create()
|
|
||||||
print("Test using Eigen Faces")
|
|
||||||
elif rec_type == 'Fisher':
|
|
||||||
faceRecognizer = cv2.face.FisherFaceRecognizer_create()
|
|
||||||
print("Test using Fisher Faces")
|
|
||||||
|
|
||||||
faceRecognizer.read(sys.path[0] + '/Facial_models/face_rec_model.yml')
|
|
||||||
labelsMap = np.load(sys.path[0] + '/Facial_models/labels_map.pkl', allow_pickle=True)
|
|
||||||
|
|
||||||
cam = cv2.VideoCapture(0)
|
|
||||||
|
|
||||||
while DBHelper.get_power() == "on":
|
|
||||||
# imagePath = testFiles[i]
|
|
||||||
success, original = cam.read()
|
|
||||||
im = cv2.resize(original, (640, 480))
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
|
|
||||||
imHeight, imWidth = im.shape[:2]
|
|
||||||
|
|
||||||
landmarks = fr.getLandmarks(faceDetector, landmarkDetector, im)
|
|
||||||
landmarks = np.array(landmarks)
|
|
||||||
|
|
||||||
cond = False
|
|
||||||
cond2 = False
|
|
||||||
|
|
||||||
if len(landmarks) == 68:
|
|
||||||
x1Limit = landmarks[0][0] - (landmarks[36][0] - landmarks[0][0])
|
|
||||||
x2Limit = landmarks[16][0] + (landmarks[16][0] - landmarks[45][0])
|
|
||||||
y1Limit = landmarks[27][1] - 3 * (landmarks[30][1] - landmarks[27][1])
|
|
||||||
y2Limit = landmarks[8][1] + (landmarks[30][1] - landmarks[29][1])
|
|
||||||
|
|
||||||
x1 = max(x1Limit, 0)
|
|
||||||
x2 = min(x2Limit, imWidth)
|
|
||||||
y1 = max(y1Limit, 0)
|
|
||||||
y2 = min(y2Limit, imHeight)
|
|
||||||
imFace = im[y1:y2, x1:x2]
|
|
||||||
|
|
||||||
alignedFace = alignFace(imFace, landmarks)
|
|
||||||
alignedFace = cv2.resize(alignedFace, (faceHeight, faceWidth))
|
|
||||||
imFaceFloat = np.float32(alignedFace) / 255.0
|
|
||||||
|
|
||||||
predictedLabel = -1
|
|
||||||
predictedLabel, score = faceRecognizer.predict(imFaceFloat)
|
|
||||||
center = (int((x1 + x2) / 2), int((y1 + y2) / 2))
|
|
||||||
radius = int((y2 - y1) / 2.0)
|
|
||||||
text = '{} {}%'.format(labelsMap[predictedLabel], round(score, 5))
|
|
||||||
cv2.rectangle(original, (x1, y1), (x2, y2), (0, 255, 0), 5)
|
|
||||||
cv2.putText(original, text, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 3)
|
|
||||||
cond = True
|
|
||||||
|
|
||||||
if cond:
|
|
||||||
DBHelper.set_motor("on")
|
|
||||||
DBHelper.set_alarm("off")
|
|
||||||
elif not cond:
|
|
||||||
DBHelper.set_motor("off")
|
|
||||||
DBHelper.set_alarm("on")
|
|
||||||
|
|
||||||
cv2.imshow('Face Recognition Demo', original)
|
|
||||||
|
|
||||||
k = cv2.waitKey(10)
|
|
||||||
|
|
||||||
DBHelper.set_alarm("off")
|
|
||||||
DBHelper.set_motor("off")
|
|
||||||
cam.release()
|
|
||||||
cv2.destroyAllWindows()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
mode = 'test'
|
|
||||||
rec_type = 'LBPH' # 'LBPH' 'Fisher' 'Eigen'
|
|
||||||
|
|
||||||
if mode == 'train':
|
|
||||||
training_recognizer(rec_type)
|
|
||||||
elif mode == 'test':
|
|
||||||
face_recognition_inference(rec_type)
|
|
||||||
|
|
||||||
# video process (keep it in case if needed)
|
|
||||||
'''
|
|
||||||
cameraCapture = cv2.VideoCapture(1)
|
|
||||||
success, frame = cameraCapture.read()
|
|
||||||
|
|
||||||
while success and cv2.waitKey(1) == -1:
|
|
||||||
success, frame = cameraCapture.read()
|
|
||||||
face_detector_ssd(frame)
|
|
||||||
cv2.imshow("video", frame)
|
|
||||||
|
|
||||||
cameraCapture.release()
|
|
||||||
cv2.destroyAllWindows()
|
|
||||||
'''
|
|
||||||
|
|
||||||
# image process (keep it in case if needed)
|
|
||||||
'''
|
|
||||||
image_name = "8.jpg"
|
|
||||||
split_name = image_name.split(".")
|
|
||||||
|
|
||||||
image_read_path = sys.path[0]+"/Facial_test_images/"+image_name
|
|
||||||
image_save_path = sys.path[0]+"/Facial_test_images/output/"+split_name[0]+"_result."+split_name[1]
|
|
||||||
|
|
||||||
image = cv2.imread(image_read_path)
|
|
||||||
|
|
||||||
image = face_detector_ssd(image)
|
|
||||||
image = face_detector_haarcascade(image)
|
|
||||||
|
|
||||||
print(image_save_path)
|
|
||||||
|
|
||||||
cv2.imwrite(image_save_path, image)
|
|
||||||
cv2.imshow("result", image)
|
|
||||||
cv2.waitKey()
|
|
||||||
cv2.destroyAllWindows()
|
|
||||||
'''
|
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 76 KiB |
BIN
Facial_images/face_rec/train/User_1/0_aug0.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
Facial_images/face_rec/train/User_1/0_aug1.jpg
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
Facial_images/face_rec/train/User_1/0_aug2.jpg
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
Facial_images/face_rec/train/User_1/0_aug3.jpg
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
Facial_images/face_rec/train/User_1/0_aug4.jpg
Normal file
After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 84 KiB |
BIN
Facial_images/face_rec/train/User_1/1_aug0.jpg
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
Facial_images/face_rec/train/User_1/1_aug1.jpg
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
Facial_images/face_rec/train/User_1/1_aug2.jpg
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
Facial_images/face_rec/train/User_1/1_aug3.jpg
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
Facial_images/face_rec/train/User_1/1_aug4.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 86 KiB |
BIN
Facial_images/face_rec/train/User_1/2_aug0.jpg
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
Facial_images/face_rec/train/User_1/2_aug1.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
Facial_images/face_rec/train/User_1/2_aug2.jpg
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
Facial_images/face_rec/train/User_1/2_aug3.jpg
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
Facial_images/face_rec/train/User_1/2_aug4.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
BIN
Facial_images/face_rec/train/User_1/3_aug0.jpg
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
Facial_images/face_rec/train/User_1/3_aug1.jpg
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
Facial_images/face_rec/train/User_1/3_aug2.jpg
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
Facial_images/face_rec/train/User_1/3_aug3.jpg
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
Facial_images/face_rec/train/User_1/3_aug4.jpg
Normal file
After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 84 KiB |
BIN
Facial_images/face_rec/train/User_1/4_aug0.jpg
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
Facial_images/face_rec/train/User_1/4_aug1.jpg
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
Facial_images/face_rec/train/User_1/4_aug2.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
Facial_images/face_rec/train/User_1/4_aug3.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
Facial_images/face_rec/train/User_1/4_aug4.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 75 KiB |
BIN
Facial_images/face_rec/train/User_1/5_aug0.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
Facial_images/face_rec/train/User_1/5_aug1.jpg
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
Facial_images/face_rec/train/User_1/5_aug2.jpg
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
Facial_images/face_rec/train/User_1/5_aug3.jpg
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
Facial_images/face_rec/train/User_1/5_aug4.jpg
Normal file
After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 76 KiB |
BIN
Facial_images/face_rec/train/User_1/6_aug0.jpg
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
Facial_images/face_rec/train/User_1/6_aug1.jpg
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
Facial_images/face_rec/train/User_1/6_aug2.jpg
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
Facial_images/face_rec/train/User_1/6_aug3.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
Facial_images/face_rec/train/User_1/6_aug4.jpg
Normal file
After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 76 KiB |
BIN
Facial_images/face_rec/train/User_1/7_aug0.jpg
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
Facial_images/face_rec/train/User_1/7_aug1.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
Facial_images/face_rec/train/User_1/7_aug2.jpg
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
Facial_images/face_rec/train/User_1/7_aug3.jpg
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
Facial_images/face_rec/train/User_1/7_aug4.jpg
Normal file
After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
BIN
Facial_images/face_rec/train/User_1/8_aug0.jpg
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
Facial_images/face_rec/train/User_1/8_aug1.jpg
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
Facial_images/face_rec/train/User_1/8_aug2.jpg
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
Facial_images/face_rec/train/User_1/8_aug3.jpg
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
Facial_images/face_rec/train/User_1/8_aug4.jpg
Normal file
After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 75 KiB |