Module deepposekit.models.layers.deeplabcut
Utilities for ImageNet data preprocessing & prediction decoding.
Expand source code
# -*- coding: utf-8 -*-
"""Utilities for ImageNet data preprocessing & prediction decoding.
"""
# Modified from
# https://github.com/keras-team/keras-applications/blob/master/keras_applications/imagenet_utils.py
# All Modifications Copyright 2018-2019 Jacob M. Graving <jgraving@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import numpy as np
from tensorflow.keras.layers import Layer
from tensorflow.keras import backend
from deepposekit.models.layers.imagenet_resnet import MODELS as RESNET_MODELS
from deepposekit.models.layers.imagenet_mobile import MODELS as MOBILE_MODELS
from deepposekit.models.layers.imagenet_densenet import MODELS as DENSENET_MODELS
from deepposekit.models.layers.imagenet_xception import MODELS as XCEPTION_MODELS
from functools import partial
def _preprocess_symbolic_input(x, data_format, mode, **kwargs):
"""Preprocesses a tensor encoding a batch of images.
# Arguments
x: Input tensor, 3D or 4D.
data_format: Data format of the image tensor.
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 tensor.
"""
if mode == "tf":
x /= 127.5
x -= 1.0
return x
if mode == "torch":
x /= 255.0
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
else:
if data_format == "channels_first":
# 'RGB'->'BGR'
if backend.ndim(x) == 3:
x = x[::-1, ...]
else:
x = x[:, ::-1, ...]
else:
# 'RGB'->'BGR'
x = x[..., ::-1]
mean = [103.939, 116.779, 123.68]
std = None
mean_tensor = backend.constant(-np.array(mean))
# Zero-center by mean pixel
if backend.dtype(x) != backend.dtype(mean_tensor):
x = backend.bias_add(
x, backend.cast(mean_tensor, backend.dtype(x)), data_format=data_format
)
else:
x = backend.bias_add(x, mean_tensor, data_format)
if std is not None:
x /= std
return x
def preprocess_input(x, data_format=None, mode="caffe", **kwargs):
"""Preprocesses a tensor or Numpy array encoding a batch of images.
# Arguments
x: Input Numpy or symbolic tensor, 3D or 4D.
The preprocessed data is written over the input data
if the data types are compatible. To avoid this
behaviour, `numpy.copy(x)` can be used.
data_format: Data format of the image tensor/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 tensor or Numpy array.
# Raises
ValueError: In case of unknown `data_format` argument.
"""
if data_format is None:
data_format = backend.image_data_format()
if data_format not in {"channels_first", "channels_last"}:
raise ValueError("Unknown data_format " + str(data_format))
return _preprocess_symbolic_input(x, data_format=data_format, mode=mode, **kwargs)
class ImageNetPreprocess(Layer):
"""Preprocessing layer for ImageNet inputs.
# Input shape
4D tensor with shape:
- If `data_format` is `"channels_last"`:
`(batch, rows, cols, channels)`
- If `data_format` is `"channels_first"`:
`(batch, channels, rows, cols)`
# Output shape
4D tensor with shape:
- If `data_format` is `"channels_last"`:
`(batch, rows, cols, channels)`
- If `data_format` is `"channels_first"`:
`(batch, channels, rows, cols)`
"""
def __init__(self, network, **kwargs):
super(ImageNetPreprocess, self).__init__(**kwargs)
self.network = network
if network.lower().startswith(("mobile", "xception")):
self.preprocess_input = partial(preprocess_input, mode="tf")
elif network.lower().startswith("resnet"):
self.preprocess_input = partial(preprocess_input, mode="caffe")
elif network.lower().startswith("densenet"):
self.preprocess_input = partial(preprocess_input, mode="torch")
def call(self, inputs):
return self.preprocess_input(inputs)
def get_config(self):
config = {"network": self.network}
base_config = super(ImageNetPreprocess, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
MODELS = (
list(RESNET_MODELS.items())
+ list(MOBILE_MODELS.items())
+ list(DENSENET_MODELS.items())
+ list(XCEPTION_MODELS.items())
)
MODELS = dict(MODELS)
if __name__ == "__main__":
from tensorflow.keras.applications.resnet50 import preprocess_input
from tensorflow.keras.layers import Input
from tensorflow.keras import Model
input_layer = Input((192, 192, 3))
model = ResNet50(include_top=False, input_shape=(192, 192, 3))
normalized = ImageNetPreprocess(network="resnet50")(input_layer)
pretrained_output = model(normalized)
model = Model(inputs=input_layer, outputs=pretrained_output)
Functions
def preprocess_input(x, data_format=None, mode='caffe', **kwargs)
-
Preprocesses a tensor or Numpy array encoding a batch of images.
Arguments
x: Input Numpy or symbolic tensor, 3D or 4D. The preprocessed data is written over the input data if the data types are compatible. To avoid this behaviour, `numpy.copy(x)` can be used. data_format: Data format of the image tensor/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 tensor or Numpy array.
Raises
ValueError: In case of unknown `data_format` argument.
Expand source code
def preprocess_input(x, data_format=None, mode="caffe", **kwargs): """Preprocesses a tensor or Numpy array encoding a batch of images. # Arguments x: Input Numpy or symbolic tensor, 3D or 4D. The preprocessed data is written over the input data if the data types are compatible. To avoid this behaviour, `numpy.copy(x)` can be used. data_format: Data format of the image tensor/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 tensor or Numpy array. # Raises ValueError: In case of unknown `data_format` argument. """ if data_format is None: data_format = backend.image_data_format() if data_format not in {"channels_first", "channels_last"}: raise ValueError("Unknown data_format " + str(data_format)) return _preprocess_symbolic_input(x, data_format=data_format, mode=mode, **kwargs)
Classes
class ImageNetPreprocess (network, **kwargs)
-
Preprocessing layer for ImageNet inputs.
Input shape
4D tensor with shape: - If `data_format` is `"channels_last"`: `(batch, rows, cols, channels)` - If `data_format` is `"channels_first"`: `(batch, channels, rows, cols)`
Output shape
4D tensor with shape: - If `data_format` is `"channels_last"`: `(batch, rows, cols, channels)` - If `data_format` is `"channels_first"`: `(batch, channels, rows, cols)`
Expand source code
class ImageNetPreprocess(Layer): """Preprocessing layer for ImageNet inputs. # Input shape 4D tensor with shape: - If `data_format` is `"channels_last"`: `(batch, rows, cols, channels)` - If `data_format` is `"channels_first"`: `(batch, channels, rows, cols)` # Output shape 4D tensor with shape: - If `data_format` is `"channels_last"`: `(batch, rows, cols, channels)` - If `data_format` is `"channels_first"`: `(batch, channels, rows, cols)` """ def __init__(self, network, **kwargs): super(ImageNetPreprocess, self).__init__(**kwargs) self.network = network if network.lower().startswith(("mobile", "xception")): self.preprocess_input = partial(preprocess_input, mode="tf") elif network.lower().startswith("resnet"): self.preprocess_input = partial(preprocess_input, mode="caffe") elif network.lower().startswith("densenet"): self.preprocess_input = partial(preprocess_input, mode="torch") def call(self, inputs): return self.preprocess_input(inputs) def get_config(self): config = {"network": self.network} base_config = super(ImageNetPreprocess, self).get_config() return dict(list(base_config.items()) + list(config.items()))
Ancestors
- tensorflow.python.keras.engine.base_layer.Layer
- tensorflow.python.module.module.Module
- tensorflow.python.training.tracking.tracking.AutoTrackable
- tensorflow.python.training.tracking.base.Trackable
Methods
def call(self, inputs)
-
This is where the layer's logic lives.
Arguments
inputs
- Input tensor, or list/tuple of input tensors.
**kwargs
- Additional keyword arguments.
Returns
A tensor or list/tuple of tensors.
Expand source code
def call(self, inputs): return self.preprocess_input(inputs)
def get_config(self)
-
Returns the config of the layer.
A layer config is a Python dictionary (serializable) containing the configuration of a layer. The same layer can be reinstantiated later (without its trained weights) from this configuration.
The config of a layer does not include connectivity information, nor the layer class name. These are handled by
Network
(one layer of abstraction above).Returns
Python dictionary.
Expand source code
def get_config(self): config = {"network": self.network} base_config = super(ImageNetPreprocess, self).get_config() return dict(list(base_config.items()) + list(config.items()))