13
$\begingroup$

I am using a Histogram3D plot to view the correlation of the R & G of an RGB image. Naturally, I want the bins to have a color corresponding to their $x$, $y$ (R,G) position on the chart.

Unfortunately, ColorFunction for Histogram3D only supplies one argument, height, not $x$ or $y$ position.

Is there a way to color each bin based on its $x$ and $y$ position within the histogram? (i.e. RGBColor[x,y,0])

Here is how I am generating my (uncolored) histogram:

    Histogram3D[Transpose[{
                           Flatten[ImageData[jpeg][[All,All,1]]]
                          ,Flatten[ImageData[jpeg][[All,All,2]]]
                           }]]
$\endgroup$
4
  • $\begingroup$ Yes, exactly. I also want to make two other plots: R,B: RGBColor[x,0,y] and B,Y: RGBColor[0,x,y] $\endgroup$ Sep 16, 2013 at 23:01
  • $\begingroup$ I'm not sure what that should show. For example RGBColor[1, 1, 0] is Yellow, but it doesn't mean it was Yellow in the image since you are not counting Blue. $\endgroup$
    – Kuba
    Sep 16, 2013 at 23:04
  • $\begingroup$ Yes, I am aware. I would like to display the color value without the Blue Counted. $\endgroup$ Sep 16, 2013 at 23:06
  • $\begingroup$ You may be interested in my edit. I've also made your code more compact. $\endgroup$
    – Kuba
    Sep 17, 2013 at 6:13

2 Answers 2

11
$\begingroup$

Thanks to ybeltukov I realised that post-processing way is not so bulletproof. Let's write a little bit longer solution to take control.

ChartElementFunction, is a handy way to deal with this (only a little bit adapted example for documentation):

f[{{xmin_, xmax_}, {ymin_, ymax_}, {zmin_, zmax_}}, ___] := {
         RGBColor[Mean[{xmin, xmax}], Mean[{ymin, ymax}], 0], 
         Cuboid[{xmin, ymin, zmin}, {xmax, ymax, zmax}]}

And it works for small images too:

jpeg = ImageResize[ExampleData[{"TestImage", "Mandrill"}], 5]

hist = Histogram3D[
                   Flatten[ImageData[jpeg][[;; , ;; , {1, 2}]], 1],
                   ChartElementFunction -> f]

(I have changed a little bit your code to make it more compact).

enter image description here


Edit All of the graphs you asked for. I had to modify f to make it more useful:

f[{x_, y_, z_}, ___, OptionsPattern[Irrelevant -> 1]] := {
               RGBColor @@ Insert[{Mean@x, Mean@y}, 0, OptionValue[Irrelevant]], 
               Cuboid @@ Transpose[{x, y, z}]}


jpeg = ImageResize[ExampleData[{"TestImage", "Mandrill"}], 100]

Histogram3D[Flatten[ImageData[jpeg][[;; , ;; , #]], 1], PlotLabel -> #2,
            ChartElementFunction -> (f[##, Irrelevant -> "x"] & /. "x" -> #3)
           ] & @@@ {{{1, 2}, "R - G", 3}, 
                    {{1, 3}, "R - B", 2}, 
                    {{2, 3}, "G - B", 1}} // GraphicsRow[#, ImageSize -> 1000] &

enter image description here


"Post-processing" way, works automatically only for larger images, for small, take a look @ybeltukov solution.

ChartElements are Cuboid s. r1 and r2 are coordinates of oposite vertices. Just reffer the color to them as you like. r2 = {x2, y2, z2} so you can involve height too.

To achieve what you've described in comments:

hist /. Cuboid[r1_, r2_] :> {RGBColor[##, 0] & @@ Most@(Mean /@ Transpose[{r1, r2}])
                             , Cuboid[r1, r2]}

enter image description here

$\endgroup$
5
  • $\begingroup$ @PerfectTommy does my edit fits your needs? $\endgroup$
    – Kuba
    Sep 16, 2013 at 23:10
  • 1
    $\begingroup$ If you want this to work on small images add the option PerformanceGoal -> "Speed" to Histogram3D. $\endgroup$
    – Mr.Wizard
    Sep 17, 2013 at 0:29
  • 1
    $\begingroup$ @Mr.Wizard Thank's for the remark. ChartElementFunction has this advantage that it still creates tooltips for small images :) $\endgroup$
    – Kuba
    Sep 17, 2013 at 6:59
  • $\begingroup$ @Kuba I ended up using the "post-processing" method and it worked wonderfully. Thanks! $\endgroup$ Sep 20, 2013 at 19:17
  • $\begingroup$ @PerfectTommy I'm glad it helps :) good luck! $\endgroup$
    – Kuba
    Sep 20, 2013 at 19:19
8
$\begingroup$

Solution of Kuba works fine only for large images when bars on Histogram3D are not dynamic objects with tooltips. I provide more general solution

hist /. (h_ /; h === CuboidBox || h === Cuboid)[r1_, r2_] :> 
With[{col = Append[Most[r1 + r2]/2, 0]}, {RGBColor[col], h[r1, r2]} /; True])

For small data set there is CuboidBox instead of Cuboid. Moreover CuboidBox is in held expression so I use Trott-Strzebonski in-place evaluation technique.

Examples

  1. Small image

    jpeg = Image[RandomReal[1, {8, 12, 3}]]
    hist = Histogram3D[
       Transpose[{Flatten[ImageData[jpeg][[All, All, 1]]], 
         Flatten[ImageData[jpeg][[All, All, 2]]]}]];
    hist /. (h_ /; h === CuboidBox || h === Cuboid)[r1_, r2_] :> 
      With[{col = Append[Most[r1 + r2]/2, 0]}, {RGBColor[col], 
         h[r1, r2]} /; True]
    

    enter image description here

  2. Large image

    jpeg = Import["ExampleData/lena.tif"]
    hist = Histogram3D[
       Transpose[{Flatten[ImageData[jpeg][[All, All, 1]]], 
         Flatten[ImageData[jpeg][[All, All, 2]]]}]];
    hist /. (h_ /; h === CuboidBox || h === Cuboid)[r1_, r2_] :> 
      With[{col = Append[Most[r1 + r2]/2, 0]}, {RGBColor[col], 
         h[r1, r2]} /; True]
    

    enter image description here

$\endgroup$
6
  • $\begingroup$ One can add the option PerformanceGoal -> "Speed" to Histogram3D to get the "large image" behavior on small data as well. $\endgroup$
    – Mr.Wizard
    Sep 17, 2013 at 0:30
  • $\begingroup$ @Mr.Wizard Thanks! I searched this option to no avail. $\endgroup$
    – ybeltukov
    Sep 17, 2013 at 0:32
  • 4
    $\begingroup$ Without help from others (this site) or an almost pathological inclination for experimentation I don't know how one is to learn of such things. I'm glad I could pass this information along. $\endgroup$
    – Mr.Wizard
    Sep 17, 2013 at 0:50
  • $\begingroup$ @ybeltukov Good catch. I must admint I have not thought about this. Could you pleaste tell me why haven't you started to participate earlier in answering on this site? Looking on your answers I feel like we 'lost' a lot :) $\endgroup$
    – Kuba
    Sep 17, 2013 at 5:08
  • $\begingroup$ p.s. Ok, I edited my post so it works with small images too :) $\endgroup$
    – Kuba
    Sep 17, 2013 at 6:14

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.