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() {}
|
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.
|
* 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 referenceBuffer The luma channel (Y) buffer of the reference image.
|
||||||
* @param distortedBuffer The luma channel (Y) buffer of the distorted image.
|
* @param distortedBuffer The luma channel (Y) buffer of the distorted image.
|
||||||
* @param width The image width in pixels.
|
* @param width The image width in pixels.
|
||||||
* @param height The image height 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.
|
* @return The MSSIM score between the input images.
|
||||||
*/
|
*/
|
||||||
public static double calculate(
|
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;
|
double totalSsim = 0;
|
||||||
int windowsCount = 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);
|
int windowHeight = computeWindowSize(currentWindowY, height);
|
||||||
for (int currentWindowX = 0; currentWindowX < width; currentWindowX += WINDOW_SIZE) {
|
for (int currentWindowX = 0; currentWindowX < width; currentWindowX += dimensionIncrement) {
|
||||||
windowsCount++;
|
windowsCount++;
|
||||||
int windowWidth = computeWindowSize(currentWindowX, width);
|
int windowWidth = computeWindowSize(currentWindowX, width);
|
||||||
int bufferIndexOffset =
|
int bufferIndexOffset =
|
||||||
|
@ -62,6 +62,34 @@ public class MssimCalculatorTest {
|
|||||||
.isEqualTo(63);
|
.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 {
|
private static Bitmap readBitmap(String assetString) throws IOException {
|
||||||
try (InputStream inputStream = getApplicationContext().getAssets().open(assetString)) {
|
try (InputStream inputStream = getApplicationContext().getAssets().open(assetString)) {
|
||||||
return BitmapFactory.decodeStream(inputStream);
|
return BitmapFactory.decodeStream(inputStream);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user