【问题标题】:how to plot rgb color histogram of image with objective c如何用目标c绘制图像的rgb颜色直方图
【发布时间】:2017-03-28 07:26:59
【问题描述】:

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

【问题讨论】:

  • 当我阅读您的问题时,唯一正确的答案是“是”。不幸的是,这太短了,无法输入。要求图书馆推荐是题外话。任何图像处理库都可以工作。它将为您提供开箱即用的工具或自行实施的方法。这很简单。只是谷歌。
  • 对不起,我现在修改了问题。你知道可能的方法吗?
  • 您刚刚改写了一些内容。这根本不会改善您的问题。要求图书馆是题外话。您应该使用像谷歌这样的网络搜索来查找图像处理库。我相信“图像处理可可”或“图像处理目标 c”会产生很多结果。您要么需要一个为您提供直方图功能的库,要么至少需要一个允许您读取图像并访问其像素数据的库。自己实现一切并不是很有效。但是,一旦您至少拥有像素数据,只需几分钟即可获得直方图。

标签: objective-c cocoa image-processing histogram rgb


【解决方案1】:

这是一个问题,因为 RGB 颜色是 3D 空间,因此它们的直方图会导致 4D 绘图,而这并不是我们真正想要的理解。

所以解决这个问题的方法是将 4D 图以某种方式转换为 3D 图。这可以通过按有意义的东西对颜色进行排序来完成。我不会推测和描述我正在使用什么。我使用 HSV 色彩空间并忽略 V 值。这样我会丢失很多颜色阴影信息,但仍然足以为我的目的描述颜色。看起来是这样的:

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

无论如何,您都可以使用任何梯度排序或任何完全由您自己决定的绘图形状。

如果你想要纯 RGB 那么你可以调整它并使用 RGB 立方体表面或将其映射到球体上并忽略来自(0,0,0) 的长度(使用单位向量)像这样:

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

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

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,输出图像为pic1(直方图)
  • pic2pic0 的副本(旧代码的残余)
  • zed 是用于 3D 显示的 Zed 缓冲区,避免了 Z 排序 ...

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


xs,ys 图像大小(以像素为单位)
p[y][x].dd 是 (x,y) 位置的像素,为 32 位整数类型
clear(color) - 清除整个图像
resize(xs,ys) - 将图像调整为新分辨率

由于球体是 3D 对象,您应该为其添加旋转,以便所有表面及时可见(或使用鼠标或其他方式旋转)...

【讨论】:

    猜你喜欢
    • 2020-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 2012-02-16
    • 2013-03-09
    相关资源
    最近更新 更多