As a follow up to this question: Calculate mean and standard deviation from ImageHistogram

I would like to add two histograms before calculating the mean and StDev. I would like to sum the numbers, not superimpose the graphics.

Explanation: I have photographed flat samples, they have a front and back side, and so I would like to get 1 outcome/Histogram for both sides summed.

Thank you for responding!


We are now using:

hist = ImageHistogram[finalCrop, Appearance -> "Separated"];
Print[hist]; resImage = ImageResize[finalCrop, 200];


"Separated"],histB=ImageHistogram[finalcrop,Appearance->\" Separated \

If[Mod[i,2] == 0, Print[histF],Print[histB]];*)

rgbImage = Transpose@Flatten[ImageData[finalCrop], 1];


table = TableForm[Through[{Mean, StandardDeviation}[#]] & /@ rgbImage,
    TableHeadings -> {{"Red", "Blue", "Green"}, {"Mean", "StDev"}}];

And I will the first to admit that I do not completely understand this, but as you can (hopefully) see, we are using histF (front of sample) en histB (back of sample) so then I would use

histTotal = Join @@@ Transpose[{histF,histB}] 

followed by

GraphicsRow[Histogram /@ histTotal]

Correct? Am trying it now!


2 Answers 2


In his reply to your previous (linked) question, Murta adviced to use

GraphicsRow[Histogram /@ imgChannelsRGB, ImageSize -> 500]

Here histogram is being applied to each of the three elements of the list imgChannelsRGB, which are themselves a List of values for red, values for green and values for blue respectively.

Suppose you have similar data of two pictures, imgChannelsRGB1 and imgChannelsRGB2.

You can use

newImgChannelsRGB = Join @@@ Transpose[{imgChannelsRGB1,imgChannelsRGB2}] 

to get a similar List of Lists of values for the individual colors. Then you can use

GraphicsRow[Histogram /@ newImgChannelsRGB]

like before.

As a side remark, note that if the red values of one picture are concentrated around 0.8 and the red values of the other are concentrated around 0.3, and each have a standard deviation of 0.1, then taking the standard deviation of the "joined sample" may be misleading (of course).

Another note: I am sure Mr. Wizard can write Join @@@ Transpose[{imgChannelsRGB1,imgChannelsRGB2}] more elegantly :).

  • $\begingroup$ Ah, Thank you, again! $\endgroup$
    – onemonkey
    Commented Oct 19, 2012 at 10:01
  • $\begingroup$ Edit: still learning that Return means post and does not add white line. Trying to post code we are now using... $\endgroup$
    – onemonkey
    Commented Oct 19, 2012 at 10:01
  • 1
    $\begingroup$ Judge for yourself: Join[imgChannelsRGB1, imgChannelsRGB2, 2] :-) $\endgroup$
    – Mr.Wizard
    Commented Oct 19, 2012 at 10:16
  • $\begingroup$ Haha, I am such a fan of yours :) $\endgroup$ Commented Oct 19, 2012 at 10:21
  • 1
    $\begingroup$ Or, I believe, you could just use imgChannelsRGB1 + imgChannelsRGB2 ;-) -- With either version the data dimensions will need to be exactly the same. $\endgroup$
    – Mr.Wizard
    Commented Oct 19, 2012 at 16:40

The spirit of the question seems to involve basing all computations on the "histograms"--binned summaries of data--rather than on the raw data. Here, then, is a solution in that spirit.

Begin with the data for an image, represented as a list of {Red, Green, Blue} values, as in this example:

x = Flatten[ImageData[Import["ExampleData/lena.tif"]], 1];

The histograms with the finest resolutions actually tally the values in the bands:

{r, g, b} = Tally /@ Transpose[x];

The result of Tally lists {value, count} pairs. All subsequent calculations will be based only on these summaries. A plot of them is tantamount to a histogram:

ListPlot[{b, r, g}, Filling -> Axis, 
     FillingStyle -> Table[i -> Directive[Opacity[1/3], {Blue, Red, Green}[[i]]], {i, 1, 3}]]


To compute the statistics, we need to weight the values and their squares by the counts before averaging. This can conveniently be done with matrix operations provided we augment each {value, count} pair to include the constant $1$ and the squared value. The following implementation uses variable names to document the meanings of the calculations being performed:

stats[x_List] := 
  Block[{z = Join[x, {1, #[[1]]^2} & /@ x, 2], a, count, mean, sum, sumSquares},
   a = Transpose[z] . z;
   sum = a[[1, 2]];
   sumSquares = a[[2, 4]];
   count = a[[2, 3]];
   mean = sum/count;
   {count, mean, Sqrt[sumSquares/count - mean^2]}

The output evidently is a list of basic statistics: the number of pixels, their average, and their standard deviation. Here is a summary by band:

TableForm[stats /@ {r, g, b} // N , TableHeadings -> {{"Red","Green","Blue"}, {"Count","Mean","SD"}}]

Summary of three bands separately

For statistics of combined data, it suffices to concatenate the information in the histograms:

TableForm[{stats[Join[r, g, b]]} // N, TableHeadings -> {{}, {"Count","Mean","SD"}}]

Joint Summary


Notice that the preceding result summarizes 52,200 values--the combined count of all three bands--rather than just 17,400 pixels, which would be the result of first superimposing the bands (by per-pixel averaging, for instance) and then summarizing. Let's compare by creating a superposition of the three bands (gray) and repeating the analyses:

gray =  Tally[Mean /@ x];
ListPlot[gray, Filling -> Axis, PlotStyle -> Black, FillingStyle -> Directive[Opacity[0.5], Gray]]

Grayscale histogram

TableForm[{stats[gray]} // N, TableHeadings -> {{}, {"Count", "Mean", "SD"}}]

Grayscale summary

As one would expect--and can easily be proven--the means are identical, but the standard deviations and counts change. (The slightly smaller SD indicates a lack of perfect correlation among the bands, also to be expected, because this was not a grayscale image.)

  • $\begingroup$ very pretty plots! $\endgroup$
    – chris
    Commented Oct 19, 2012 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.