Mage-VL / neural_codec /DCVC /src /utils /metrics.py
Xinjie-Q's picture
Upload Mage-VL: unified codec-native streaming VLM (image+video understanding + proactive gate)
12acbba verified
Raw
History Blame Contribute Delete
3.17 kB
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import numpy as np
from scipy import signal
from scipy import ndimage
def fspecial_gauss(size, sigma):
x, y = np.mgrid[-size // 2 + 1:size // 2 + 1, -size // 2 + 1:size // 2 + 1]
g = np.exp(-((x**2 + y**2) / (2.0 * sigma**2)))
return g / g.sum()
def calc_ssim(img1, img2, data_range=255):
img1 = img1.astype(np.float64)
img2 = img2.astype(np.float64)
size = 11
sigma = 1.5
window = fspecial_gauss(size, sigma)
K1 = 0.01
K2 = 0.03
C1 = (K1 * data_range)**2
C2 = (K2 * data_range)**2
mu1 = signal.fftconvolve(window, img1, mode='valid')
mu2 = signal.fftconvolve(window, img2, mode='valid')
mu1_sq = mu1 * mu1
mu2_sq = mu2 * mu2
mu1_mu2 = mu1 * mu2
sigma1_sq = signal.fftconvolve(window, img1 * img1, mode='valid') - mu1_sq
sigma2_sq = signal.fftconvolve(window, img2 * img2, mode='valid') - mu2_sq
sigma12 = signal.fftconvolve(window, img1 * img2, mode='valid') - mu1_mu2
return (((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
(sigma1_sq + sigma2_sq + C2)),
(2.0 * sigma12 + C2) / (sigma1_sq + sigma2_sq + C2))
def calc_msssim(img1, img2, data_range=255):
'''
img1 and img2 are 2D arrays
'''
level = 5
weight = np.array([0.0448, 0.2856, 0.3001, 0.2363, 0.1333])
height, width = img1.shape
if height < 176 or width < 176:
# according to HM implementation
level = 4
weight = np.array([0.0517, 0.3295, 0.3462, 0.2726])
if height < 88 or width < 88:
assert False
downsample_filter = np.ones((2, 2)) / 4.0
im1 = img1.astype(np.float64)
im2 = img2.astype(np.float64)
mssim = np.array([])
mcs = np.array([])
for _ in range(level):
ssim_map, cs_map = calc_ssim(im1, im2, data_range=data_range)
mssim = np.append(mssim, ssim_map.mean())
mcs = np.append(mcs, cs_map.mean())
filtered_im1 = ndimage.filters.convolve(im1, downsample_filter,
mode='reflect')
filtered_im2 = ndimage.filters.convolve(im2, downsample_filter,
mode='reflect')
im1 = filtered_im1[::2, ::2]
im2 = filtered_im2[::2, ::2]
return (np.prod(mcs[0:level - 1]**weight[0:level - 1]) *
(mssim[level - 1]**weight[level - 1]))
def calc_msssim_rgb(img1, img2, data_range=255):
'''
img1 and img2 are arrays with 3xHxW
'''
msssim = 0
for i in range(3):
msssim += calc_msssim(img1[i, :, :], img2[i, :, :], data_range)
return msssim / 3
def calc_psnr(img1, img2, data_range=255):
'''
img1 and img2 are arrays with same shape
'''
img1 = img1.astype(np.float64)
img2 = img2.astype(np.float64)
mse = np.mean(np.square(img1 - img2))
if np.isnan(mse) or np.isinf(mse):
return -999.9
if mse > 1e-10:
psnr = 10 * np.log10(data_range * data_range / mse)
else:
psnr = 999.9
if psnr > 99.9:
psnr = 99.9
return psnr