diff --git a/src/main/java/BlockRedundancy2D_.java b/src/main/java/BlockRedundancy2D_.java index 0de1c94..cf062e4 100644 --- a/src/main/java/BlockRedundancy2D_.java +++ b/src/main/java/BlockRedundancy2D_.java @@ -74,15 +74,14 @@ public void run(String s) { } // Define metric possibilities - String[] metrics = new String[4]; + String[] metrics = new String[3]; metrics[0] = "Pearson's R"; metrics[1] = "Cosine similarity"; - metrics[2] = "Hu moments"; - metrics[3] = "mSSIM"; + metrics[2] = "SSIM"; // Initialize dialog box - NonBlockingGenericDialog gd = new NonBlockingGenericDialog("SReD: Block Redundancy (2D)"); - gd.addChoice("Patch:", titles, titles[0]); + NonBlockingGenericDialog gd = new NonBlockingGenericDialog("SReD: Block Repetition (2D)"); + gd.addChoice("Block:", titles, titles[0]); gd.addChoice("Image:", titles, titles[1]); gd.addSlider("Filter constant: ", 0.0f, 5.0f, 1.0f, 0.1f); gd.addChoice("Metric:", metrics, metrics[0]); @@ -131,7 +130,7 @@ public void run(String s) { // ------------------------------------------------- // ImagePlus imp = WindowManager.getImage(patchID); if (imp == null) { - IJ.error("Patch image not found. Try again."); + IJ.error("Block image not found. Try again."); return; } ImageProcessor ip = imp.getProcessor(); @@ -142,7 +141,7 @@ public void run(String s) { // Check if patch dimensions are odd, otherwise kill program if (bW % 2 == 0 || bH % 2 == 0) { - IJ.error("Patch dimensions must be odd (e.g., 3x3 or 5x5). Please try again."); + IJ.error("Block dimensions must be odd (e.g., 3x3 or 5x5). Please try again."); return; } @@ -186,40 +185,13 @@ public void run(String s) { minimizer.run(); refPixels = VarianceStabilisingTransform2D_.getGAT(refPixels, minimizer.gain, minimizer.sigma, minimizer.offset); IJ.log("Done."); -/* - // ----------------------------------- // - // ---- Calculate gaussian window ---- // - // ----------------------------------- // - - // Define parameters - double[] gaussianWindow = new double[bW*bH]; // The full window before keeping only the pixels within the inbound circle/ellipse - double gaussianSum = 0.0; - double sigma_x = bW/1.0; // Gaussian sigma in the x-direction (SSIM paper uses 7.3 instead of 4) - double sigma_y = bH/1.0; // Gaussian sigma in the y-direction - - // Calculate gaussian window - for(int j=0; j0.0f) { - showStatus("Calculating relevance map..."); - - // Create OpenCL program - String programStringGetRelevanceMap = getResourceAsString(BlockRedundancy2D_.class, "kernelGetRelevanceMap2D.cl"); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$WIDTH$", "" + w); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$HEIGHT$", "" + h); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$PATCH_SIZE$", "" + patchSize); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$BRW$", "" + bRW); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$BRH$", "" + bRH); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$EPSILON$", "" + EPSILON); - programGetRelevanceMap = context.createProgram(programStringGetRelevanceMap).build(); - - // Create and fill buffers - float[] relevanceMap = new float[wh]; - clRelevanceMap = context.createFloatBuffer(wh, READ_WRITE); - fillBufferWithFloatArray(clRelevanceMap, relevanceMap); - queue.putWriteBuffer(clRelevanceMap, true); - queue.finish(); - - // Create OpenCL kernel and set args - kernelGetRelevanceMap = programGetRelevanceMap.createCLKernel("kernelGetRelevanceMap2D"); - - argn = 0; - kernelGetRelevanceMap.setArg(argn++, clRefPixels); - kernelGetRelevanceMap.setArg(argn++, clRelevanceMap); - - // Calculate - queue.put2DRangeKernel(kernelGetRelevanceMap, 0, 0, w, h, 0, 0); - queue.finish(); - - // Read the relevance map back from the device - queue.putReadBuffer(clRelevanceMap, true); - for (int y=0; y noiseMeanVar * filterConstant) { - float pixelValue = pearsonMap[j * w + i]; - if (pixelValue > pearsonMax) { - pearsonMax = pixelValue; - } - if (pixelValue < pearsonMin) { - pearsonMin = pixelValue; - } - } - } - } - - // Remap pixels - for (int j = bRH; j < h - bRH; j++) { - for (int i = bRW; i < w - bRW; i++) { - if (relevanceMap[j * w + i] > noiseMeanVar * filterConstant) { - pearsonMap[j * w + i] = (pearsonMap[j * w + i] - pearsonMin) / (pearsonMax - pearsonMin + EPSILON); - } - } - } - } - } - - // Release resources - context.release(); - - - // ------------------------- // - // ---- Display results ---- // - // ------------------------- // - - FloatProcessor fp1 = new FloatProcessor(w, h, pearsonMap); - ImagePlus imp1 = new ImagePlus("Block Redundancy Map", fp1); - imp1.show(); } if(metric == metrics[1]) { // Cosine similarity @@ -666,9 +516,8 @@ public void run(String s) { programGetPatchDiffStd = context.createProgram(programStringGetPatchDiffStd).build(); // Fill OpenCL buffers - float[] diffStdMap = new float[wh]; clDiffStdMap = context.createFloatBuffer(wh, READ_WRITE); - fillBufferWithFloatArray(clDiffStdMap, diffStdMap); + fillBufferWithFloatArray(clDiffStdMap, repetitionMap); // Create kernel and set args kernelGetPatchDiffStd = programGetPatchDiffStd.createCLKernel("kernelGetPatchDiffStd2D"); @@ -686,7 +535,7 @@ public void run(String s) { queue.putReadBuffer(clDiffStdMap, true); for (int y=0; y0.0f) { - showStatus("Calculating relevance map..."); - - // Create OpenCL program - String programStringGetRelevanceMap = getResourceAsString(BlockRedundancy2D_.class, "kernelGetRelevanceMap2D.cl"); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$WIDTH$", "" + w); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$HEIGHT$", "" + h); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$PATCH_SIZE$", "" + patchSize); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$BRW$", "" + bRW); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$BRH$", "" + bRH); - programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$EPSILON$", "" + EPSILON); - programGetRelevanceMap = context.createProgram(programStringGetRelevanceMap).build(); - - // Create and fill buffers - float[] relevanceMap = new float[wh]; - clRelevanceMap = context.createFloatBuffer(wh, READ_WRITE); - fillBufferWithFloatArray(clRelevanceMap, relevanceMap); - queue.putWriteBuffer(clRelevanceMap, true); - queue.finish(); - - // Create OpenCL kernel and set args - kernelGetRelevanceMap = programGetRelevanceMap.createCLKernel("kernelGetRelevanceMap2D"); - - argn = 0; - kernelGetRelevanceMap.setArg(argn++, clRefPixels); - kernelGetRelevanceMap.setArg(argn++, clRelevanceMap); - - // Calculate - queue.put2DRangeKernel(kernelGetRelevanceMap, 0, 0, w, h, 0, 0); - queue.finish(); - - // Read the relevance map back from the device - queue.putReadBuffer(clRelevanceMap, true); - for (int y=0; y noiseMeanVar * filterConstant) { - float pixelValue = diffStdMap[j * w + i]; - if (pixelValue > diffStdMax) { - diffStdMax = pixelValue; - } - if (pixelValue < diffStdMin) { - diffStdMin = pixelValue; - } - } - } - } - - // Remap pixels - for (int j=bRH; j noiseMeanVar * filterConstant) { - diffStdMap[j*w+i] = (diffStdMap[j*w+i]-diffStdMin)/(diffStdMax-diffStdMin+EPSILON); - } - } - } - } - } - - // Release resources - context.release(); - - - // ------------------------- // - // ---- Display results ---- // - // ------------------------- // - - FloatProcessor fp1 = new FloatProcessor(w, h, diffStdMap); - ImagePlus imp1 = new ImagePlus("Block Redundancy Map", fp1); - imp1.show(); } - if(metric == metrics[2]) { // Hu moments - // Create OpenCL program - String programStringGetPatchHu = getResourceAsString(BlockRedundancy2D_.class, "kernelGetPatchHu2D.cl"); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$WIDTH$", "" + w); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$HEIGHT$", "" + h); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$PATCH_SIZE$", "" + patchSize); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$BW$", "" + bW); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$BH$", "" + bH); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$BRW$", "" + bRW); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$BRH$", "" + bRH); - programStringGetPatchHu = replaceFirst(programStringGetPatchHu, "$EPSILON$", "" + EPSILON); - programGetPatchHu = context.createProgram(programStringGetPatchHu).build(); + if(metric == metrics[2]) { // SSIM + showStatus("Calculating SSIM..."); + + // Build OpenCL program + String programStringGetPatchSsim = getResourceAsString(BlockRedundancy2D_.class, "kernelGetPatchSsim2D.cl"); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$WIDTH$", "" + w); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$HEIGHT$", "" + h); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$PATCH_SIZE$", "" + patchSize); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$BW$", "" + bW); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$BH$", "" + bH); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$BRW$", "" + bRW); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$BRH$", "" + bRH); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$PATCH_MEAN$", "" + patchMeanFloat); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$PATCH_STD$", "" + patchStdDev); + programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$EPSILON$", "" + EPSILON); + programGetPatchSsim = context.createProgram(programStringGetPatchSsim).build(); + //System.out.println(programGetPatchSsim.getBuildLog()); // Print program build log to check for errors // Fill OpenCL buffers clPatchPixels = context.createFloatBuffer(patchSize, READ_ONLY); fillBufferWithFloatArray(clPatchPixels, patchPixelsFloat); - float[] huMap = new float[wh]; - clHuMap = context.createFloatBuffer(wh, READ_WRITE); - fillBufferWithFloatArray(clHuMap, huMap); + clSsimMap = context.createFloatBuffer(wh, READ_WRITE); + fillBufferWithFloatArray(clSsimMap, repetitionMap); - // Create OpenCL kernel and set args - kernelGetPatchHu = programGetPatchHu.createCLKernel("kernelGetPatchHu2D"); + // Create kernel and set args + kernelGetPatchSsim = programGetPatchSsim.createCLKernel("kernelGetPatchSsim2D"); argn = 0; - kernelGetPatchHu.setArg(argn++, clPatchPixels); - kernelGetPatchHu.setArg(argn++, clRefPixels); - kernelGetPatchHu.setArg(argn++, clLocalMeans); - kernelGetPatchHu.setArg(argn++, clHuMap); + kernelGetPatchSsim.setArg(argn++, clPatchPixels); + kernelGetPatchSsim.setArg(argn++, clRefPixels); + kernelGetPatchSsim.setArg(argn++, clLocalMeans); + kernelGetPatchSsim.setArg(argn++, clLocalStds); + kernelGetPatchSsim.setArg(argn++, clSsimMap); - // Calculate + // Calculate SSIM queue.putWriteBuffer(clPatchPixels, true); - queue.putWriteBuffer(clHuMap, true); + queue.putWriteBuffer(clSsimMap, true); + queue.put2DRangeKernel(kernelGetPatchSsim, 0, 0, w, h, 0, 0); queue.finish(); - // Enqueue kernel - queue.put2DRangeKernel(kernelGetPatchHu, 0, 0, w, h, 0, 0); - - // Read results back from the device - queue.putReadBuffer(clHuMap, true); + // Read SSIM back from the GPU + queue.putReadBuffer(clSsimMap, true); for (int y=0; ynoiseMeanVar*filterConstant) { - float pixelValue = huMap[j * w + i]; - if (pixelValue > huMax) { - huMax = pixelValue; - } - if (pixelValue < huMin) { - huMin = pixelValue; - } - } - } - } - - // Remap pixels - float[] huMapNorm = new float[wh]; - for(int j=bRH; jnoiseMeanVar*filterConstant) { - huMapNorm[j*w+i] = (huMap[j*w+i] - huMin) / (huMax - huMin); - } - } - } - - - // ------------------------- // - // ---- Display results ---- // - // ------------------------- // - - FloatProcessor fp1 = new FloatProcessor(w, h, huMapNorm); - ImagePlus imp1 = new ImagePlus("Block Redundancy Map", fp1); - imp1.show(); + clSsimMap.release(); + programGetPatchSsim.release(); } - if(metric == metrics[3]) { // mSSIM (i.e., SSIM without the luminance component) - showStatus("Calculating mSSIM..."); + if(metric == metrics[2]) { // SSIM + showStatus("Calculating SSIM..."); // Build OpenCL program String programStringGetPatchSsim = getResourceAsString(BlockRedundancy2D_.class, "kernelGetPatchSsim2D.cl"); @@ -956,17 +621,17 @@ public void run(String s) { programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$PATCH_STD$", "" + patchStdDev); programStringGetPatchSsim = replaceFirst(programStringGetPatchSsim, "$EPSILON$", "" + EPSILON); programGetPatchSsim = context.createProgram(programStringGetPatchSsim).build(); + //System.out.println(programGetPatchSsim.getBuildLog()); // Print program build log to check for errors // Fill OpenCL buffers clPatchPixels = context.createFloatBuffer(patchSize, READ_ONLY); fillBufferWithFloatArray(clPatchPixels, patchPixelsFloat); - float[] ssimMap = new float[wh]; clSsimMap = context.createFloatBuffer(wh, READ_WRITE); - fillBufferWithFloatArray(clSsimMap, ssimMap); + fillBufferWithFloatArray(clSsimMap, repetitionMap); // Create kernel and set args - kernelGetPatchSsim = programGetPatchSsim.createCLKernel("kernelGetSynthPatchSsim2D"); + kernelGetPatchSsim = programGetPatchSsim.createCLKernel("kernelGetPatchSsim2D"); argn = 0; kernelGetPatchSsim.setArg(argn++, clPatchPixels); @@ -975,17 +640,17 @@ public void run(String s) { kernelGetPatchSsim.setArg(argn++, clLocalStds); kernelGetPatchSsim.setArg(argn++, clSsimMap); - // Calculate Pearson's correlation coefficient (reference patch vs. all) + // Calculate SSIM queue.putWriteBuffer(clPatchPixels, true); queue.putWriteBuffer(clSsimMap, true); queue.put2DRangeKernel(kernelGetPatchSsim, 0, 0, w, h, 0, 0); queue.finish(); - // Read Pearson's coefficients back from the GPU + // Read SSIM back from the GPU queue.putReadBuffer(clSsimMap, true); for (int y=0; y0.0f) { + showStatus("Calculating relevance map..."); - argn = 0; - kernelGetRelevanceMap.setArg(argn++, clRefPixels); - kernelGetRelevanceMap.setArg(argn++, clRelevanceMap); + // Create OpenCL program + String programStringGetRelevanceMap = getResourceAsString(BlockRedundancy2D_.class, "kernelGetRelevanceMap2D.cl"); + programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$WIDTH$", "" + w); + programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$HEIGHT$", "" + h); + programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$PATCH_SIZE$", "" + patchSize); + programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$BRW$", "" + bRW); + programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$BRH$", "" + bRH); + programStringGetRelevanceMap = replaceFirst(programStringGetRelevanceMap, "$EPSILON$", "" + EPSILON); + programGetRelevanceMap = context.createProgram(programStringGetRelevanceMap).build(); + + // Create and fill buffers + float[] relevanceMap = new float[wh]; + clRelevanceMap = context.createFloatBuffer(wh, READ_WRITE); + fillBufferWithFloatArray(clRelevanceMap, relevanceMap); + queue.putWriteBuffer(clRelevanceMap, true); + queue.finish(); - // Calculate - queue.put2DRangeKernel(kernelGetRelevanceMap, 0, 0, w, h, 0, 0); - queue.finish(); + // Create OpenCL kernel and set args + kernelGetRelevanceMap = programGetRelevanceMap.createCLKernel("kernelGetRelevanceMap2D"); - // Read the relevance map back from the device - queue.putReadBuffer(clRelevanceMap, true); - for (int y=0; ynoiseMeanVar*filterConstant) { - float pixelValue = ssimMap[j*w+i]; - if (pixelValue > ssimMax) { - ssimMax = pixelValue; + float pearsonMin = Float.MAX_VALUE; + float pearsonMax = -Float.MAX_VALUE; + + for (int j = bRH; j < h - bRH; j++) { + for (int i = bRW; i < w - bRW; i++) { + if (relevanceMap[j * w + i] > noiseMeanVar * filterConstant) { + float pixelValue = repetitionMap[j * w + i]; + if (pixelValue > pearsonMax) { + pearsonMax = pixelValue; } - if (pixelValue < ssimMin) { - ssimMin = pixelValue; + if (pixelValue < pearsonMin) { + pearsonMin = pixelValue; } } } } // Remap pixels - for (int j=bRH; jnoiseMeanVar*filterConstant) { - ssimMapNorm[j*w+i] = (ssimMap[j*w+i]-ssimMin) / (ssimMax-ssimMin); + for (int j = bRH; j < h - bRH; j++) { + for (int i = bRW; i < w - bRW; i++) { + if (relevanceMap[j * w + i] > noiseMeanVar * filterConstant) { + repetitionMap[j * w + i] = (repetitionMap[j * w + i] - pearsonMin) / (pearsonMax - pearsonMin + EPSILON); } } } - }else{ - - // -------------------------- // - // ---- Normalize output ---- // - // -------------------------- // - - // Find min and max - float ssimMin = Float.MAX_VALUE; - float ssimMax = -Float.MAX_VALUE; - - for (int j=bRH; j ssimMax) { - ssimMax = pixelValue; - } - if (pixelValue < ssimMin) { - ssimMin = pixelValue; - } - } - } - - // Remap pixels - for (int j=bRH; j