Module seg_mask_modifs.mask_generator
Expand source code
import cv2
import json
import numpy as np
import torch
from PIL import Image
from torchvision.transforms import transforms as transforms
from model_utils.model_celebmask import BiSeNet
class mask_generator:
""" Class to generate masks using models"""
def __init__(self, threshold=0.5, auto_init=True):
"""
Arguments:
threshold: Minimum required model threshold on inferencing.
auto_init: Auto initialize models whenever their label is seen.
Initializes from default path model stored to in download_models(). If path changed then initialize manually.
"""
self.model_preference = ['deeplabv3', 'maskrcnn', 'face']
self.all_models = ['deeplabv3', 'maskrcnn', 'face']
self.maskrcnn_model = False
self.deeplabv3_model = False
self.face_model = False
self.threshold = threshold
self.auto_init = auto_init
self.device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
self.gpu = torch.cuda.is_available()
self.model_labels = json.load(open('model_utils/labels.json'))
self.label_mapping = {'deeplabv3': 'deeplab_pascal_labels',
'maskrcnn': 'maskrcnn_coco_labels',
'face': 'face_labels'}
def init_maskrcnn(self, model_path='models/maskrcnn_resnet50_fpn.pt'):
""" Function to initialize maskrcnn model
Arguments:
model_path: Path to maskrcnn model
"""
self.maskrcnn_model = torch.load(model_path)
self.maskrcnn_model.to(self.device).eval()
def init_deeplabv3(self, model_path='models/deeplab_restnet101.pt'):
""" Function to initialize deeplabv3 model
Arguments:
model_path: Path to deeplabv3 model
"""
self.deeplabv3_model = torch.load(model_path)
self.deeplabv3_model.to(self.device).eval()
def init_face(self, model_path='models/face.pth'):
""" Function to initialize face model
Arguments:
model_path: Path to face model
"""
self.face_model = BiSeNet(n_classes=19)
if self.gpu:
self.face_model.cuda()
self.face_model.load_state_dict(torch.load(model_path))
else:
self.face_model.load_state_dict(torch.load(model_path, map_location='cpu'))
self.face_model.eval()
def print_model_preference(self):
""" Function to know the current model preference"""
print(self.model_preference)
def set_model_preference(self, model=None, pos=0, model_list=None):
""" Function to set the model preference.
Only the models in model list will be used for mask generation.
Pass either model along with its position or complete list containing models.
If both are passed model_list will be preffered.
Arguments:
model: str having of 'deeplabv3', 'maskrcnn', 'face' whose value need to be set.
pos: int having the position of preference of the model starting from 0. Default: 0.
model_list: List containing models
"""
if model_list is None and model is None:
raise AttributeError("One of model or model_list needs to be passed")
if model_list is not None:
for models in model_list:
if models not in self.all_models:
print("Wrong model name passed:", models)
raise ValueError
self.model_preference = model_list
return
if model not in self.all_models:
print("Wrong model name passed:", model)
raise ValueError
if model in self.model_preference:
self.model_preference.remove(model)
self.model_preference.insert(pos, model)
def maskrcnn_inference(self, img, labels):
"""Function to perform inference using MaskRCNN
Arguments:
img: input image
labels: labels to generate mask of.
Returns:
output_mask: A combined mask of the labels provided"""
transform = transforms.Compose([
transforms.ToTensor()
])
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_rgb = transform(img_rgb)
img_rgb = img_rgb.unsqueeze(0).to(self.device)
with torch.no_grad():
outputs = self.maskrcnn_model(img_rgb)
# correct from code in docker
scores = list(outputs[0]['scores'].detach().cpu().numpy())
if len(outputs[0]['masks']) == 1:
masks = (outputs[0]['masks'] > 0.5)[0].detach().cpu().numpy()
else:
masks = (outputs[0]['masks'] > 0.5).squeeze().detach().cpu().numpy()
pred_labels = [self.model_labels['maskrcnn_coco_labels'][i] for i in outputs[0]['labels']]
output_mask = np.zeros((img.shape[:2]), dtype=np.uint8)
for i in range(len(scores)):
if scores[i] > self.threshold and pred_labels[i] in labels:
output_mask = cv2.bitwise_or(output_mask, np.array(masks[i], dtype=np.uint8))
return output_mask
def deeplabv3_inference(self, img, labels):
"""Function to perform inference using deeplabv3
Arguments:
img: input image
labels: labels to generate mask of.
Returns:
output_mask: A combined mask of the labels provided"""
trf = transforms.Compose([transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
img_pil = Image.fromarray(img)
inp = trf(img_pil).unsqueeze(0).to(self.device)
with torch.no_grad():
out = self.deeplabv3_model(inp)['out']
output_mask = torch.argmax(out.squeeze(), dim=0).detach().cpu().numpy()
pred_labels_ind = np.unique(output_mask)
req_label_ind = [self.model_labels['deeplab_pascal_labels'].index(
label) for label in labels]
for pred_label_ind in pred_labels_ind:
if pred_label_ind not in req_label_ind:
# converting all unwanted labels to 0
output_mask[output_mask[:] == pred_label_ind] = 0
output_mask = np.array(output_mask, dtype=np.uint8)
_, output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY)
return output_mask
def face_inference(self, img, labels):
"""Function to perform inference using face model
Arguments:
img: input image
labels: labels to generate mask of.
Returns:
output_mask: A combined mask of the labels provided"""
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
])
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_rgb = transform(img_rgb)
img_rgb = img_rgb.unsqueeze(0).to(self.device)
with torch.no_grad():
out = self.face_model(img_rgb)[0]
output_mask = out.squeeze(0).cpu().numpy().argmax(0)
output_mask = output_mask.astype(np.uint8)
pred_labels_ind = np.unique(output_mask)
req_label_ind = [self.model_labels['face_labels'].index(label) for label in labels]
if "face" in labels:
# for complete face blurring adding all label indices except hat and cloth
# and removing its index from list
req_label_ind.extend([i for i in range(16)])
req_label_ind.append(17)
req_label_ind.remove(19)
req_label_ind = list(set(req_label_ind))
for pred_label_ind in pred_labels_ind:
if pred_label_ind not in req_label_ind:
# converting all unwanted labels to 0
output_mask[output_mask[:] == pred_label_ind] = 0
_, output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY)
return output_mask
def generate(self, img, labels, use_model=None):
""" Function to generate masks for labels.
Arguments:
img: Input image read by OpenCV
labels: list containing one or more labels whose masks needs to be generated.
use_model: One of deeplabv3, maskrcnn or face.
If argument passed only that model will be used for mask creation.
Returns: mask of those labels.
"""
if use_model is not None:
if use_model not in self.all_models:
print("use_model should be one of:", *self.all_models)
raise ValueError
model_labels = self.model_labels[self.label_mapping[use_model]]
labels_skipped = list(set(labels) - set(model_labels))
if not len(labels_skipped):
print("Skipping labels:", *labels_skipped,
", not present in labels of model:", use_model)
labels = list(set(labels).intersection(set(model_labels)))
# initialize model if auto_init is True and model is not initialized yet.
if self.auto_init and not eval("self." + use_model + "_model"):
eval("self.init_" + use_model)
# using eval("self.__" + use_model + "_inference") to generate inference funtion
output_mask = eval("self." + use_model + "_inference")(img, labels)
output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY)
return output_mask
output_mask = np.zeros((img.shape[:2]), dtype=np.uint8)
for model in self.model_preference:
model_labels = self.model_labels[self.label_mapping[model]]
labels_pass = list(set(labels).intersection(set(model_labels)))
if len(labels_pass):
# initialize model if auto_init is True and model is not initialized yet.
if self.auto_init and not eval("self." + model + "_model"):
eval("self.init_" + model)()
print("Inferencing labels:", *labels_pass, "with model:", model)
mask = eval("self." + model + "_inference")(img, labels_pass)
labels = list(set(labels) - set(labels_pass))
output_mask = cv2.bitwise_or(output_mask, mask)
if len(labels):
print("Labels skipped:", *labels, ", not present in labels of any model")
_, output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY)
return output_mask
# Testing
if __name__ == "__main__":
obj = mask_generator()
img = cv2.imread('images/city.jpg')
mask = obj.generate(img, ["backpack", "suitcase"])
# print(mask)
mask = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow('mask', mask)
cv2.waitKey(0)
cv2.destroyAllWindows()
Classes
class mask_generator (threshold=0.5, auto_init=True)
-
Class to generate masks using models
Arguments
threshold: Minimum required model threshold on inferencing.
auto_init: Auto initialize models whenever their label is seen.
Initializes from default path model stored to in download_models(). If path changed then initialize manually.Expand source code
class mask_generator: """ Class to generate masks using models""" def __init__(self, threshold=0.5, auto_init=True): """ Arguments: threshold: Minimum required model threshold on inferencing. auto_init: Auto initialize models whenever their label is seen. Initializes from default path model stored to in download_models(). If path changed then initialize manually. """ self.model_preference = ['deeplabv3', 'maskrcnn', 'face'] self.all_models = ['deeplabv3', 'maskrcnn', 'face'] self.maskrcnn_model = False self.deeplabv3_model = False self.face_model = False self.threshold = threshold self.auto_init = auto_init self.device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') self.gpu = torch.cuda.is_available() self.model_labels = json.load(open('model_utils/labels.json')) self.label_mapping = {'deeplabv3': 'deeplab_pascal_labels', 'maskrcnn': 'maskrcnn_coco_labels', 'face': 'face_labels'} def init_maskrcnn(self, model_path='models/maskrcnn_resnet50_fpn.pt'): """ Function to initialize maskrcnn model Arguments: model_path: Path to maskrcnn model """ self.maskrcnn_model = torch.load(model_path) self.maskrcnn_model.to(self.device).eval() def init_deeplabv3(self, model_path='models/deeplab_restnet101.pt'): """ Function to initialize deeplabv3 model Arguments: model_path: Path to deeplabv3 model """ self.deeplabv3_model = torch.load(model_path) self.deeplabv3_model.to(self.device).eval() def init_face(self, model_path='models/face.pth'): """ Function to initialize face model Arguments: model_path: Path to face model """ self.face_model = BiSeNet(n_classes=19) if self.gpu: self.face_model.cuda() self.face_model.load_state_dict(torch.load(model_path)) else: self.face_model.load_state_dict(torch.load(model_path, map_location='cpu')) self.face_model.eval() def print_model_preference(self): """ Function to know the current model preference""" print(self.model_preference) def set_model_preference(self, model=None, pos=0, model_list=None): """ Function to set the model preference. Only the models in model list will be used for mask generation. Pass either model along with its position or complete list containing models. If both are passed model_list will be preffered. Arguments: model: str having of 'deeplabv3', 'maskrcnn', 'face' whose value need to be set. pos: int having the position of preference of the model starting from 0. Default: 0. model_list: List containing models """ if model_list is None and model is None: raise AttributeError("One of model or model_list needs to be passed") if model_list is not None: for models in model_list: if models not in self.all_models: print("Wrong model name passed:", models) raise ValueError self.model_preference = model_list return if model not in self.all_models: print("Wrong model name passed:", model) raise ValueError if model in self.model_preference: self.model_preference.remove(model) self.model_preference.insert(pos, model) def maskrcnn_inference(self, img, labels): """Function to perform inference using MaskRCNN Arguments: img: input image labels: labels to generate mask of. Returns: output_mask: A combined mask of the labels provided""" transform = transforms.Compose([ transforms.ToTensor() ]) img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_rgb = transform(img_rgb) img_rgb = img_rgb.unsqueeze(0).to(self.device) with torch.no_grad(): outputs = self.maskrcnn_model(img_rgb) # correct from code in docker scores = list(outputs[0]['scores'].detach().cpu().numpy()) if len(outputs[0]['masks']) == 1: masks = (outputs[0]['masks'] > 0.5)[0].detach().cpu().numpy() else: masks = (outputs[0]['masks'] > 0.5).squeeze().detach().cpu().numpy() pred_labels = [self.model_labels['maskrcnn_coco_labels'][i] for i in outputs[0]['labels']] output_mask = np.zeros((img.shape[:2]), dtype=np.uint8) for i in range(len(scores)): if scores[i] > self.threshold and pred_labels[i] in labels: output_mask = cv2.bitwise_or(output_mask, np.array(masks[i], dtype=np.uint8)) return output_mask def deeplabv3_inference(self, img, labels): """Function to perform inference using deeplabv3 Arguments: img: input image labels: labels to generate mask of. Returns: output_mask: A combined mask of the labels provided""" trf = transforms.Compose([transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) img_pil = Image.fromarray(img) inp = trf(img_pil).unsqueeze(0).to(self.device) with torch.no_grad(): out = self.deeplabv3_model(inp)['out'] output_mask = torch.argmax(out.squeeze(), dim=0).detach().cpu().numpy() pred_labels_ind = np.unique(output_mask) req_label_ind = [self.model_labels['deeplab_pascal_labels'].index( label) for label in labels] for pred_label_ind in pred_labels_ind: if pred_label_ind not in req_label_ind: # converting all unwanted labels to 0 output_mask[output_mask[:] == pred_label_ind] = 0 output_mask = np.array(output_mask, dtype=np.uint8) _, output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY) return output_mask def face_inference(self, img, labels): """Function to perform inference using face model Arguments: img: input image labels: labels to generate mask of. Returns: output_mask: A combined mask of the labels provided""" transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), ]) img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img_rgb = transform(img_rgb) img_rgb = img_rgb.unsqueeze(0).to(self.device) with torch.no_grad(): out = self.face_model(img_rgb)[0] output_mask = out.squeeze(0).cpu().numpy().argmax(0) output_mask = output_mask.astype(np.uint8) pred_labels_ind = np.unique(output_mask) req_label_ind = [self.model_labels['face_labels'].index(label) for label in labels] if "face" in labels: # for complete face blurring adding all label indices except hat and cloth # and removing its index from list req_label_ind.extend([i for i in range(16)]) req_label_ind.append(17) req_label_ind.remove(19) req_label_ind = list(set(req_label_ind)) for pred_label_ind in pred_labels_ind: if pred_label_ind not in req_label_ind: # converting all unwanted labels to 0 output_mask[output_mask[:] == pred_label_ind] = 0 _, output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY) return output_mask def generate(self, img, labels, use_model=None): """ Function to generate masks for labels. Arguments: img: Input image read by OpenCV labels: list containing one or more labels whose masks needs to be generated. use_model: One of deeplabv3, maskrcnn or face. If argument passed only that model will be used for mask creation. Returns: mask of those labels. """ if use_model is not None: if use_model not in self.all_models: print("use_model should be one of:", *self.all_models) raise ValueError model_labels = self.model_labels[self.label_mapping[use_model]] labels_skipped = list(set(labels) - set(model_labels)) if not len(labels_skipped): print("Skipping labels:", *labels_skipped, ", not present in labels of model:", use_model) labels = list(set(labels).intersection(set(model_labels))) # initialize model if auto_init is True and model is not initialized yet. if self.auto_init and not eval("self." + use_model + "_model"): eval("self.init_" + use_model) # using eval("self.__" + use_model + "_inference") to generate inference funtion output_mask = eval("self." + use_model + "_inference")(img, labels) output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY) return output_mask output_mask = np.zeros((img.shape[:2]), dtype=np.uint8) for model in self.model_preference: model_labels = self.model_labels[self.label_mapping[model]] labels_pass = list(set(labels).intersection(set(model_labels))) if len(labels_pass): # initialize model if auto_init is True and model is not initialized yet. if self.auto_init and not eval("self." + model + "_model"): eval("self.init_" + model)() print("Inferencing labels:", *labels_pass, "with model:", model) mask = eval("self." + model + "_inference")(img, labels_pass) labels = list(set(labels) - set(labels_pass)) output_mask = cv2.bitwise_or(output_mask, mask) if len(labels): print("Labels skipped:", *labels, ", not present in labels of any model") _, output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY) return output_mask
Methods
def generate(self, img, labels, use_model=None)
-
Function to generate masks for labels.
Arguments
img: Input image read by OpenCV
labels: list containing one or more labels whose masks needs to be generated.
use_model: One of deeplabv3, maskrcnn or face. If argument passed only that model will be used for mask creation.Returns: mask of those labels.
Expand source code
def generate(self, img, labels, use_model=None): """ Function to generate masks for labels. Arguments: img: Input image read by OpenCV labels: list containing one or more labels whose masks needs to be generated. use_model: One of deeplabv3, maskrcnn or face. If argument passed only that model will be used for mask creation. Returns: mask of those labels. """ if use_model is not None: if use_model not in self.all_models: print("use_model should be one of:", *self.all_models) raise ValueError model_labels = self.model_labels[self.label_mapping[use_model]] labels_skipped = list(set(labels) - set(model_labels)) if not len(labels_skipped): print("Skipping labels:", *labels_skipped, ", not present in labels of model:", use_model) labels = list(set(labels).intersection(set(model_labels))) # initialize model if auto_init is True and model is not initialized yet. if self.auto_init and not eval("self." + use_model + "_model"): eval("self.init_" + use_model) # using eval("self.__" + use_model + "_inference") to generate inference funtion output_mask = eval("self." + use_model + "_inference")(img, labels) output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY) return output_mask output_mask = np.zeros((img.shape[:2]), dtype=np.uint8) for model in self.model_preference: model_labels = self.model_labels[self.label_mapping[model]] labels_pass = list(set(labels).intersection(set(model_labels))) if len(labels_pass): # initialize model if auto_init is True and model is not initialized yet. if self.auto_init and not eval("self." + model + "_model"): eval("self.init_" + model)() print("Inferencing labels:", *labels_pass, "with model:", model) mask = eval("self." + model + "_inference")(img, labels_pass) labels = list(set(labels) - set(labels_pass)) output_mask = cv2.bitwise_or(output_mask, mask) if len(labels): print("Labels skipped:", *labels, ", not present in labels of any model") _, output_mask = cv2.threshold(output_mask, 0, 255, cv2.THRESH_BINARY) return output_mask
def init_deeplabv3(self, model_path='models/deeplab_restnet101.pt')
-
Function to initialize deeplabv3 model
Arguments
model_path: Path to deeplabv3 model
Expand source code
def init_deeplabv3(self, model_path='models/deeplab_restnet101.pt'): """ Function to initialize deeplabv3 model Arguments: model_path: Path to deeplabv3 model """ self.deeplabv3_model = torch.load(model_path) self.deeplabv3_model.to(self.device).eval()
def init_face(self, model_path='models/face.pth')
-
Function to initialize face model
Arguments
model_path: Path to face model
Expand source code
def init_face(self, model_path='models/face.pth'): """ Function to initialize face model Arguments: model_path: Path to face model """ self.face_model = BiSeNet(n_classes=19) if self.gpu: self.face_model.cuda() self.face_model.load_state_dict(torch.load(model_path)) else: self.face_model.load_state_dict(torch.load(model_path, map_location='cpu')) self.face_model.eval()
def init_maskrcnn(self, model_path='models/maskrcnn_resnet50_fpn.pt')
-
Function to initialize maskrcnn model
Arguments
model_path: Path to maskrcnn model
Expand source code
def init_maskrcnn(self, model_path='models/maskrcnn_resnet50_fpn.pt'): """ Function to initialize maskrcnn model Arguments: model_path: Path to maskrcnn model """ self.maskrcnn_model = torch.load(model_path) self.maskrcnn_model.to(self.device).eval()
def print_model_preference(self)
-
Function to know the current model preference
Expand source code
def print_model_preference(self): """ Function to know the current model preference""" print(self.model_preference)
def set_model_preference(self, model=None, pos=0, model_list=None)
-
Function to set the model preference. Only the models in model list will be used for mask generation. Pass either model along with its position or complete list containing models. If both are passed model_list will be preffered.
Arguments
model: str having of 'deeplabv3', 'maskrcnn', 'face' whose value need to be set.
pos: int having the position of preference of the model starting from 0. Default: 0.
model_list: List containing modelsExpand source code
def set_model_preference(self, model=None, pos=0, model_list=None): """ Function to set the model preference. Only the models in model list will be used for mask generation. Pass either model along with its position or complete list containing models. If both are passed model_list will be preffered. Arguments: model: str having of 'deeplabv3', 'maskrcnn', 'face' whose value need to be set. pos: int having the position of preference of the model starting from 0. Default: 0. model_list: List containing models """ if model_list is None and model is None: raise AttributeError("One of model or model_list needs to be passed") if model_list is not None: for models in model_list: if models not in self.all_models: print("Wrong model name passed:", models) raise ValueError self.model_preference = model_list return if model not in self.all_models: print("Wrong model name passed:", model) raise ValueError if model in self.model_preference: self.model_preference.remove(model) self.model_preference.insert(pos, model)