python – Changing Shape in Image input to Match that of a Downloaded Model

I am working on a Model downloaded from github that takes as an input an image and begins a Classification process . After taking a deeper look at this model,i figured out that it expect image with type (numpy.ndarray ) and a Shape of (1, 512, 512, 1).The model downloaded predicts on a tfrecord file , but i want to predict image that i supply and not the ones given . My Question is how can i change the image to match that of the expected model ?Please tell me if you need further details ! Here is the Code just for reference but i don’t know whether it will help or not and tell me if the code for the Functions are necessary

filenames = ['/content/drive/MyDrive/dataset.tfrecord']
raw_dataset_test = tf.data.TFRecordDataset(filenames)
parsed_dataset_test = raw_dataset_test.map(_parse_function)

def extract_test_data(inpt):
  """Normalizes images: `uint8` -> `float32`."""
  return tf.expand_dims(inpt['image/pixels'], axis=-1), inpt['image/brixiascore'], inpt['image/source_id']

def apply_test_equalization(images, labels, *args):
    return equalize(images), labels, args

ds_test = parsed_dataset_test
ds_test = ds_test.map(
    extract_test_data, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.map(
    apply_test_equalization, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(1)
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)

///////////////////////

preds = [] 
y_true = []
X_test = []
test_sourceid = []
for el in tqdm(ds_test.as_numpy_iterator()):
    preds.extend(single_model.predict(el[0]))
    y_true.extend(el[1])
    X_test.extend(el[0])
    test_sourceid.extend(el[2][0])

Update: Here is the Code for the Functions used:

# Create a description of the features.
feature_description = {
    'image/height': tf.io.FixedLenFeature([], tf.int64, default_value=0),
    'image/width': tf.io.FixedLenFeature([], tf.int64, default_value=0),
    'image/filename': tf.io.FixedLenFeature([], tf.string),
    'image/source_id': tf.io.FixedLenFeature([], tf.string),
    'image/pixels': tf.io.FixedLenFeature([target_size, target_size], dtype=tf.float32),
    'image/format': tf.io.FixedLenFeature([], tf.string),
    'image/globalscore': tf.io.FixedLenFeature([], tf.int64, default_value=0),
    'image/brixiascore': tf.io.FixedLenFeature([3,2], dtype=tf.int64)
}

def _parse_function(example_proto):
  # Parse the input `tf.Example` proto using the dictionary above.
  return tf.io.parse_single_example(example_proto, feature_description)

def _dynamic_to_4D_image(image):
    shape = tf.shape(image)
    original_rank = tf.rank(image)
    # 4D image => [N, H, W, C] or [N, C, H, W]
    # 3D image => [1, H, W, C] or [1, C, H, W]
    # 2D image => [1, H, W, 1]
    left_pad = tf.cast(tf.less_equal(original_rank, 3), dtype=tf.int32)
    right_pad = tf.cast(tf.equal(original_rank, 2), dtype=tf.int32)
    new_shape = tf.concat(
        [
            tf.ones(shape=left_pad, dtype=tf.int32),
            shape,
            tf.ones(shape=right_pad, dtype=tf.int32),
        ],
        axis=0,
    )
    return tf.reshape(image, new_shape)


def to_4D_image(image):
    """Convert 2/3/4D image to 4D image.
    Args:
      image: 2/3/4D tensor.
    Returns:
      4D tensor with the same type.
    """
    with tf.control_dependencies(
        [
            tf.debugging.assert_rank_in(
                image, [2, 3, 4], message="`image` must be 2/3/4D tensor"
            )
        ]
    ):
        ndims = image.get_shape().ndims
        if ndims is None:
            return _dynamic_to_4D_image(image)
        elif ndims == 2:
            return image[None, :, :, None]
        elif ndims == 3:
            return image[None, :, :, :]
        else:
            return image
        
def _dynamic_from_4D_image(image, original_rank):
    shape = tf.shape(image)
    # 4D image <= [N, H, W, C] or [N, C, H, W]
    # 3D image <= [1, H, W, C] or [1, C, H, W]
    # 2D image <= [1, H, W, 1]
    begin = tf.cast(tf.less_equal(original_rank, 3), dtype=tf.int32)
    end = 4 - tf.cast(tf.equal(original_rank, 2), dtype=tf.int32)
    new_shape = shape[begin:end]
    return tf.reshape(image, new_shape)


def from_4D_image(image, ndims):
    """Convert back to an image with `ndims` rank.
    Args:
      image: 4D tensor.
      ndims: The original rank of the image.
    Returns:
      `ndims`-D tensor with the same type.
    """
    with tf.control_dependencies(
        [tf.debugging.assert_rank(image, 4, message="`image` must be 4D tensor")]
    ):
        if isinstance(ndims, tf.Tensor):
            return _dynamic_from_4D_image(image, ndims)
        elif ndims == 2:
            return tf.squeeze(image, [0, 3])
        elif ndims == 3:
            return tf.squeeze(image, [0])
        else:
            return image
        
@tf.function       
def equalize_image_gray(image, data_format="channels_last"):
    """Implements Equalize function from PIL using TF ops."""

    def scale_channel(image, channel, nbins=256):
        """Scale the data in the channel to implement equalize."""
        image_dtype = image.dtype

        if data_format == "channels_last":
            image = tf.cast(image[:, :, channel], tf.int32)
        elif data_format == "channels_first":
            image = tf.cast(image[channel], tf.int32)
        else:
            raise ValueError(
                "data_format can either be channels_last or channels_first"
            )
        # Compute the histogram of the image channel.
        histo = tf.histogram_fixed_width(image, [0, nbins], nbins=nbins)

        # For the purposes of computing the step, filter out the nonzeros.
        nonzero = tf.where(tf.not_equal(histo, 0))
        nonzero_histo = tf.reshape(tf.gather(histo, nonzero), [-1])
        step = (tf.reduce_sum(nonzero_histo) - nonzero_histo[-1]) // nbins

        def build_lut(histo, step):
            # Compute the cumulative sum, shifting by step // 2
            # and then normalization by step.
            lut = (tf.cumsum(histo) + (step // 2)) // step
            # Shift lut, prepending with 0.
            lut = tf.concat([[0], lut[:-1]], 0)
            # Clip the counts to be in range.  This is done
            # in the C code for image.point.
            return tf.clip_by_value(lut, 0, nbins)

        # If step is zero, return the original image.  Otherwise, build
        # lut from the full histogram and step and then index from it.

        if step == 0:
            result = image
        else:
            result = tf.gather(build_lut(histo, step), image)

        return tf.cast(result, image_dtype)

    idx = 2 if data_format == "channels_last" else 0
    image = scale_channel(4095*image, channel=0, nbins=4096)
    image = image/tf.math.reduce_max(image)
    image = tf.expand_dims(image, axis=-1)
    return image

@tf.function
def equalize(image, data_format = "channels_last") :
    """Equalize image(s)
    Args:
      images: A tensor of shape
          (num_images, num_rows, num_columns, num_channels) (NHWC), or
          (num_images, num_channels, num_rows, num_columns) (NCHW), or
          (num_rows, num_columns, num_channels) (HWC), or
          (num_channels, num_rows, num_columns) (CHW), or
          (num_rows, num_columns) (HW). The rank must be statically known (the
          shape is not `TensorShape(None)`).
      data_format: Either 'channels_first' or 'channels_last'
    Returns:
      Image(s) with the same type and shape as `images`, equalized.
    """
    image_dims = tf.rank(image)
    image = to_4D_image(image)
    fn = partial(equalize_image_gray, data_format=data_format)
    image = tf.map_fn(fn, image)
    return from_4D_image(image, image_dims)

Leave a Comment