Shortcuts

Source code for libcom.opa_score.opa_score_prediction

import torch
import torchvision
from libcom.utils.model_download import download_pretrained_model
from libcom.utils.process_image import *
from libcom.utils.environment import *
from libcom.opa_score.source import ObjectPlaceNet
import torch 
import os
import torchvision.transforms as transforms

cur_dir   = os.path.dirname(os.path.abspath(__file__))
model_dir = os.environ.get('LIBCOM_MODEL_DIR',cur_dir)
model_set = ['SimOPA'] 


[docs]class OPAScoreModel: """ OPA score prediction model. Args: device (str | torch.device): gpu id model_type (str): predefined model type. kwargs (dict): other parameters for building model Examples: >>> from libcom import OPAScoreModel >>> from libcom import get_composite_image >>> from libcom.utils.process_image import make_image_grid >>> import cv2 >>> net = OPAScoreModel(device=0, model_type='SimOPA') >>> test_dir = './source' >>> bg_img = 'source/background/17.jpg' >>> fg_img = 'source/foreground/17.jpg' >>> fg_mask = 'source/foreground_mask/17.png' >>> bbox_list = [[475, 697, 1275, 1401], [475, 300, 1275, 1004]] >>> comp1, comp_mask1 = get_composite_image(fg_img, fg_mask, bg_img, bbox_list[0]) >>> comp2, comp_mask2 = get_composite_image(fg_img, fg_mask, bg_img, bbox_list[1]) >>> score1 = net(comp1, comp_mask1) >>> score2 = net(comp2, comp_mask2) >>> grid_img = make_image_grid([comp1, comp_mask1, comp2, comp_mask2], text_list=[f'opa_score:{score1:.2f}', 'composite-mask', f'opa_score:{score2:.2f}', 'composite-mask']) >>> cv2.imwrite('../docs/_static/image/opascore_result1.jpg', grid_img) Expected result: .. image:: _static/image/opascore_result1.jpg :scale: 38 % """ def __init__(self, device=0, model_type='SimOPA', **kwargs): assert model_type in model_set, f'Not implementation for {model_type}' self.model_type = model_type self.option = kwargs weight_path = os.path.join(model_dir, 'pretrained_models', 'SimOPA.pth') download_pretrained_model(weight_path) self.device = check_gpu_device(device) self.build_pretrained_model(weight_path) self.build_data_transformer() def build_pretrained_model(self, weight_path): model = ObjectPlaceNet(False) model.load_state_dict(torch.load(weight_path, map_location='cpu', weights_only=True)) self.model = model.to(self.device).eval() def build_data_transformer(self): self.image_size = 256 self.transformer = transforms.Compose([ transforms.Resize((self.image_size, self.image_size)), transforms.ToTensor(), ]) def inputs_preprocess(self, composite_image, composite_mask): img = read_image_pil(composite_image) img = self.transformer(img) mask = read_mask_pil(composite_mask) mask = self.transformer(mask) cat_img = torch.cat([img, mask], dim=0) cat_img = cat_img.unsqueeze(0).to(self.device) return cat_img def outputs_postprocess(self, outputs): score = torch.softmax(outputs, dim=-1)[0, 1].cpu().item() return score @torch.no_grad() def __call__(self, composite_image, composite_mask): """ Predicting the object placement assessment (opa) score for the given composite image, which evaluates the rationality of foreground object placement. Args: composite_image (str | numpy.ndarray): The path to composite image or the compposite image in ndarray form. composite_mask (str | numpy.ndarray): Mask of composite image which indicates the foreground object region in the composite image. Returns: opa_score (float): Predicted opa score ranges from 0 to 1, where a larger score indicates more reasonable placement. """ inputs = self.inputs_preprocess(composite_image, composite_mask) outputs = self.model(inputs) preds = self.outputs_postprocess(outputs) return preds