如何用目标c绘制图像的rgb颜色直方图 [英] how to plot rgb color histogram of image with objective c

查看:229
本文介绍了如何用目标c绘制图像的rgb颜色直方图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在cocoa应用程序中显示图像RGB颜色直方图。请建议使用目标c或任何可用于实现此目的的第三方库来实现此目的。

解决方案

这是一个问题因为 RGB 颜色是 3D 空间所以它们的直方图会导致 4D 图,这是我们无法理解的。



因此,解决方案是将 4D 绘图以某种方式转换为 3D 绘图。这可以通过用具有某种含义的东西对颜色进行排序来完成。我不会推测和描述我正在使用的东西。我使用 HSV 颜色空间并忽略 V 值。这样我就失去了很多色调信息,但它仍然足以为我的目的描述颜色。这就是它的样子:





您还可以使用不同 V 的更多图表来覆盖更多颜色。欲了解更多信息,请参阅:






  • 因此,如果你 R,G,B < 0 ,1> 您将其转换为< -1,+ 1> 然后计算球面坐标(忽略半径)并得到2个变量而不是3,你可以用作情节( 2D 地球基地或 3D 球体......)。



    <强>这里C ++代码如何做到这一点(由HSV直方图制作):

     图片PIC0,PIC1,PIC2,捷思; 

    const int na = 360,nb = 180,nb2 = nb>> 1; //直方图表的大小
    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; //将输入图像pic0复制到pic2
    (a = 0; a< na; a ++)//清晰直方图
    for(b = 0; b< nb; b ++)
    他的[ A] [b] = 0;
    for(y = 0; y< pic2.ys; y ++)//为它计算
    (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); //转换RGB - >球形a,b角度
    if(!l){a = 0; B = 0; }
    else {
    a = double(double(na)* acos(double(b)/ double(l))/(2.0 * M_PI));
    if(!r)b = 0;否则b = double(double(nb)* atan(double(g)/ double(r))/(M_PI)); B + = NB2;
    而(a <0)a + = na;而(a> = na)a- = na;
    if(b <0)b = 0; if(b> = nb)b = nb-1;
    }
    他的[a] [b] ++; //更新颜色使用次数...
    }
    for(n = 0,a = 0; a< na; a ++)//最大概率
    for(b = 0; b< nb; b ++)
    if(n< his [a] [b])n = his [a] [b];

    //绘制彩色RGB球体和直方图
    zed = pic1; zed .clear(9999); //用于3D的zed缓冲区
    pic1.clear(0); //直方图的图像
    da = 2.0 * M_PI / double(na);
    db = M_PI / double(nb); (ba = -M_PI,b = 0; b //正常
    dx = cos(bb)* cos(aa);
    dy = cos(bb)* sin(aa);
    dz = sin(bb);
    //表面颜色(深色)
    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;
    //柱状图中心
    x = pic1.xs>> 1;
    y = pic1.ys>> 1;
    //表面位置
    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; }
    //如果零颜色计数则忽略行
    if(!his [a] [b])继续;
    //线条颜色(明亮)
    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;
    //行长
    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;如果(x> = xs)中断;
    if(y <0)break; if(y> = ys)中断;
    }
    }




    • 输入图片是 pic0 ,输出图像 pic1 (直方图)

    • pic2 pic0 的副本(旧代码的残余)

    • zed 是用于3D显示的Zed缓冲区,避免Z排序......



    我使用自己的图片类对于图像,所以一些成员是:




    xs,ys 图像大小(以像素为单位)

    p [y] [x] .dd 是(x,y)位置的像素为32位整数类型

    清除(颜色) - 清除整个图像

    调整大小(xs,ys) - 将图像大小调整为新分辨率



    由于球体是一个3D物体,你应该为它添加旋转,以便所有表面都能及时显示(或用鼠标或其他任何东西旋转)......


    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.

    解决方案

    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:

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

    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<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;
            }
        }
    

    • 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) ...

    这篇关于如何用目标c绘制图像的rgb颜色直方图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆