Add support for skipping windows in MssimCalculator.
By skipping every other row and column, SSIM calculation time reduces by 10-30%. PiperOrigin-RevId: 474286702
This commit is contained in:
parent
3e0ad6d804
commit
6dd2a6dac6
@ -44,23 +44,47 @@ import static java.lang.Math.pow;
|
||||
|
||||
private MssimCalculator() {}
|
||||
|
||||
/**
|
||||
* Calculates the Mean Structural Similarity (MSSIM) between two images with window skipping.
|
||||
*
|
||||
* @see #calculate(byte[], byte[], int, int, boolean).
|
||||
*/
|
||||
public static double calculate(
|
||||
byte[] referenceBuffer, byte[] distortedBuffer, int width, int height) {
|
||||
return calculate(
|
||||
referenceBuffer, distortedBuffer, width, height, /* enableWindowSkipping= */ true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Mean Structural Similarity (MSSIM) between two images.
|
||||
*
|
||||
* <p>The images are split into a grid of windows. For each window, the structural similarity
|
||||
* (SSIM) is calculated. The MSSIM returned from this method is the mean of these SSIM values. If
|
||||
* window skipping is enabled, only every other row and column are considered, thereby only one in
|
||||
* four windows are evaluated.
|
||||
*
|
||||
* @param referenceBuffer The luma channel (Y) buffer of the reference image.
|
||||
* @param distortedBuffer The luma channel (Y) buffer of the distorted image.
|
||||
* @param width The image width in pixels.
|
||||
* @param height The image height in pixels.
|
||||
* @param enableWindowSkipping Whether to skip every other row and column when evaluating windows
|
||||
* for SSIM calculation.
|
||||
* @return The MSSIM score between the input images.
|
||||
*/
|
||||
public static double calculate(
|
||||
byte[] referenceBuffer, byte[] distortedBuffer, int width, int height) {
|
||||
byte[] referenceBuffer,
|
||||
byte[] distortedBuffer,
|
||||
int width,
|
||||
int height,
|
||||
boolean enableWindowSkipping) {
|
||||
double totalSsim = 0;
|
||||
int windowsCount = 0;
|
||||
|
||||
for (int currentWindowY = 0; currentWindowY < height; currentWindowY += WINDOW_SIZE) {
|
||||
int dimensionIncrement = WINDOW_SIZE * (enableWindowSkipping ? 2 : 1);
|
||||
|
||||
for (int currentWindowY = 0; currentWindowY < height; currentWindowY += dimensionIncrement) {
|
||||
int windowHeight = computeWindowSize(currentWindowY, height);
|
||||
for (int currentWindowX = 0; currentWindowX < width; currentWindowX += WINDOW_SIZE) {
|
||||
for (int currentWindowX = 0; currentWindowX < width; currentWindowX += dimensionIncrement) {
|
||||
windowsCount++;
|
||||
int windowWidth = computeWindowSize(currentWindowX, width);
|
||||
int bufferIndexOffset =
|
||||
|
@ -62,6 +62,34 @@ public class MssimCalculatorTest {
|
||||
.isEqualTo(63);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateSsim_withWindowSkipping_similarToWithout() throws Exception {
|
||||
Bitmap referenceBitmap = readBitmap("media/bitmap/sample_mp4_first_frame/original.png");
|
||||
Bitmap distortedBitmap =
|
||||
readBitmap("media/bitmap/sample_mp4_first_frame/increase_brightness.png");
|
||||
byte[] referenceLuminosity = bitmapToLuminosityArray(referenceBitmap);
|
||||
byte[] distortedLuminosity = bitmapToLuminosityArray(distortedBitmap);
|
||||
|
||||
assertThat(
|
||||
(int)
|
||||
(MssimCalculator.calculate(
|
||||
referenceLuminosity,
|
||||
distortedLuminosity,
|
||||
referenceBitmap.getWidth(),
|
||||
referenceBitmap.getHeight(),
|
||||
/* enableWindowSkipping= */ false)
|
||||
* 100))
|
||||
.isEqualTo(
|
||||
(int)
|
||||
(MssimCalculator.calculate(
|
||||
referenceLuminosity,
|
||||
distortedLuminosity,
|
||||
referenceBitmap.getWidth(),
|
||||
referenceBitmap.getHeight(),
|
||||
/* enableWindowSkipping= */ true)
|
||||
* 100));
|
||||
}
|
||||
|
||||
private static Bitmap readBitmap(String assetString) throws IOException {
|
||||
try (InputStream inputStream = getApplicationContext().getAssets().open(assetString)) {
|
||||
return BitmapFactory.decodeStream(inputStream);
|
||||
|
Loading…
x
Reference in New Issue
Block a user