def compare(self, image: np.ndarray, reference: np.ndarray) -> float: # This implementations is based on # https://docs.opencv.org/2.4/doc/tutorials/highgui/video-input-psnr-ssim/video-input-psnr-ssim.html _, max_pixel_value = _utilities._get_image_dtype_range(image.dtype) C1 = (self._k1 * max_pixel_value)**2.0 C2 = (self._k2 * max_pixel_value)**2.0 image = image.astype(compimg.config.intermediate_dtype) reference = reference.astype(compimg.config.intermediate_dtype) x = image y = reference y_squared = reference * reference x_squared = image * image x_times_y = image * reference x_mean = kernels.convolve(x, _SSIM_GAUSSIAN_KERNEL_11X11) y_mean = kernels.convolve(y, _SSIM_GAUSSIAN_KERNEL_11X11) x_mean_squared = x_mean * x_mean y_mean_squared = y_mean * y_mean sigma_x_squared = kernels.convolve(x_squared, _SSIM_GAUSSIAN_KERNEL_11X11) sigma_x_squared -= x_mean_squared sigma_y_squared = kernels.convolve(y_squared, _SSIM_GAUSSIAN_KERNEL_11X11) sigma_y_squared -= y_mean_squared sigma_x_y = kernels.convolve(x_times_y, _SSIM_GAUSSIAN_KERNEL_11X11) sigma_x_y -= x_mean * y_mean t1 = 2 * x_mean * y_mean + C1 t2 = 2 * sigma_x_y + C2 t3 = t1 * t2 t1 = x_mean_squared + y_mean_squared + C1 t2 = sigma_x_squared + sigma_y_squared + C2 t1 = t1 * t2 ssim_map = t3 / t1 return np.mean(ssim_map)
def test_convolve_work_correctly_on_one_channel_image(): image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8) kernel = kernels.BOX_BLUR_3X3 filtered_image = kernels.convolve(image, kernel) assert filtered_image.shape == (1, 1) assert filtered_image[0][0] == 5.0
def test_convolve_work_correctly_on_three_channels(): image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8) image = image.reshape((3, 3, 1)) image = np.concatenate((image, image, image), axis=2) kernel = kernels.BOX_BLUR_3X3 filtered_image = kernels.convolve(image, kernel) assert filtered_image.shape == (1, 1, 3) assert np.array_equal(filtered_image[0][0], [5.0, 5.0, 5.0])
def compare(self, image: np.ndarray, reference: np.ndarray) -> float: _, max_pixel_value = _utilities._get_image_dtype_range(image.dtype) C1 = (self._k1 * max_pixel_value)**2.0 C2 = (self._k2 * max_pixel_value)**2.0 C3 = C2 / 2.0 image = image.astype(compimg.config.intermediate_dtype) reference = reference.astype(compimg.config.intermediate_dtype) x = image y = image x_mean = kernels.convolve(x, _SSIM_GAUSSIAN_KERNEL_11X11) y_mean = kernels.convolve(y, _SSIM_GAUSSIAN_KERNEL_11X11) x_mean_squared = x_mean * x_mean y_mean_squared = y_mean * y_mean sobel_image = self._apply_sobel(image) sobel_reference = self._apply_sobel(reference) # sx means sobel_x sx_squared = sobel_image * sobel_image sy_squared = sobel_reference * sobel_reference sxy = sobel_reference * sobel_image sx_mean = kernels.convolve(sobel_image, _SSIM_GAUSSIAN_KERNEL_11X11) sy_mean = kernels.convolve(sobel_reference, _SSIM_GAUSSIAN_KERNEL_11X11) sx_mean_squared = sx_mean * sx_mean sy_mean_squared = sy_mean * sy_mean sigma_sx_squared = kernels.convolve(sx_squared, _SSIM_GAUSSIAN_KERNEL_11X11) sigma_sx_squared -= sx_mean_squared sigma_sy_squared = kernels.convolve(sy_squared, _SSIM_GAUSSIAN_KERNEL_11X11) sigma_sy_squared -= sy_mean_squared sigma_sxy = kernels.convolve(sxy, _SSIM_GAUSSIAN_KERNEL_11X11) sigma_sxy -= sx_mean * sy_mean luminance = (2 * x_mean * y_mean + C1) / (x_mean_squared + y_mean_squared + C1) contrast = (2 * np.sqrt(sigma_sx_squared) * np.sqrt(sigma_sy_squared) + C2) / (sigma_sx_squared + sigma_sy_squared + C2) structure = (sigma_sxy + C3) / ( np.sqrt(sigma_sx_squared) * np.sqrt(sigma_sy_squared) + C3) return np.mean(luminance * contrast * structure)
def _apply_sobel(self, array: np.ndarray) -> np.ndarray: array = EdgePad(1).apply(array) array1 = kernels.convolve(array, kernels.HORIZONTAL_SOBEL_3x3) array2 = kernels.convolve(array, kernels.VERTICAL_SOBEL_3x3) return array1 + array2
def test_convolve_raises_when_kernel_is_not_2d_array(): image = np.zeros((10, 10)) kernel = np.array(np.ones((4, 4, 3))) with pytest.raises(KernelNot2DArray): kernels.convolve(image, kernel)
def test_convolve_raises_when_kernel_is_not_odd_shape(): image = np.zeros((10, 10)) kernel = np.array(np.ones((4, 4))) with pytest.raises(KernelShapeNotOddError): kernels.convolve(image, kernel)
def test_convolve_raises_when_kernel_is_bigger(): image = np.zeros((2, 2)) kernel = kernels.BOX_BLUR_3X3 with pytest.raises(KernelBiggerThanImageError): kernels.convolve(image, kernel)