Commit 25e67e3c authored by Maria Kleppestø Mcculloch's avatar Maria Kleppestø Mcculloch
Browse files

First version

parent e663e61f
# Tested with Python 3.8.3
import os # Only used in usage_example
import sys # Only used in cli_main
import cv2 # Tested with opencv-python 4.4.0.44
import dlib # Tested with dlib 19.22.0
import numpy as np # Tested with numpy 1.18.5
def cli_main():
"""CLI entry function for usage_example"""
usage_example(
image_dir=sys.argv[1]
if len(sys.argv) > 1 else "images",
dlib_landmark_detector_path=sys.argv[2]
if len(sys.argv) > 2 else
"shape_predictor_68_face_landmarks.dat"
)
def usage_example(image_dir: str, dlib_landmark_detector_path: str):
"""The dlib_landmark_detector_path should point to the shape_predictor_68_face_landmarks.dat model
file, which is available here: http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
Note that the license of this model's training data excludes commercial use.
You can find additional information in the general Dlib landmark detector Python example,
available at: http://dlib.net/face_landmark_detection.py.html
"""
dlib_landmark_detector = dlib.shape_predictor(dlib_landmark_detector_path)
image_filenames = os.listdir(image_dir)
quality_scores = []
for image_filename in image_filenames:
image_path = os.path.join(image_dir, image_filename)
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
quality_score = compute_illumination_uniformity(image, dlib_landmark_detector)
quality_scores.append(quality_score)
print(f"Count={len(quality_scores)}"
f" Min={np.min(quality_scores)} Max={np.max(quality_scores)} Mean={np.mean(quality_scores)}")
def compute_illumination_uniformity(image, dlib_landmark_detector):
# Note that this example assumes that the image is already cropped to the face region.
# Step 1: Find the eye center points and the inter-eye center point.
dlib_landmarks = dlib_landmark_detector(image, dlib.rectangle(0, 0, image.shape[1],
image.shape[0]))
left_eye_center = (dlib_landmarks.part(37) + dlib_landmarks.part(40)) * 0.5
right_eye_center = (dlib_landmarks.part(43) + dlib_landmarks.part(46)) * 0.5
inter_eye_center = (left_eye_center + right_eye_center) * 0.5
# Step 2: Determine the slope and intercept of the dividing line.
slope = get_slope(left_eye_center, right_eye_center)
if slope != 0:
intercept = inter_eye_center.y - (slope * inter_eye_center.x)
else:
intercept = inter_eye_center.x
# Step 3: Establish disjunct per-pixel masks for the left and right half.
y_values = np.zeros(image.shape[:2])
if slope != 0:
y_values[:, :] = np.arange(image.shape[0]).reshape(image.shape[0], 1)
right_mask = y_values > (np.arange(image.shape[1]) * slope + intercept)
else:
y_values[:, :] = np.arange(image.shape[0])
right_mask = y_values > intercept
left_mask = np.logical_not(right_mask)
# Step 4: Compute the normalized histograms for the halves.
left_histogram = get_normalized_histogram(image, left_mask)
right_histogram = get_normalized_histogram(image, right_mask)
# Step 5: Return the scaled sum of the element-wise minimum of the normalized histograms as the
#quality score.
min_histogram = np.minimum(left_histogram, right_histogram)
quality_score = int(100 * np.sum(min_histogram))
return quality_score
def get_slope(point1, point2):
return -(point2.x - point1.x) / (point2.y - point1.y) if point2.y != point1.y else 0
def get_normalized_histogram(image, mask):
histogram = cv2.calcHist([image], [0], mask.astype(np.uint8), [256], [0, 256])
histogram = histogram.flatten()
histogram /= np.sum(histogram)
return histogram
if __name__ == "__main__":
cli_main()
\ No newline at end of file
......@@ -8,27 +8,77 @@ bh = BaseHandler(51, 5)
qe = QualityEvaluator()
qual_scores = qe.getBrisqueValues();
sim_scores = np.load('data/sim_scores_noise.npy')
#qual_scores = qe.getBrisqueValues()
#qual_scores_f = qe.getFocusValues()
#qual_scores_s_p = qe.getSharpnessValues("P")
#qual_scores_s_g = qe.getSharpnessValues("gp")
#qual_scores_s_psp = qe.getSharpnessValues("psp")
gens = qe.getAllGenuine(bh, sim_scores)
imps = qe.getAllImposters(bh, sim_scores)
qual_scores = np.load('data/quality_focus_norm_0.npy')
sim_scores = np.load('data/sim_scores_0_noise.npy')
# Balck Purple Blue DarkGreen Red LightGreen BlackDots
'''
sim_scores_p = np.load('data/sim_scores.npy')
sim_scores_psp = np.load('data/sim_scores_psp_noise.npy')
gens_p = qe.getAllGenuine(bh, sim_scores_p)
imps_p = qe.getAllImposters(bh, sim_scores_p)
'''
gens_g = qe.getAllGenuine(bh, sim_scores)
imps_g = qe.getAllImposters(bh, sim_scores)
print("Number of imps: ", len(imps_g))
'''
gens_psp = qe.getAllGenuine(bh, sim_scores_psp)
imps_psp = qe.getAllImposters(bh, sim_scores_psp)
gen_score_aggr = [gens_p,gens_g,gens_psp]
imp_score_aggr = [imps_p,imps_g, imps_psp]
gens = []
imps = []
for i in range(len(gen_score_aggr)):
gg = gen_score_aggr[i]
ii = imp_score_aggr[i]
for j in range(len(gg)):
gens.append(gg[j])
for j in range(len(ii)):
imps.append(ii[j])
'''
# Balck Purple Blue DarkGreen Red LightGreen BlackDots
colour = [ "Kitty", "Disco", "Rabbit","Dog" , "Card", "Mickey", "Mask"]
#print(qual_scores.shape, " ", max(qual_scores), " ", min(qual_scores))
# Genereate sim scores
for i in range(1, 5):
for i in range(1, 6):
#gq,iq = qe.removeLowQualValues(sim_scores, qual_scores, bh, i)
g_p,i_p = qe.removeLowQualValues(sim_scores, qual_scores, bh, i)
#g_p, i_p = qe.prepare(gq,iq)
print(max(i_p), " " , min(i_p))
print(len(g_p), " ", len(i_p))
#qe.plotDET(g_p, i_p, colour[i] )
if len(i_p) != 0 and len(g_p) != 0:
print(i, ":")
print("Have gorund: " ,max(i_p) > min(i_p))
print(len(g_p), " ", len(i_p))
qe.plotDET(g_p, i_p, colour[i] )
else:
print(i, ": Empty: ", len(g_p), " || ", len(i_p))
qe.plotDET(gens, imps, colour[1] )
qe.showDET()
\ No newline at end of file
'''
gens, imps = gens_g, imps_g
print(len(gens), " ", len(imps))
print(max(imps), " " , min(gens))
qe.plotDET(gens, imps,"Kitty" )
'''
qe.showDET()
......@@ -7,7 +7,9 @@ from insightface.data import get_image as ins_get_image
# Vars
#path = '/Users/krunal/Desktop/code/database'
projectpath = 'C:/Users/maria/Desktop/Biometrics/TermPaper/imt4126-biometricqualitymetrics/'
imgsdir = 'img/Casia_Converted_Noise/Gaussian/'
imgsdir = 'img/Casia_Converted_Noise/Gaussian_Salted/'
imgsdir_other = 'img/Casia_Converted/'
imgsdir_other_other = 'img/Casia_Converted_Noise/ScrambledEggs_l/'
# TODO change names
imgsnr = 51
......@@ -32,13 +34,20 @@ handler.prepare(ctx_id=0)
for i in range (0, imgsnr):
subjectnr = '00' + str(i) if i<10 else '0' + str(i)
subjectdir = subjectnr + '/'
fullpath = projectpath + imgsdir + subjectdir
print("Path" + imgsdir + subjectdir)
img_obs.append([])
print("Read in for: " + str(i) + "-th subject")
for j in range(0, change_me):
if j == 0: fullpath = projectpath + imgsdir_other + subjectdir
elif j ==1: fullpath = projectpath + imgsdir_other_other + subjectdir
else: fullpath = projectpath + imgsdir + subjectdir
#fullpath = projectpath + imgsdir + subjectdir
imgname = subjectnr + '_' + str(j)
#print(subjectdir + name)
#convert(projectpath + 'Casia/' + subjectdir + imgname + ".bmp", imgname + ".jpg", fullpath )
......@@ -70,7 +79,9 @@ for i in range(0, len(img_obs)):
# Save to file
new_array = np.array(sim_scores)
np.save("data/sim_scores_noise.npy", new_array)
spath = "data/sim_scores_0_noise.npy"
print("Saving to: ", spath)
np.save(spath, new_array)
......
function computeBrisque()
high_path = "img/Casia_Converted";
fullpath = "img/Casia_Converted";
imgsdir = "img/Casia_Converted_Noise/Gaussian_Salted/"
imgsdir_other = "img/Casia_Converted/"
imgsdir_other_other = "img/Casia_Converted_Noise/ScrambledEggs_l/"
% For all subjects
for i =1:51
if (i-1) <10
nr = "0" + (i-1);
else
......@@ -12,7 +19,15 @@ function computeBrisque()
sub_nr = "0" + nr;
for j=1:5
if (j == 1)
high_path = imgsdir_other;
elseif(j ==2)
high_path = imgsdir_other_other ;
else
high_path = imgsdir;
end
path = high_path + '/' + sub_nr + '/' + sub_nr + '_' + (j-1) + '.jpg';
img = imread(path);
......
import cv2
import numpy as np
from insightface.app import FaceAnalysis
from insightface.data import get_image as ins_get_image
from matplotlib import pyplot as plt
import scipy
from qualityEvaluation import QualityAssesmenet
#projectpath = 'C:/Users/maria/Desktop/Biometrics/TermPaper/imt4126-biometricqualitymetrics/'
#imgsdir = 'img/Casia_Converted_Noise/Gaussian_Poisson/'
#imgsdir = 'img/Casia_Converted/'
#fullpath = projectpath + "img1" #imgsdir + "001/001_1"
#fullpath = projectpath + imgsdir + "001/001_1"
class Image_Preparator:
def __init__(self) -> None:
self.app = FaceAnalysis(allowed_modules=['detection']) # enable detection model only
self.app.prepare(ctx_id=0, det_size=(640, 640))
pass
def read_in(self, path: str):
image = ins_get_image(path)
return image
def segment(self, image):
face = self.app.get(image)
box = face[0].bbox.astype(np.int)
# xy
# Top left (box[0], box[1]), yl xt,
# Bottom Left (box[2], box[3]) yr, xb
# xt:xb yl:yr
crop_img = image[box[1]:box[3], box[0]:box[2]].copy()
return crop_img
def segment_square(self, image):
face = self.app.get(image)
box = face[0].bbox.astype(np.int)
# Determine smallest dimension
x = box[3] - box[1]
y = box[2] - box[0]
diff = abs(x-y)
if (np.mod(diff,2)!=0):
diff1 = int(diff/2) +1
diff2 = int(diff/2)
else:
diff1 = int(diff/2)
diff2 = int(diff/2)
#Mod smallest dimension
if x < y:
box[3] = box[3] +diff1
box[1] = box[1] -diff2
elif y<x:
box[2] = box[2] + diff1
box[0] = box[0] - diff2
return image[box[1]:box[3], box[0]:box[2]].copy()
def draw(self, img, dest):
faces = self.app.get(img)
rimg = self.app.draw_on(img, faces)
cv2.imwrite(dest, rimg)
def luimanence(self, image):
lum = np.zeros(shape=(len(image), len(image[0])))
for i in range(len(image)):
for j in range(len(image[0])):
convert = False
t = 0.04045
npx = [0,0,0]
# Normalize each pixel
for k in range(3):
nc = image[i][j][k]/255
if(nc <= t): convert = True
# Perform Gamma Inversion
if(convert):
if(nc > t):
nc = (nc + 0.055)/1.0558
else:
nc = nc/ 12.92
nc = pow(nc, 2.4)
npx[k] = nc
# Calculate luiminance
#if sum(npx) > 1: print(npx)
lum[i][j] = 0.2126*npx[0]+ 0.7152*npx[1] + 0.0722*npx[2]
return lum
def ColorConvert(V):
return -1
def calculate(projectpath, subnr, samplenr, flavor):
# Variables
q = QualityAssesmenet()
d = Image_Preparator()
f_list = []
s_list = []
# For each subject
for i in range (0, subnr):
subjectnr = '00' + str(i) if i<10 else '0' + str(i)
subjectdir = subjectnr + '/'
# Print("Path" + imgsdir + subjectdir)
print("Read in for: " + str(i) + "-th subject")
# Focus values
f_list.append([])
# Sharpness values
s_list.append([])
for j in range(0, samplenr):
imgsdir = 'img/Casia_Converted_Noise/Gaussian_Salted/'
imgsdir_other = 'img/Casia_Converted/'
imgsdir_other_other = 'img/Casia_Converted_Noise/ScrambledEggs_l/'
if j == 0: fullpath = projectpath + imgsdir_other + subjectdir
elif j ==1: fullpath = projectpath + imgsdir_other_other + subjectdir
else: fullpath = projectpath + imgsdir + subjectdir
imgname = subjectnr + '_' + str(j)
im = d.read_in(fullpath + imgname)
# Get segments
crop = d.segment(im)
square= d.segment_square(im)
#cv2.imwrite( "./tesytes" , im)
lum = d.luimanence(crop)
lum_s = d.luimanence(square)
f = q.de_focus(lum)
s = q.Sharpness(lum_s)
f_list[i].append(f)
s_list[i].append(s)
# Save to file
f_arr = np.array(f_list)
s_arr = np.array(s_list)
spath = "data/quality_sharpness_" + flavor+ ".npy"
fpath = "data/quality_focus_" + flavor+ ".npy"
print("Avg s: ", np.mean(s_arr))
print("Std s: ", np.std(s_arr))
print("Avg f: ", np.mean(f_arr))
print("Std f: ", np.std(f_arr))
#np.save(fpath, f_arr)
#np.save(spath, s_arr)
f_norm = q.quality_normalize(f_arr)
s_norm = q.quality_normalize(s_arr)
fpath = "data/quality_focus_norm_" + flavor+ ".npy"
print("Saving to: ", fpath)
np.save(fpath, f_norm)
spath = "data/quality_sharpness_norm_" + flavor+ ".npy"
print("Saving to: ", spath)
np.save(spath, s_norm)
print("-----------------------------------------------")
projectpathh = 'C:/Users/maria/Desktop/Biometrics/TermPaper/imt4126-biometricqualitymetrics/'
flavor = ["Normal", "Gaussian", "Poisson", "GP", "PG", "PSP"]
calculate(projectpathh, 51, 5, "0")
function generateArtificalData(Path)
high_path_destination = "img/Casia_Converted_Noise/Gaussian";
high_path_destination = "img/Casia_Converted_Noise/Gaussian_Salted";
high_path_source = "img/Casia_Converted";
% For all subjects
for i =1:51
......@@ -13,6 +13,7 @@ function generateArtificalData(Path)
sub_nr = "0" + nr;
mkdir(high_path_destination + '/' + sub_nr )
for j=1:5
imgpath = '/' + sub_nr + '/' + sub_nr + '_' + (j-1) + '.jpg';
......@@ -22,9 +23,13 @@ function generateArtificalData(Path)
img = imread(path_source);
i = imnoise(img,'gaussian');
img = imnoise(img,'gaussian');
%img = imnoise(img,'speckle');
img = imnoise(img,'salt & pepper');
%img = imnoise(img,'poisson');
imwrite(i, high_path_destination + imgpath)
imwrite(img, high_path_destination + imgpath)
%J = imnoise(I,'gaussian')
%J = imnoise(I,'gaussian',m)
......
high_path_destination = "img/Casia_Converted_Noise/Poisson_Gaussian";
high_path_source = "img/Casia_Converted";
imgpath = '/001/001_0.jpg';
path_source = high_path_source + imgpath;
img = imread(path_source);
img = imnoise(img,'gaussian');
img = imnoise(img,'speckle');
img = imnoise(img,'salt & pepper');
img = imnoise(img,'poisson');
disp("jhh")
figure
imshow(img)
imgpath2 = '/004/004_0.jpg';
path_source2 = high_path_source + imgpath2;
img3 = imread(path_source2);
img3 = imnoise(img3,'gaussian');
img3 = imnoise(img3,'speckle');
img3 = imnoise(img3,'salt & pepper');
img3 = imnoise(img3,'poisson');
figure
imshow(img3)
\ No newline at end of file
......@@ -5,6 +5,11 @@ import numpy as np
from utils.baseScore import BaseHandler
from DET.DET import DET
import matplotlib.pyplot as mpl
from insightface.app import FaceAnalysis
from insightface.data import get_image as ins_get_image
from matplotlib import pyplot as plt
import scipy
......@@ -31,9 +36,20 @@ class QualityEvaluator:
data[i][j] = float(data_s[i][ j])
return data
def getFocusValues(self):
path_brisque = "data/quality_focus_norm.npy"
return np.load(path_brisque)
def getSharpnessValues(self, flavor="P"):
if flavor == "PSP" : path_brisque = "data/quality_sharpness_norm_PSP.npy"
elif flavor == "P": path_brisque = "data/quality_sharpness_norm.npy"
elif flavor == "GP": path_brisque = "data/quality_sharpness_norm_gp.npy"
elif flavor == "G": path_brisque = "data/quality_sharpness_norm_g.npy"
return np.load(path_brisque)
# Rejection set
......@@ -114,8 +130,9 @@ class QualityEvaluator:
return int((q1+q2)/2)
def eval_quality(self, q1: int, q2:int, k: int) -> bool:
return True
#return self.H(q1, q2) == k
#return True
return (q1==k or q2==k)
return self.H(q1, q2) == k
def removeLowQualValues(self, sim_scores: list, quality_scores: list, bh: BaseHandler, ql:int) -> list:
#g_s, i_s = prepare(getAllGenuine(bh, sim_scores), getAllImposters(bh, sim_scores))
......@@ -136,7 +153,7 @@ class QualityEvaluator:
#print("S score: " + s[1], "|| ", i, " ", j, " x ", k, " ", l)
if (self.eval_quality(q1, q2, ql)):
if(i==k):
if k<l: g_s_new.append(float(s[0]))
if j<l: g_s_new.append(float(s[0]))
else:
i_s_new.append(float(s[0]))
......@@ -164,3 +181,78 @@ class QualityEvaluator:
return gl,il
class QualityAssesmenet:
def __init__(self) -> None:
self.a = 0.0606690309518936
self.b = 0.01
self.c = 5.292513593982813
self.d = 1
pass
def quality_normalize(self, m):
f_norm = m
for i in range(len(f_norm)):
for j in range(len(f_norm[0])):
if f_norm[i][j] < 20: f_norm[i][j] = 1
if f_norm[i][j] < 40 and f_norm[i][j] >= 20: f_norm[i][j] = 2
if f_norm[i][j] < 60 and f_norm[i][j] >= 40: f_norm[i][j] = 3
if f_norm[i][j] < 80 and f_norm[i][j] >= 60: f_norm[i][j] = 4
if f_norm[i][j] >= 80: f_norm[i][j] = 5
return f_norm
def de_focus(self, luiminance_map):
Bs = self.mean_filter(luiminance_map)
Ds = abs(Bs - luiminance_map)
dim = Ds.shape
Blurloss = (sum(sum(Ds)))/(dim[0]*dim[1])
return (1 - self.SIGMOID(Blurloss, self.a, self.b))*100
#return Blurloss
def mean_filter(self, arr, filtersize=3):
w = np.full((filtersize