opencv绘制二维直方图

我想知道如何在opencv c ++中绘制HSV Mat的二维直方图。 我目前的代码试图显示它失败了。 我已经环顾四周如何绘制直方图,我发现的所有那些是将它们绘制为独立的1d直方图。

这是我当前的输出,色相的数量是30,饱和度是32。

这里是另一个输出,色调箱的数量是7,饱和度箱是5:

我希望看起来更像这里的结果

http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html

我也注意到,每当我做cout << Hist.size它给我50×50。 我明白,只是意味着arrays的第一个维度是250?

另外,如何将直方图从最高到最低(或反之亦然)值频率sorting? 那是我想解决的另一个问题。

我目前的function如下。

void Perform_Hist(Mat& MeanShift, Mat& Pyramid_Result, Mat& BackProj){ Mat HSV, Hist; int histSize[] = {hbins, sbins}; int channels[] = {0, 1}; float hranges[] = {0, 180}; float sranges[] = {0, 256}; const float* ranges[] = {hranges, sranges}; cvtColor(MeanShift, HSV, CV_BGR2HSV); Mat PyrGray = Pyramid_Result.clone(); calcHist(&HSV, 1, channels, Mat(), Hist, 2, histSize, ranges, true, false); normalize(Hist, Hist, 0, 255, NORM_MINMAX, -1, Mat()); invert(Hist, Hist, 1); calcBackProject(&PyrGray, 1, channels, Hist, BackProj, ranges, 1, true); double maxVal = 0; minMaxLoc(Hist, 0, &maxVal, 0, 0); int scale = 10; Mat histImage = Mat::zeros(sbins*scale, hbins*10, CV_8UC3); for(int i = 1; i < hbins * sbins; i++){ line(histImage, Point(hbins*sbins*(i-1), sbins - cvRound(Hist.at<float>(i-1))), Point(hbins*sbins*(i-1), sbins - cvRound(Hist.at<float>(i))), Scalar(255,0,0), 2, 8, 0); } imshow (HISTOGRAM, histImage); } 

你是不是这个意思?

HSV直方图为3D图形

  • 它是HSV直方图显示为3Dgraphics
  • V被忽略到3D(否则它会是4D图…)

如果是的话,这是如何做到这一点 (我不使用OpenCV,以便根据您的需要进行调整):

  1. 将源图像转换为HSV
  2. 计算直方图忽略V值
    • 所有颜色相同的H,S被认为是单一的颜色,不pipeV是什么
    • 你可以忽略其他的参数,但是V参数看起来是最好的select
  3. 绘制graphics

    • 先用较深的颜色画出椭圆(HSV基盘)
    • 然后为每个点取对应的直方图值并绘制颜色较亮的垂直线。 线条大小与直方图值成比例

这里是我用这样做的C ++代码:

 picture pic0,pic1,pic2,zed; int his[65536]; DWORD w; int h,s,v,x,y,z,i,n; double r,a; color c; // compute histogram (ignore v) pic2=pic0; // copy input image pic0 to pic2 pic2.rgb2hsv(); // convert to HSV for (x=0;x<65536;x++) his[x]=0; // clear histogram for (y=0;y<pic2.ys;y++) // compute it for (x=0;x<pic2.xs;x++) { c=pic2.p[y][x]; h=c.db[picture::_h]; s=c.db[picture::_s]; w=h+(s<<8); // form 16 bit number from 24bit HSV color his[w]++; // update color usage count ... } for (n=0,x=0;x<65536;x++) if (n<his[x]) n=his[x]; // max probability // draw the colored HSV base plane and histogram zed =pic1; zed .clear(999); // zed buffer for 3D pic1.clear(0); // image of histogram for (h=0;h<255;h++) for (s=0;s<255;s++) { c.db[picture::_h]=h; c.db[picture::_s]=s; c.db[picture::_v]=100; // HSV base darker c.db[picture::_a]=0; x=pic1.xs>>1; // HSV base disc position centers on the bottom y=pic1.ys-100; a=2.0*M_PI*double(h)/256.0; // disc -> x,y r=double(s)/256.0; x+=120.0*r*cos(a); // elipse for 3D ilusion y+= 50.0*r*sin(a); z=-y; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x--; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y--; w=h+(s<<8); // get histogram index for this color i=((pic1.ys-150)*his[w])/n; c.db[picture::_v]=255; // histogram brighter for (;(i>0)&&(y>0);i--,y--) { if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y++; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x--; if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y--; } } pic1.hsv2rgb(); // convert to RGB to see correct colors 
  • input图像是pic0 (玫瑰),输出图像是pic1 (直方图)
  • pic0pic0转换为HSV进行直方图计算
  • zed是避免Zsorting的3D显示Zed缓冲区…

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

  • xs,ys图像的像素大小
  • p[y][x].dd是(x,y)位置处的像素,为32位整数types
  • clear(color) – 清除整个图像
  • resize(xs,ys) – 将图像大小调整为新的分辨率
  • rgb2hsv()hsv2rgb() …猜它是什么:)

你的二维直方图

它看起来像你有颜色编码成二维数组。 一个轴是H ,第二个是S 所以你需要从数组地址计算H,S值。 如果它是线性的,那么对于HSV[i][j]

  • H=h0+(h1-h0)*i/maxi
  • S=s0+(s1-s0)*j/maxj
  • 或者i,j颠倒了
  • h0,h1,s0,s1是颜色范围
  • maxi,maxj是数组大小

正如你可以看到你也放弃像我这样的V所以现在你有H,S为直方图二维数组中的每个单元格。 概率是单元格的价值。 现在,如果你想绘制一个图像,你需要知道如何输出(作为一个二维graphics,三维,映射,…)。 对于未分类的二维graphics绘制graphics,其中:

  • x=i+maj*i
  • y=HSV[i][j]
  • color=(H,S,V=200);

如果你想对它进行sorting,那么只需要按不同的方式计算x轴,或者按照sorting顺序循环二维数组,并且x只是递增

更新代码和一些图片

我已经修复了上面的C ++代码(错误的Z值符号,改变了Z缓冲区条件,并为更好的输出增加了更大的点数)。 你的二维数组的颜色可以是这样的:

HS颜色

其中一个轴/索引是H ,另一个SValue是固定的(我select200)。 如果你的轴交换,然后只是通过y=x镜像我认为…

颜色sorting实际上只是您从数组中选取所有颜色的顺序。 例如:

 v=200; x=0; for (h=0;h<256;h++) for (s=0;s<256;s++,x++) { y=HSV[h][s]; // here draw line (x,0)->(x,y) by color hsv2rgb(h,s,v); } 

这是递增的方式。 你可以用H,S来计算x来实现不同的sorting或交换forsx++必须在内部循环中)

如果您想要RGB直方图绘图,请参阅:

  • 如何绘制图像的rgb颜色直方图与目标c