# under development import cv2 import torch import torch.nn as nn import numpy as np import torch.nn.functional as F class EdgeLoss(nn.Module): def __init__(self, device, reduction='mean'): super().__init__() self.loss_fn = nn.L1Loss(reduction=reduction) self.gaussianKernel = self._gaussianKernel2dOpencv(kernel_size=5, sigma=1) self.gaussianKernel = np.reshape(self.gaussianKernel, (1, 1, 5, 5)) # 5 is kernel size self.gaussianKernel = torch.from_numpy(self.gaussianKernel).float().to(device) def forward(self, outputs, GTs, masks, cannyEdges): """ Calculate the L1 loss in the edge regions edges are detected by canny operator Args: outputs: torch tensor, shape [b, c, h, w] GTs: torch tensor, shape [b, c, h, w] masks: torch tensor, shape [b, 1, h, w] cannyEdges: shape [b, c, h, w], 1 indicates edge regions, while 0 indicates nonedge regions cannyEdges should be provided by the dataloader Returns: edge loss between outputs and GTs """ cannyEdges = self.gaussianBlur(cannyEdges) loss = self.loss_fn(outputs * cannyEdges * masks, GTs * cannyEdges * masks) / torch.mean(masks) return loss def gaussianBlur(self, cannyEdges, iteration=2): for i in range(iteration): cannyEdges = F.conv2d(cannyEdges, self.gaussianKernel, stride=1, padding=2) return cannyEdges def _gaussianKernel2dOpencv(self, kernel_size=5, sigma=1): kx = cv2.getGaussianKernel(kernel_size, sigma) ky = cv2.getGaussianKernel(kernel_size, sigma) return np.multiply(kx, np.transpose(ky)) if __name__ == '__main__': from PIL import Image from torchvision.transforms import ToTensor from skimage.feature import canny from torchvision.utils import save_image from skimage.color import rgb2gray output = Image.open('images/00001_res.jpg') GT = Image.open('images/img2.jpg') # mask = Image.open('images/mask.png') cannyMap = canny(rgb2gray(np.array(GT)), sigma=2).astype(np.float32) output = ToTensor()(output).unsqueeze(0) GT = ToTensor()(GT).unsqueeze(0) # mask = ToTensor()(mask).unsqueeze(0) mask = torch.ones_like(GT) cannyMap = ToTensor()(cannyMap).unsqueeze(0) output = output * 2 - 1 GT = GT * 2 - 1 EdgeLossLayer = EdgeLoss(2, 'cpu') edgeLoss, cannyPriority, edgeMap_output, edgeMap_GT, errorMap, errorMap2 = EdgeLossLayer(output, GT, mask, cannyMap) print(edgeLoss) save_image(cannyPriority, 'images/cannyPriority.jpg') save_image(edgeMap_output, 'images/edgeMap_output.jpg') save_image(edgeMap_GT, 'images/edgeMap_GT.jpg') save_image(edgeMap_output * cannyPriority, 'images/edgeMap_output_canny.jpg') save_image(edgeMap_GT * cannyPriority, 'images/edgeMap_GT_canny.jpg') save_image(errorMap, 'images/errorMap.jpg') save_image(errorMap2, 'images/errorMap2.jpg')