How to build a graphical histogram of an rgb image with a c lens

I want to show a graphical histogram of RGB color in a cocoa application. Please suggest a possible way to do this with an objective c or any third-party library available for this.

0
source share
1 answer

Well, this is a problem, because RGB colors are 3D , so their histogram will lead to a 4D chart, which we really do not comprehend.

So, the solution to this is to convert the 4D chart to 3D . This can be done by sorting the colors using something that has some meaning. I will not ponder and describe what I use. I use HSV color space and ignore the value of V. Thus, I lose a lot of information about the color scheme, but this is enough to describe the colors for my purposes. Here's what it looks like:

HSV histogram

You can also use more graphics with different V to cover more colors. For more information see:

In any case, you can use any gradient sort or any figure of your plot that is completely on you.

If you want pure RGB , then you can adapt this and use the cube of the RGB surface or display it on a sphere and ignore the length from (0,0,0) (use unit vectors) something like this:

RGB histogram

So, if you are R,G,B at <0,1> , you will convert this value to <-1,+1> , then calculate the spherical coordinates (ignoring the radius), and instead of 2 3 you get variables that you can use as a graph (either as a <strong> 2D earth base or 3D sphere ...).

Here's the C ++ code on how to do this (from the HSV histogram):

 picture pic0,pic1,pic2,zed; const int na=360,nb=180,nb2=nb>>1; // size of histogram table int his[na][nb]; DWORD w; int a,b,r,g,x,y,z,l,i,n; double aa,bb,da,db,dx,dy,dz,rr; color c; pic2=pic0; // copy input image pic0 to pic2 for (a=0;a<na;a++) // clear histogram for (b=0;b<nb;b++) his[a][b]=0; for (y=0;y<pic2.ys;y++) // compute it for (x=0;x<pic2.xs;x++) { c=pic2.p[y][x]; r=c.db[picture::_r]-128; g=c.db[picture::_g]-128; b=c.db[picture::_b]-128; l=sqrt(r*r+g*g+b*b); // convert RGB -> spherical a,b angles if (!l) { a=0; b=0; } else{ a=double(double(na)*acos(double(b)/double(l))/(2.0*M_PI)); if (!r) b=0; else b=double(double(nb)*atan(double(g)/double(r))/(M_PI)); b+=nb2; while (a<0) a+=na; while (a>=na) a-=na; if (b<0) b=0; if (b>=nb) b=nb-1; } his[a][b]++; // update color usage count ... } for (n=0,a=0;a<na;a++) // max probability for (b=0;b<nb;b++) if (n<his[a][b]) n=his[a][b]; // draw the colored RGB sphere and histogram zed =pic1; zed .clear(9999); // zed buffer for 3D pic1.clear(0); // image of histogram da=2.0*M_PI/double(na); db=M_PI/double(nb); for (aa=0.0,a=0;a<na;a++,aa+=da) for (bb=-M_PI,b=0;b<nb;b++,bb+=db) { // normal dx=cos(bb)*cos(aa); dy=cos(bb)*sin(aa); dz=sin(bb); // color of surface (darker) rr=75.0; c.db[picture::_r]=double(rr*dx)+128; c.db[picture::_g]=double(rr*dy)+128; c.db[picture::_b]=double(rr*dz)+128; c.db[picture::_a]=0; // histogram center x=pic1.xs>>1; y=pic1.ys>>1; // surface position rr=64.0; z=rr; x+=double(rr*dx); y+=double(rr*dy); z+=double(rr*dz); if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } // ignore lines if zero color count if (!his[a][b]) continue; // color of lines (bright) rr=125.0; c.db[picture::_r]=double(rr*dx)+128; c.db[picture::_g]=double(rr*dy)+128; c.db[picture::_b]=double(rr*dz)+128; c.db[picture::_a]=0; // line length l=(xs*his[a][b])/(n*3); for (double xx=x,yy=y,zz=z;l>=0;l--) { if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } xx+=dx; yy+=dy; zz+=dz; x=xx; y=yy; z=zz; if (x<0) break; if (x>=xs) break; if (y<0) break; if (y>=ys) break; } } 
  • pic0 input image, pic1 output image (bar graph)
  • pic2 is a copy of pic0 (the rest of the old code)
  • zed is the Zed buffer for the 3D display, eliminating the sorting of Z ...

I use my own image class for images, so some members:


xs,ys image size in pixels
p[y][x].dd - pixel at position (x, y) as a 32-bit integer type
clear(color) - clears the entire image
resize(xs,ys) - resize the image in a new resolution

Since the sphere is a three-dimensional object, you must add a rotation to it so that the entire surface is visible in time (or rotates with the mouse or something else) ...

+1
source

Source: https://habr.com/ru/post/1234968/


All Articles