import cv2 import numpy as np import matplotlib.pyplot as plt import math import copy import importlib def tiler(img,image_size,tiles=2,pad=0,): # pad is 0 to 0.9% h,w=img.shape[:2] tile_h=(h//tiles) tile_w=(w//tiles) pad=int(tile_h*pad) crops=[] coordinates=[] for i in range(tiles): for j in range(tiles): ymin=tile_h*i xmin=tile_w*j if i!=0:ymin=ymin-pad if j!=0:xmin=xmin-pad ymax=min(ymin+tile_h+pad,h) xmax=min(xmin+tile_w+pad,w) # crops.append(img[ymin:ymax,xmin:xmax]) crops.append(cv2.resize(img[ymin:ymax,xmin:xmax],[image_size,image_size])) coordinates.append((xmin,ymin,xmax,ymax)) # print(crops[-1].shape) return coordinates,np.array(crops) class square_crop: def __call__(self,img): h,w=img.shape[:2] self.w_removed,self.h_removed=0,0 if w>h: self.w_removed=(w-h)//2 img=img[:,self.w_removed:w-self.w_removed] elif h>w: self.h_removed=(h-w)//2 img=img[self.h_removed:h-self.h_removed,:] h,w=img.shape[:2] self.w_removed,self.h_removed=self.w_removed/w,self.h_removed/h return img def rescale(self,objs_found): raise NotImplementedError class square_pad: def __init__(self,color=(0,0,0)): self.color=color def __call__(self,img): h,w=img.shape[:2] self.w_added,self.h_added=0,0 if h>w: self.w_added=int((h-w)/2) padding=(np.ones([h,self.w_added,3])*np.array(self.color)[None,None,:]).astype("uint8") img=np.concatenate([padding,img,padding],axis=1) elif w>h: self.h_added=int((w-h)/2) padding=(np.ones([self.h_added,w,3])*np.array(self.color)[None,None,:]).astype("uint8") img=np.concatenate([padding,img,padding],axis=0) h,w=img.shape[:2] self.w_added,self.h_added=self.w_added/w,self.h_added/h return img def rescale(self,objs_found): for i in range(len(objs_found)): objs_found[i][2]=(objs_found[i][2]-self.w_added)/(1-2*self.w_added) objs_found[i][3]=(objs_found[i][3]-self.h_added)/(1-2*self.h_added) objs_found[i][4]=(objs_found[i][4])/(1-2*self.w_added) objs_found[i][5]=(objs_found[i][5])/(1-2*self.h_added) return objs_found class face_detection: def __init__(self,model_path): ################### set num_anchors & tf_anchors ################### anchor_boxes=np.loadtxt(model_path+"/anchors.txt") num_anchors=anchor_boxes.shape[0] tf_anchors=K.reshape(K.variable(anchor_boxes),[1, 1, 1, num_anchors, 2]) load_model_lib.num_anchors=num_anchors decode_model_lib.tf_anchors=tf_anchors #################################################################### self.model=load_model(model_path+"/model.h5") self.modes_available=["tiled","sized"] self.square_preprocessing=square_crop config_file_path='.'.join(model_path.split("/"))+".config" # print(config_file_path) self.model_config= importlib.import_module(config_file_path) def invoke_model(self,img,p,iou_threshold,batch_size): all_objs_found=[] for i in range(math.ceil(img.shape[0]/batch_size)): y_pred=self.model.predict(img[int(i*batch_size):int((i+1)*batch_size)].astype('float32'),verbose=0) # print(y_pred.shape) for i in range(y_pred.shape[0]): objs_found=get_objects(y_pred[i],p=p) all_objs_found.append(objs_found) return all_objs_found def get_tiled_output(self,img,p_thres,nms_thres,tiles,pad,image_size,save_tiles=None,batch_size=4): # pad is 0 to 0.5% # pad=0.05 img=cv2.resize(img,[image_size*tiles,image_size*tiles]) coordinates,crops=tiler(img,tiles=tiles,pad=pad,image_size=image_size) all_objs_found=self.invoke_model(crops,p_thres,nms_thres,batch_size) if save_tiles: fig=plt.figure(figsize=(3*tiles,3*tiles)) plt.axis("off") plt.title(f"pad:{pad}") for i in range(int(tiles*tiles)): fig.add_subplot(tiles,tiles,i+1) plt.axis("off") plt.imshow(pred_image(crops[i],all_objs_found[i])) # plt.show(block=False) plt.savefig(save_tiles+f"_{tiles}.jpg") plt.close() all_objs_found_joined=[] for i in range(int(tiles*tiles)): xmin,ymin,xmax,ymax=coordinates[i] w,h=xmax-xmin,ymax-ymin for j in range(all_objs_found[i].__len__()): # all_objs_found[i][j]['xywh']=np.array(all_objs_found[i][j]['xywh'])/image_size all_objs_found[i][j]['xywh']=np.array(all_objs_found[i][j]['xywh'])*w all_objs_found[i][j]['xywh'][0]+=xmin all_objs_found[i][j]['xywh'][1]+=ymin all_objs_found[i][j]['xywh']=(all_objs_found[i][j]['xywh']/(image_size*tiles)).tolist() all_objs_found_joined.extend(all_objs_found[i]) return all_objs_found_joined def set_mode(self,p_thres,nms_thres,batch_size=1,mode="sized",**kwargs): # mode : tiled or sized self.p_thres=p_thres self.nms_thres=nms_thres self.batch_size=batch_size if mode=="tiled": try: self.image_size=kwargs['image_size'] if "tiles" not in kwargs: self.tiles=[1] self.pad=0 else: self.tiles=kwargs['tiles'] if(type(kwargs['tiles'])==type(list([1])) or type(kwargs['tiles'])==type(np.zeros([]))) else [kwargs['tiles']] self.pad=kwargs['pad'] except: raise ValueError(f"Not all tiled mode parameters passed.") self.save_tiles=kwargs["save_tiles"] if ("save_tiles" in kwargs) else None elif mode=="sized": try: # self.image_size=kwargs['image_size'] self.image_size=kwargs['image_size'] if(type(kwargs['image_size'])==type(list([1])) or type(kwargs['image_size'])==type(np.zeros([]))) else [kwargs['image_size']] self.batch_size=1 except: raise ValueError(f"Not all Sized mode parameters passed.") else: raise ValueError(f"Unavailable mode={mode} \nmode can only be one of:{self.modes_available}") self.mode=mode def predict_once(self,img): if (type(img)==str): img=cv2.cvtColor(cv2.imread(img),cv2.COLOR_BGR2RGB) elif (type(img)!=type(np.zeros([]))): raise TypeError(f"Inappropriate type of image={type(img)}") # if img.shape[0]!=img.shape[1]: raise ValueError(f"The image should be squared") if not hasattr(self,'mode'): raise ValueError(f"First call set_mode function to set mode using one of the following mode :{self.modes_available}") if self.mode=='tiled': if type(self.tiles)==type(list([1])) or type(self.tiles)==type(np.zeros([])): raise TypeError("use advanced_predict function for inference on multiple tiles") objs_found=self.get_tiled_output(img,p_thres=self.p_thres,nms_thres=self.nms_thres,tiles=self.tiles,pad=self.pad,image_size=self.image_size,save_tiles=self.save_tiles) elif self.mode=='sized': if type(self.image_size)==type(list([1])) or type(self.image_size)==type(np.zeros([])): raise TypeError("use advanced_predict function for inference on multiple sizes") resized_img=cv2.resize(img,[self.image_size,self.image_size]) objs_found=self.invoke_model(resized_img[None,:,:,:],self.p_thres,self.nms_thres,batch_size=1)[0] return objs_found def predict(self,img): if (type(img)==str): img=cv2.cvtColor(cv2.imread(img),cv2.COLOR_BGR2RGB) elif (type(img)!=type(np.zeros([]))): raise TypeError(f"Inappropriate type of image={type(img)}") img=self.square_preprocessing(img) if not hasattr(self,'mode'): raise ValueError(f"First call set_mode function to set mode using one of the following mode :{self.modes_available}") if self.mode=="tiled": all_objs_found=[] all_tiles=copy.deepcopy(self.tiles) for tiles in all_tiles: self.tiles=tiles _,objs_found=self.predict_once(img) all_objs_found.extend(objs_found) self.tiles=all_tiles elif self.mode=="sized": all_objs_found=[] all_image_size=copy.deepcopy(self.image_size) for image_size in all_image_size: self.image_size=image_size objs_found=self.predict_once(img) all_objs_found.extend(objs_found) self.image_size=all_image_size all_objs_found=np.array(all_objs_found) all_objs_found=nms(all_objs_found,self.nms_thres) all_objs_found=self.square_preprocessing.rescale(all_objs_found) #rescale coordinates to original image's resolution for obj_found in all_objs_found: obj_found[1]=idx_to_class[obj_found[1]] # print(all_objs_found) return all_objs_found if __name__=="__main__": import create_load_model as load_model_lib import decode_yolo_v2 as decode_model_lib from create_load_model import * from decode_yolo_v2 import * face_detector=face_detection("face_detection/Models/v1/") # test_img="C:\\Users\\Home\\Downloads\\WhatsApp Image 2023-01-04 at 6.58.40 PM.jpeg" test_img="C:\\Users\\Home\\Downloads\\family-52.jpg" p_thres=0.5 nms_thres=0.3 tiles=3 pad=0 # face_detector.set_mode(p_thres,nms_thres,mode="tiled",tiles=[1,2],pad=pad,image_size=416,save_tiles="tile") # face_detector.set_mode(p_thres=p_thres,nms_thres=nms_thres,image_size=608) # face_detector.set_mode(p_thres,nms_thres,mode="sized",image_size=256) # face_detector.set_mode(p_thres,nms_thres,mode="sized",image_size=352) # face_detector.set_mode(p_thres,nms_thres,mode="sized",image_size=608) face_detector.set_mode(p_thres,nms_thres,mode="sized",image_size=1024) # face_detector.set_mode(p_thres,nms_thres,mode="sized",image_size=[608,1024]) img,objs_found=face_detector.predict(test_img) # img,objs_found=face_detector.advanced_predict(test_img) pred_img=pred_image(img,objs_found) plt.figure() plt.imshow(pred_img) plt.show() # cv2.imwrite("test_output.jpg",pred_img[:,:,::-1]) else: import face_detection.create_load_model as load_model_lib import face_detection.decode_yolo_v2 as decode_model_lib from face_detection.create_load_model import * from face_detection.decode_yolo_v2 import *