fiji / bUnwarpJ

ImageJ/Fiji plugin for consistent elastic registration of 2D images
http://imagej.net/BUnwarpJ
GNU General Public License v3.0
23 stars 10 forks source link

Output pixel value range exceeds input pixel value range #12

Open christianrickert opened 2 years ago

christianrickert commented 2 years ago

I have notice an "odd" behavior when using bUnwarpJ: the output pixel value range can exceed the input pixel value range. Log window output:

Target Image Minimum: 0, Maximum: 255 Source Image Minimum: 0.9607, Maximum: 254.9642 Registered Source Image Minimum: -2.4964, Maximum: 255.3859

What I would have expected is that the histogram of the output (registered) image is a "washed-out" (lower contrast) version of the input histogram - within the same value bounds. However, some pixel exhibit novel values: in particular, values that exceed the input image range.

Here's a simple example ImageJ2 macro:

print("\\Clear");

// load sample as target
run("AuPbSn 40");
run("32-bit");   // grayscale
rename("Target Image");

// rotate copy of target to create source
run("Duplicate...", "title=[Source Image]");
run("Rotate... ", "angle=45 grid=1 interpolation=Bilinear enlarge");

// register source with target using MOPS registration markers
run("Extract MOPS Correspondences", "source_image=[Source Image] target_image=[Target Image] initial_gaussian_blur=1.60 steps_per_scale_octave=3 minimum_image_size=64 maximum_image_size=1024 feature_descriptor_size=16 closest/next_closest_ratio=0.92 maximal_alignment_error=25 inlier_ratio=0.05 expected_transformation=Rigid")
run("bUnwarpJ", "source_image=[Source Image] target_image=[Target Image] registration=Mono image_subsample_factor=0 initial_deformation=[Very Coarse] final_deformation=Fine divergence_weight=0 curl_weight=0 landmark_weight=0 image_weight=1 consistency_weight=10 stop_threshold=0.01");

// display extrema from target and registered source
getExtrema("Target Image");  // within 8-bit range
getExtrema("Source Image");  // within 8-bit range
getExtrema("Registered Source Image");  // exceeds 8-bit range
run("Tile");  // display all windows tiled

function getExtrema(image)
{
  selectWindow(image);
  print(getTitle());
  getRawStatistics(nPixels, mean, min, max);
  print("  Minimum: " + min + ",\n  Maximum: " + max)
  run("Histogram", "bins=1024 use x_min=0 x_max=1023 y_min=min y_max=max");
}

As a workaround, I'm currently clipping the extrema of the output data to match the input data.

// get extrema before registration
getRawStatistics(nPixels, mean, min, max);
// perform registration from source_transform file
call("bunwarpj.bUnwarpJ_.loadElasticTransform", source_transform, "target", "source");
// set extrema after registration
run("Min...", "value=min slice");
run("Max...", "value=max slice");

The observed effect seems to positively correlate with the contrast of the input image. - I am not sure if this is expected behavior: But I basically ended up with fanned out pixel values in my registered recordings when compared to the values of my original recordings.

Best regards, Chris