How to retrieve the parameters calculated and used by ImageAdjust?
Major update at the bottom. First part may be obsolete.
A brute force approach:
Define a function that provides a measure of the difference between the automatically adjusted image and an image with given contrast, brightness and gamma adjustments (for now, this only works for images that are made of a raster of color triplets):
ClearAll[f];
f[c_?NumericQ, b_?NumericQ, γ_?NumericQ, im_Image] :=
Total[Map[#.# &, ImageData@ImageAdjust[im] - ImageData@ImageAdjust[im, {c, b, γ}], {2}], 2]
Get an image:
img=Import["http://i.stack.imgur.com/nAaCm.png"]
Now minimize the image differences:
adj = FindMinimum[f[c, b, γ, img], {{c, 0.1, 0, -1, 1}, {b, 0.1, 0, -1, 1}, {γ, 1.1, 1, 0.1, 3}}]
{14.19915417, {c -> -0.06143890985, b -> 0.09520280553, γ -> 1.094933574}}
Comparison of original image and automatically adjusted image:
Row[{img, ImageReflect[ImageAdjust[img], Left -> Right], img}]
Comparison of the semi-automatically adjusted image and fully automatically adjusted image:
Row[{ImageAdjust[img, {c, b, γ} /. adj[[2]]],
ImageReflect[ImageAdjust[img], Left -> Right],
ImageAdjust[img, {c, b, γ} /. adj[[2]]]}
]
The differences are small:
ImageSubtract[ImageAdjust[img, {c, b, γ} /. adj[[2]]], ImageAdjust[img]]
And 'small' is this:
ImageSubtract[ImageAdjust[img, {c, b, γ} /. adj[[2]]], ImageAdjust[img]] // ImageData // Max
0.0431372549
Using ImageAdjust
itself to enhance those differences:
ImageSubtract[ImageAdjust[img, {c, b, γ} /. adj[[2]]], ImageAdjust[img]] // ImageAdjust
Not quite an exact match but close.
EDIT
Originally, I believed that ImageAdjust
does a simple histogram stretch, scaling the maximum pixel value to 1 and the minimum to 0, basically this:
imgd = img // ImageData;
min = Min[imgd];
max = Max[imgd];
Rescale[imgd, {min, max}, {0, 1}]
But that simply didn't work out. If I use the measure introduced in the beginning to determine the difference between the {c,b,γ}-adjusted pictures and the automatically ImageAdjusted
pictures on the one hand and the rescaled pictures and the automatically ImageAdjusted
pictures on the other hand, the {c,b,γ} seems to be better 4 out of the 5 test images I used it on.
(
img = #;
imgd = img // ImageData;
min = Min[imgd];
max = Max[imgd];
adj = FindMinimum[f[c, b, γ, img],
{{c, 0.1, 0, -1, 1}, {b, 0.1, 0, -1, 1}, {γ, 1.1, 1, 0.1, 3}}];
{Total[Map[#.# &,
ImageData@ImageAdjust[img]-ImageData@ImageAdjust[img, {c, b, γ} /. adj[[2]]], {2}],
2],
Total[Map[#.# &, ImageData@ImageAdjust[img]-Rescale[imgd, {min, max}, {0, 1}], {2}], 2]
}
) & /@ { ...images...}
For the five pictures on the ImageAdjust
doc page I get:
{{50.5394233, 81.76899059}, {14.19915417, 14.46839005}, {30.34660515, 46.0902785}, {6.459238754, 2.528418174}, {537.6580546, 1011.243348}}
It seems that ImageAdjust
does more than a simple stretching of the values. It probably uses histogram equalization, which linearizes the cumulative distribution function of the pixel intensity values. This is a rather non-linear transformation. It probably requires a transformation to another color space first, to separate color values from luminance values (CIELab for instance). The transformation will then be done on the luminance component only after which an inverse color space transformation occurs.
Yet another edit
Trying to test the hypothesis Mathematica is using histogram equalization.
Load an image and turn it into grayscale (we won't do this colorspace hence and forth stuff here):
img = Import["http://i.stack.imgur.com/xGMge.png"]
imgG = ImageData[ColorConvert[img, "Grayscale"]];
Do histogram equalization:
ClearAll[cdf];
SetAttributes[cdf, Listable]
Scan[(cdf[#[[1]]] = #[[2]]) &,
Transpose[MapAt[Accumulate, Transpose[Sort@Tally[Flatten[imgG]]], 2]]]
imgH = (cdf[imgG] - cdf[Min[imgG]])/(Times @@ ImageDimensions[img] - cdf[Min[imgG]]);
Accumulated counts before equalization:
ListPlot@Transpose[MapAt[Accumulate, Transpose[Sort@Tally[Flatten[imgG]]], 2]]
Accumulated counts after equalization:
ListPlot@Transpose[MapAt[Accumulate, Transpose[Sort@Tally[Flatten[imgH]]], 2]]
Image comparisons:
Original grayscale image:
imgG // Image
Automatically adjusted image:
imgG // Image // ImageAdjust
Histogram equalized image:
imgH // Image
Clearly, ImageAdjust
does not do a histogram equalization.
Final edit
For grayscale images at least, Mathematica seems to do a simple rescaling after all. The rescaling I used above used the minimum and maximum values measured over all color channels. In a grayscale image, rescaling with
Rescale[imgG, {Min[imgG], Max[imgG]}, {0, 1}]
yields an image that is virtually identical to the adjusted image:
(imgG // Image // ImageAdjust // ImageData) -
Rescale[imgG, {Min[imgG], Max[imgG]}, {0, 1}] // Abs // Max
2.220446049*10^-16
So, conclusion: there are no {c, b, γ} parameters to be estimated
because ImageAdjust
, called without additional parameters, doesn't use
them.
With only one argument, ImageAdjust[img]
performs histogram stretching, ie. pixel values, which run from min
to max
in img
, are rescaled so they run from 0 to 1 in the ouput image.
The setting {contrast, brightness, gamma} = {0, 0, 1}
does not change anything:
ImageAdjust[img, {0, 0, 1}] === img
gives True
.