#tensorflow #pytorch #python-imaging-library
#tensorflow #pytorch #python-imaging-library
Вопрос:
У меня была модель кодировщика pytorch resnet101, когда входное изображение получило эту предварительную обработку:
import torchvision as tv
from PIL import Image
data_transforms = tv.transforms.Compose([
tv.transforms.Resize((224, 224)),
tv.transforms.ToTensor(),
tv.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])
img = Image.open(img_path)
img = img.convert('RGB')
img = data_transforms(img)
img = torch.FloatTensor(img)
img = img.unsqueeze(0)
print(img)
Форма ввода для кодировщика в этом случае [1, 3, 224, 224], и это изображение нормализовано со средним значением и стандартным значением ImageNet. Теперь я экспортирую эту модель в tensorflow, итак, как выполнить такую же предварительную обработку изображения для tf-модели?
Я пытался сделать что-то вроде этого:
from PIL import Image
img = Image.open(img_path)
img = img.convert('RGB')
img = tf.keras.preprocessing.image.img_to_array(img)
img = tf.image.resize(tf_img, (224, 224))
img = tf.keras.applications.resnet.preprocess_input(img)# now shape is [224, 224, 3]
img = tf.reshape(img, [1, 3, 224, 224])
print(img)
но я уверен, что я сделал что-то не так, потому что тензоры torch и tf выглядят очень по-разному для одного изображения и дают совершенно разные выходные результаты для одной модели кодера.
Может кто-нибудь помочь, что я должен исправить в предварительной обработке tf?
Ответ №1:
Это:
img = Image.open(img_path)
img = img.convert('RGB')
может быть заменен на
image = tf.io.read_file(filename=filepath)
image = tf.image.decode_jpeg(image, channels=3) #or decode_png
Кроме того, противоположность unsqueeze
и squeeze
является expand_dims
:
img = tf.expand_dims(img,axis=0)
Все должно работать хорошо, просто убедитесь, что
tf.keras.applications.resnet.preprocess_input(img) `and` data.transforms()
приведите к желаемым / необходимым преобразованиям.
Что касается фотографий, я совершенно уверен, что вы пропустили / 255.0 в случае PyTorch или добавили деление 255.0 в случае TensorFlow.
Фактически, углубляясь в серверную часть Keras, вы можете видеть, что когда вы вызываете свою функцию предварительной обработки, она вызывает эту функцию здесь:
def _preprocess_numpy_input(x, data_format, mode):
"""Preprocesses a Numpy array encoding a batch of images.
Arguments:
x: Input array, 3D or 4D.
data_format: Data format of the image array.
mode: One of "caffe", "tf" or "torch".
- caffe: will convert the images from RGB to BGR,
then will zero-center each color channel with
respect to the ImageNet dataset,
without scaling.
- tf: will scale pixels between -1 and 1,
sample-wise.
- torch: will scale pixels between 0 and 1 and then
will normalize each channel with respect to the
ImageNet dataset.
Returns:
Preprocessed Numpy array.
"""
if not issubclass(x.dtype.type, np.floating):
x = x.astype(backend.floatx(), copy=False)
if mode == 'tf':
x /= 127.5
x -= 1.
return x
elif mode == 'torch':
x /= 255.
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
else:
if data_format == 'channels_first':
# 'RGB'->'BGR'
if x.ndim == 3:
x = x[::-1, ...]
else:
x = x[:, ::-1, ...]
else:
# 'RGB'->'BGR'
x = x[..., ::-1]
mean = [103.939, 116.779, 123.68]
std = None
# Zero-center by mean pixel
if data_format == 'channels_first':
if x.ndim == 3:
x[0, :, :] -= mean[0]
x[1, :, :] -= mean[1]
x[2, :, :] -= mean[2]
if std is not None:
x[0, :, :] /= std[0]
x[1, :, :] /= std[1]
x[2, :, :] /= std[2]
else:
x[:, 0, :, :] -= mean[0]
x[:, 1, :, :] -= mean[1]
x[:, 2, :, :] -= mean[2]
if std is not None:
x[:, 0, :, :] /= std[0]
x[:, 1, :, :] /= std[1]
x[:, 2, :, :] /= std[2]
else:
x[..., 0] -= mean[0]
x[..., 1] -= mean[1]
x[..., 2] -= mean[2]
if std is not None:
x[..., 0] /= std[0]
x[..., 1] /= std[1]
x[..., 2] /= std[2]
return x
mode
Параметр по умолчанию в Keras и TensorFlow для предварительной обработки для ResNet50, на удивление, не tf
но caffe
.
Таким образом, предварительная обработка, которая выполняется для изображения, находится в этой ветке else (я добавляю ветку else и код после этого, чтобы вы могли следить за преобразованиями и видеть, чего вам не хватает):
else:
if data_format == 'channels_first':
# 'RGB'->'BGR'
if x.ndim == 3:
x = x[::-1, ...]
else:
x = x[:, ::-1, ...]
else:
# 'RGB'->'BGR'
x = x[..., ::-1]
mean = [103.939, 116.779, 123.68]
std = None
# Zero-center by mean pixel
if data_format == 'channels_first':
if x.ndim == 3:
x[0, :, :] -= mean[0]
x[1, :, :] -= mean[1]
x[2, :, :] -= mean[2]
if std is not None:
x[0, :, :] /= std[0]
x[1, :, :] /= std[1]
x[2, :, :] /= std[2]
else:
x[:, 0, :, :] -= mean[0]
x[:, 1, :, :] -= mean[1]
x[:, 2, :, :] -= mean[2]
if std is not None:
x[:, 0, :, :] /= std[0]
x[:, 1, :, :] /= std[1]
x[:, 2, :, :] /= std[2]
else:
x[..., 0] -= mean[0]
x[..., 1] -= mean[1]
x[..., 2] -= mean[2]
if std is not None:
x[..., 0] /= std[0]
x[..., 1] /= std[1]
x[..., 2] /= std[2]
return x
Описание:
caffe: преобразует изображения из RGB в BGR, затем обнуляет каждый цветовой канал по отношению к набору данных ImageNet без масштабирования.