为了账号安全,请及时绑定邮箱和手机立即绑定

opencv绘制2d直方图

/ 猿问

opencv绘制2d直方图

opencv绘制2d直方图

我想知道如何在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它给我50x50。我理解这只是意味着数组的第一个维度是250的大小?

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

我目前的功能如下。

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


查看完整描述

3 回答

?
慕盖茨4494581

你的意思是这样的吗?

  • 它是HSV直方图显示为3D图

  • V 被忽略得到3D(否则它将是4D图...)

如果是,那么这是怎么做的(我不使用OpenCV,所以根据您的需要调整它):

  1. 将源图像转换为HSV

  2. 计算直方图忽略V值

    • 无论V是什么,所有具有相同H,S的颜色都被认为是单色

    • 你可以忽略任何其他,但V参数看起来是最好的选择

  3. 绘制图表

    • 首先绘制颜色较深的椭圆(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 pic2pic2.rgb2hsv();                 // convert to HSVfor (x=0;x<65536;x++) his[x]=0; // clear histogramfor (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 histogramzed =pic1; zed .clear(999); // zed buffer for 3D
           pic1.clear(0);   // image of histogramfor (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
  • 输入图像是pic0(rose),输出图像是pic1(histogram graph)

  • pic2pic0转换为HSV以进行直方图计算

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

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

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

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

  • clear(color) - 清除整个图像

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

  • rgb2hsv()hsv2rgb()...猜猜它做了什么:)

[edit1]您的2D直方图

看起来您已将颜色编码为2D数组。一轴是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对直方图2D阵列中的每个单元都有。其中概率是单元格值。现在,如果你想绘制图像,你需要知道如何输出它(作为2D图形,3D,映射,......)。对于未分类的2D图形绘制图形,其中:

  • x=i+maj*i

  • y=HSV[i][j]

  • color=(H,S,V=200);

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

[edit2]更新代码和一些图像

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

其中一个轴/索引是H,其他的SValue被固定(I选择200)。如果您的轴被交换,那么y=x我认为只是镜像它...

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

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

这是递增的方式。可以计算xH,S代替,以实现不同的排序或交换forsx++必须在内部循环)


查看完整回答
反对 回复 2019-08-28
?
暮色呼如

我使用Luv的倒置2d直方图来抑制背景并增强前景(或者至少也尝试过......)。这是一篇简短的论文,但输出图像可能会清楚我想要做的事情。我还需要在opencv中实现或找到一个可以计算Mat内的欧几里德距离的函数。 breckon.eu/toby/publications/papers/sokalski10uavsalient.pdf

查看完整回答
反对 回复 2019-08-28
?
森栏

你不能通过那个函数对数组进行排序(除非你里面还有颜色信息)在这种情况下的排序只是一个排序的方式/顺序如何从2D数组中挑选单元并呈现它们......不,我不是在CV领域活跃(我做了一些商业项目,但我不是该领域的专家)你链接的输出图像不是直方图...直方图没有对源图像的视觉参考你的看起来像过滤/变换图像而不是直方图

查看完整回答
反对 回复 2019-08-28
  • 3 回答
  • 0 关注
  • 111 浏览
我要回答

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信