how to plot rgb color histogram of image with objective c

前端 未结 1 770
萌比男神i
萌比男神i 2020-12-22 10:03

i want to show image RGB colour histogram in cocoa application. Please suggest possible way to do it with objective c or any third party library available to achieve this.

1条回答
  •  隐瞒了意图╮
    2020-12-22 10:43

    well this is a problem as RGB colors are 3D space so their histogram would lead to 4D plot which is something we do not really comprehend.

    So the solution to this is to convert the 4D plot to 3D plot somehow. This can be done by sorting the colors by something that has some meaning. I will not speculate and describe what I am using. I use HSV color space and ignore the V value. This way I lose a lot of color shade info but it is still enough to describe colors for my purposes. This is how it looks like:

    HSV histogram

    You can also use more plots with different V to cover more colors. For more info see:

    • HSV histogram

    Anyway you can use any gradient sorting or any shape of your plot that is completely on you.

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

    So if you R,G,B are in <0,1> you convert that to <-1,+1> then compute the spherical coordinates (ignoring radius) and you got your 2 variables instead of 3 which you can use as a plot (either as 2D globe base or 3D sphere ...).

    Here C++ code how to do this (made 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 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>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;
            }
        }
    
    • input image is pic0, output image is pic1 (histogram graph)
    • pic2 is copy of pic0 (remnant of old code)
    • zed is the Zed buffer for 3D display avoiding Z sorting ...

    I use my own picture class for images so some members are:


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

    As the sphere is a 3D object you should add rotation to it so all the surface is visible in time (or rotate with mouse or whatever) ...

    0 讨论(0)
提交回复
热议问题