Computes SSIM index between img1 and img2 per color channel. This function matches the standard SSIM implementation from: Wang, Z., Bovik, A. C., Sheikh, H. R., & Simoncelli, E. P. (2004). Image quality assessment: from error visibility to structural similarity. IEEE transactions on image p
(img1,
img2,
max_val=1.0,
filter_size=11,
filter_sigma=1.5,
k1=0.01,
k2=0.03)
| 3222 | |
| 3223 | |
| 3224 | def _ssim_per_channel(img1, |
| 3225 | img2, |
| 3226 | max_val=1.0, |
| 3227 | filter_size=11, |
| 3228 | filter_sigma=1.5, |
| 3229 | k1=0.01, |
| 3230 | k2=0.03): |
| 3231 | """Computes SSIM index between img1 and img2 per color channel. |
| 3232 | |
| 3233 | This function matches the standard SSIM implementation from: |
| 3234 | Wang, Z., Bovik, A. C., Sheikh, H. R., & Simoncelli, E. P. (2004). Image |
| 3235 | quality assessment: from error visibility to structural similarity. IEEE |
| 3236 | transactions on image processing. |
| 3237 | |
| 3238 | Details: |
| 3239 | - 11x11 Gaussian filter of width 1.5 is used. |
| 3240 | - k1 = 0.01, k2 = 0.03 as in the original paper. |
| 3241 | |
| 3242 | Args: |
| 3243 | img1: First image batch. |
| 3244 | img2: Second image batch. |
| 3245 | max_val: The dynamic range of the images (i.e., the difference between the |
| 3246 | maximum the and minimum allowed values). |
| 3247 | filter_size: Default value 11 (size of gaussian filter). |
| 3248 | filter_sigma: Default value 1.5 (width of gaussian filter). |
| 3249 | k1: Default value 0.01 |
| 3250 | k2: Default value 0.03 (SSIM is less sensitivity to K2 for lower values, so |
| 3251 | it would be better if we taken the values in range of 0< K2 <0.4). |
| 3252 | |
| 3253 | Returns: |
| 3254 | A pair of tensors containing and channel-wise SSIM and contrast-structure |
| 3255 | values. The shape is [..., channels]. |
| 3256 | """ |
| 3257 | filter_size = constant_op.constant(filter_size, dtype=dtypes.int32) |
| 3258 | filter_sigma = constant_op.constant(filter_sigma, dtype=img1.dtype) |
| 3259 | |
| 3260 | shape1, shape2 = array_ops.shape_n([img1, img2]) |
| 3261 | checks = [ |
| 3262 | control_flow_ops.Assert( |
| 3263 | math_ops.reduce_all( |
| 3264 | math_ops.greater_equal(shape1[-3:-1], filter_size)), |
| 3265 | [shape1, filter_size], |
| 3266 | summarize=8), |
| 3267 | control_flow_ops.Assert( |
| 3268 | math_ops.reduce_all( |
| 3269 | math_ops.greater_equal(shape2[-3:-1], filter_size)), |
| 3270 | [shape2, filter_size], |
| 3271 | summarize=8) |
| 3272 | ] |
| 3273 | |
| 3274 | # Enforce the check to run before computation. |
| 3275 | with ops.control_dependencies(checks): |
| 3276 | img1 = array_ops.identity(img1) |
| 3277 | |
| 3278 | # TODO(sjhwang): Try to cache kernels and compensation factor. |
| 3279 | kernel = _fspecial_gauss(filter_size, filter_sigma) |
| 3280 | kernel = array_ops.tile(kernel, multiples=[1, 1, shape1[-1], 1]) |
| 3281 |
no test coverage detected