torch transform.resize() против cv2.resize()

#python #pytorch

#python #pytorch

Вопрос:

Модель CNN принимает тензор размера изображения (112x112) в качестве входных данных и выдает (1x512) тензор размера в качестве выходных данных.

Использование функции Opencv cv2.resize() или использование Transform.resize в pytorch для изменения размера входных данных (112x112) дает разные результаты.

В чем причина этого? (Я понимаю, что причиной этого может быть разница в базовой реализации изменения размера opencv по сравнению с изменением размера torch, но я хотел бы иметь подробное представление об этом)

 import cv2
import numpy as np 
from PIL import image
import torch
import torchvision
from torchvision import transforms as trans


# device for pytorch
device = torch.device('cuda:0')

torch.set_default_tensor_type('torch.cuda.FloatTensor')

model = torch.jit.load("traced_facelearner_model_new.pt")
model.eval()

# read the example image used for tracing
image=cv2.imread("videos/example.jpg")

test_transform = trans.Compose([
            trans.ToTensor(),
            trans.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
        ])   
test_transform2 = trans.Compose([
            trans.Resize([int(112), int(112)]),
            trans.ToTensor(),
            trans.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
        ])      

resized_image = cv2.resize(image, (112, 112))

tensor1 = test_transform(resized_image).to(device).unsqueeze(0)
tensor2 = test_transform2(Image.fromarray(image)).to(device).unsqueeze(0)
output1 = model(tensor1)
output2 = model(tensor2)
  

Тензоры output1 и output2 имеют разные значения.

Ответ №1:

В основном torchvision.transforms.Resize() используется PIL.Image.BILINEAR интерполяция по умолчанию.

В то время как в вашем коде вы просто используете cv2.resize , который не использует никакой интерполяции.

Например

 import cv2
from PIL import Image
import numpy as np

a = cv2.imread('videos/example.jpg')
b = cv2.resize(a, (112, 112))
c = np.array(Image.fromarray(a).resize((112, 112), Image.BILINEAR))
  

Вы увидите, что b и c немного отличаются.

Редактировать:

На самом деле в документах opencv говорится

INTER_LINEAR — билинейная интерполяция (используется по умолчанию)

Но да, это не дает того же результата, что PIL .

Правка 2:

Это также в документах

Чтобы уменьшить изображение, оно, как правило, будет выглядеть лучше всего с интерполяцией INTER_AREA

И, по-видимому

 d = cv2.resize(a, (112, 112), interpolation=cv2.INTER_AREA)
  

Дает почти тот же результат, что и c . Но, к сожалению, они не отвечают на вопрос.

Комментарии:

1. OpenCV по умолчанию не использует интерполяцию

2. Читайте здесь docs.opencv.org/trunk/da/d54 /…

3. Это выполняется None на Python, но по умолчанию cv::resize используется INTER_LINEAR

4. @Natthaphon Хонгчароен. PIL применяет некоторый фильтр сглаживания перед изменением размера. Но не cv2, это также приводит к некоторым различиям

5. @GirishDattatrayHegde Вот и ответ на вопрос. Я думаю, вам следует использовать это в качестве другого ответа, поскольку здесь его можно легко пропустить.