SSIM для объема 3D-изображения

Я работаю над проблемой сверхвысокого разрешения изображения (как 2D, так и 3D) с использованием TensorFlow и использую SSIM в качестве одного из eval_metrics.

Я использую image.ssim от TF и ​​measure.comapre_ssim от skimage. Оба они дают одинаковые результаты для 2D, но всегда есть разница в результатах для 3D объемов.

Я просмотрел исходный код обоих Реализация TF и реализация skimage. Кажется, есть некоторые фундаментальные различия в том, как входные изображения рассматриваются и обрабатываются в этих двух реализациях.

Код для воспроизведения проблемы:

import numpy as np
import tensorflow as tf

from skimage import measure

# For 2-D case
np.random.seed(12345)
a = np.random.random([32, 32, 64])
b = np.random.random([32, 32, 64])

a_ = tf.convert_to_tensor(a)
b_ = tf.convert_to_tensor(b)

ssim_2d_tf = tf.image.ssim(a_, b_, 1.0)
ssim_2d_sk = measure.compare_ssim(a, b, multichannel=True, gaussian_weights=True, data_range=1.0, use_sample_covariance=False)

print (tf.Session().run(ssim_2d_tf), ssim_2d_sk)

# For 3-D case
np.random.seed(12345)
a = np.random.random([32, 32, 32, 64])
b = np.random.random([32, 32, 32, 64])

a_ = tf.convert_to_tensor(a)
b_ = tf.convert_to_tensor(b)

ssim_3d_tf = tf.image.ssim(a_, b_, 1.0)
ssim_3d_sk = measure.compare_ssim(a, b, multichannel=True, gaussian_weights=True, data_range=1.0, use_sample_covariance=False)

s_3d_tf = tf.Session().run(ssim_3d_tf)
print (np.mean(s_3d_tf), ssim_3d_sk)

Я должен взять среднее значение вывода в случае 3D, поскольку Tensorflow вычисляет SSIM по последним трем измерениям и, следовательно, дает 32 значения SSIM. Это говорит о том, что TF рассматривает изображения для SSIM в формате NHWC. Подходит ли это для SSIM по сравнению с 3D-томами?

skimage однако, похоже, использует одномерные фильтры Гаусса. Так что ясно, что даже здесь не учитывается глубина 3D-объемов.

Может ли кто-нибудь пролить свет на них и помочь мне решить, какой из них использовать дальше и почему?


person End-2-End    schedule 26.12.2018    source источник


Ответы (1)


При беглом взгляде на код кажется, что TensorFlow всегда вычисляет 2D SSIM для каждого изображения в пакете и для каждого канала. Он усредняет значения SSIM по каналам и возвращает значение для каждого изображения в пакете. Для TF массив 4D представляет собой набор 2D-изображений с несколькими каналами.

Напротив, SciKit-Image вычисляет SSIM по всем измерениям, кроме последнего, если установлено multichannel. Таким образом, в случае массива 4D он вычисляет 3D SSIM для каждого канала и усредняет значения по каналам.

Это согласуется с тем, что вы обнаружили аналогичные результаты для трехмерного массива, но разные результаты для четырехмерного массива.


Однако skimage, похоже, использует одномерные фильтры Гаусса.

Я не уверен, откуда вы это взяли, SciKit-Image использует nD Gaussian в случае nD изображения. Однако фильтр Гаусса — это разделимый фильтр, то есть его можно эффективно реализовать с помощью n применений одномерного фильтра.

person Cris Luengo    schedule 26.12.2018
comment
Спасибо за ответ. Что касается комментария к 1D-фильтру, в сравните_ssim исходный код, я вижу используется фильтр Гаусса, который дополнительно использует gaussian_filter1D. Так что я предполагаю, что этот 1D-фильтр применяется 3 раза для 3D здесь. Дай мне знать, если это правильно. - person End-2-End; 27.12.2018
comment
@End-2-End: используется gaussian_filter, который, по словам документации, является многомерным фильтром Гаусса. Да, глядя на код, который вы связали, он делает for axis..., поэтому он перебирает каждое измерение, применяя 1D-фильтр. - person Cris Luengo; 27.12.2018