import sys import os import cv2 import json import base64 import time import numpy as np from copy import copy, deepcopy from matplotlib import pyplot as plt class FaceClass(object): backend = None model = None imgs = {} encs = {} crops = {} visual = 0 files = {} boxes = [] jsonx = "" errstr = "" vidcap = None tree = { "device1":"NA", "device2":"NA", "threshold":380, "device1_qual":0.5, "device2_qual":0.5, "score":0, "detectms":0, "comparems":0 } def json2obj(self,jsonx): print(jsonx) self.jsonx = jsonx return json.loads(jsonx) # # # # ##### # ## # # # # # # # # # # # # # # # # # ## # # # # # # # # Prep tasks def init(self, backend=None, mod=None): self.backend = backend self.model = mod return None def clear(self): self.imgs = {} self.files = {} self.faces = {} # #### ## ##### # # # # # # # # # # # # # # # # # ###### # # # # # # # # # ###### #### # # ##### # @doc Load a pic using the device label def load1(self, name,fname): print(" Loading image '%s' from file %s" % (name, fname)) if not os.path.isfile(fname): print(" * file not found: %s" % (fname)) return '{ "status":442565, "remark":"file name not found", "guilty_param":"fname", "guilty_value":"%s" }' % (fname) self.files[name] = fname self.imgs[name] = cv2.imread(fname) print(" Loaded %s from file %s" % (name, fname)) return '{ "status":0, "remark":"OK", "name":"%s", "fname":"%s" }' % (name,fname) def load2(self, name1,fname1,name2,fname2): print("FaceClass loading files ....................... ") self.load1(name1,fname1) self.load1(name2,fname2) return '{ "status":0, "remark":"OK", "name1":"%s", "fname1":"%s", "name2":"%s", "fname2":"%s" }' % (name1,fname1,name2,fname2) ##### ###### ##### ###### #### ##### # # # # # # # # # # ##### # ##### # # # # # # # # # # # # # # # # # ##### ###### # ###### #### # # Find all faces - put resul in self.boxes - an array of rectangles where faces are def detect(self,name): self.faces = [] return '{ "status":88241, "remark":"override this!" }' # @doc find the biggest face in the named image # Imge has origin at top left and value are b = [ X1, Y1, X2, Y2 ] def ideal(self, name, rectname, cropname): found = -1 biggest = -1 self.crops[name] = [] print("** faceclass::ideal ... %s with %d boxes => %s + %s" % (name, len(self.boxes), rectname, cropname )) # resize boxes for i in range(len(self.boxes)): b = self.boxes[i] area = (b[2]-b[0]) * (b[3]-b[1]) print(b,area) if area > biggest: found = i biggest = area if found < 0: return '{ "status":8572421, "remark":"no ideal face", "guilty_param":"name", "guilty_value":"%s" }' % name b = self.boxes[found] # extract crops and highlights - colours are BGR self.imgs[cropname] = self.crop(name,b[0],b[1],b[2],b[3]) self.crops[name].append(self.imgs[cropname]) self.imgs[rectname] = deepcopy(self.imgs[name]) #print(self.imgs[name]) #print(self.imgs[rectname]) for bs in self.boxes: self.rect(rectname,bs[0],bs[1],bs[2],bs[3],(255,0,0)) self.rect(rectname,b[0],b[1],b[2],b[3],(0,255,0)) return '{ "status":0, "remark":"OK", "faces":%d, "ideal_ix":%s, "ideal_area":%d, "boxes":%s }' % (len(self.boxes), found, biggest, json.dumps(self.boxes)) # Find landmarks def landmarks(self): return '{ "status":88243, "remark":"override this!" }' # Find metadata (age etc) def metadata(self,name): return '{ "status":88244, "remark":"override this!" }' #### #### # # ##### ## ##### ###### # # # # ## ## # # # # # # # # # # # ## # # # # # # # ##### # # # # # ##### ###### ##### # # # # # # # # # # # # # #### #### # # # # # # # ###### # Match two faces def compare(self,name1,name2): return '{ "status":88245, "remark":"override this!" }' # @doc This does everything for you. # If you are smartserv, "crowd" means cam and "govid" means regula pic def crowd_vs_govid(self, name1,file1,scale1, name2,file2,scale2): print("##1##") if self.json2obj(self.load1(name1, file1))["status"] != 0: return self.jsonx if scale1 !=0: self.shrink(name1,scale1) if self.json2obj(self.detect(name1))["status"] != 0: return self.jsonx self.boxscale(name1,0.3) if self.json2obj(self.ideal(name1,name1+"_rect",name1+"_crop"))["status"] != 0: return self.jsonx self.save(name1,"/tmp") self.save(name1+"_rect","/tmp") self.save(name1+"_crop","/tmp") print(self.imgs.keys()) print("##2##") if self.json2obj(self.load1(name2, file2))["status"] != 0: return self.jsonx if scale2 !=0: self.shrink(name2,scale2) self.save(name2,"/tmp") if self.json2obj(self.detect(name2))["status"]!=0: return self.jsonx self.boxscale(name2,0.3) if self.json2obj(self.ideal(name2,name2+"_rect",name2+"_crop"))["status"] != 0: return self.jsonx self.save(name2,"/tmp") self.save(name2+"_rect","/tmp") self.save(name2+"_crop","/tmp") print(self.imgs.keys()) print("##R##") jsonstr = self.compare(name1+"_crop",name2+"_crop") print(jsonstr) return jsonstr # @doc This does deomgraphic examination on a pic. # If you are smartserv, "crowd" means cam and "govid" means regula pic def traffic(self, name, file, scale=0): print("##1##") jsons = [] if self.json2obj(self.load1(name, file))["status"] != 0: return self.jsonx if scale !=0: self.shrink(name,scale) if self.json2obj(self.detect(name))["status"] != 0: return self.jsonx for i in range(len(self.boxes)): b = self.boxes[i] print(">>>>" , b) analysis = self.metadata(self.imgs[name][b[0]:b[0]+b[1],b[2]:b[2]+b[3]]) jsons.append(analysis) print(json.dumps(jsons)) return jsonx ###### ##### # ##### # # # # # ##### # # # # # # # # # # # # # # ###### ##### # # # use this when the face isolation boxes arent big enough def boxscale(self,name,skale=0.2): i = 0 for b in self.boxes: self.boxes[i] = self.rebox(b[0],b[1],b[2],b[3],self.imgs[name].shape, skale) i += 1 def rebox(self,x1,y1,x2,y2,shape,scale=0.2): print("!!!!!!1 rebox with shape ",shape) xx1 = x1 - int((x2-x1)*scale*0.8) xx2 = x2 + int((x2-x1)*scale*0.8) yy1 = y1 - int((y2-y1)*scale*1.3) yy2 = y2 + int((y2-y1)*scale*1.3) if xx1 < 0: xx1 = 0 if yy1 < 0: yy1 = 0 if xx2 > shape[1]: xx2 = shape[1] if yy2 > shape[0]: yy2 = shape[0] return (xx1,yy1,xx2,yy2) # @doc draw a box on an image def rect(self, name, x1, y1, x2, y2, color): print ("recting ",x1,y1,x2,y2) cv2.rectangle(self.imgs[name],(x1,y1),(x2,y2), color, 4) # @doc crop an image, allowing a gutter. def crop(self, name, x1, y1, x2, y2): print ("cropping ",x1,y1,x2,y2) return self.imgs[name][y1:y2 , x1:x2] # @doc crop an image, allowing a gutter. def shrink(self, name, skale=0.5): print ("shrinking ",name) self.imgs[name] = cv2.resize(self.imgs[name],None,fx=skale,fy=skale) ##### ###### ##### # # ##### # # # # # # # # # # ## # # # ##### # # # # # # # # ##### # # # # ##### # # # # # # # # # # # # ## # # ###### # #### # # # # def scores(self): return json.dumps(self.tree) # return a base64 version of the pic in memory def dump64(self,which): _ , im_arr = cv2.imencode('.png', self.imgs[which]) img_as_txt = base64.b64encode(im_arr) return b'data:image/png;base64, '+img_as_txt def save(self,which,dir,format="png"): cv2.imwrite(dir + "/" + which + "." + format, self.imgs[which]) def stats(self,which): print(which + " stats....") print(type(self.imgs[which])) print(np.shape(self.imgs[which])) if __name__ == '__main__': d = FaceClass() d.load1("messi1","testimg/messi1.jpg") d.load2("messi2","testimg/messi2.jpg", "messi3","testimg/messi3.jpg") # look for pics in /tmp d.save("messi1", "/tmp") d.save("messi2", "/tmp") d.save("messi3", "/tmp")