【发布时间】:2015-05-29 18:16:24
【问题描述】:
我想知道如何在 opencv c++ 中绘制 HSV Mat 的二维直方图。我当前试图显示它的代码惨遭失败。我环顾四周,了解如何绘制直方图,我发现的所有方法都是将它们绘制为独立的一维直方图。
这是我当前的输出,色调箱数为 30,饱和度箱数为 32:
这是另一个输出,色调箱数为 7,饱和度箱数为 5:
我希望它看起来更像这里的结果
我也注意到每当我做 cout
另外,如何从最高到最低(反之亦然)值频率对直方图进行排序?这是我试图解决的另一个问题。
我目前的功能如下。
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);
}
【问题讨论】:
-
什么是二维直方图?直方图是图像(或具有任何维度的任何数据集)中每种颜色(或任何其他参数)的概率(或像素数),因此绘图是二维图 x 轴是颜色(值、代码、索引...)和 y轴是概率。所以你的意思是二维直方图,或者你想为每个图像片段(如网格)制作直方图?并以某种方式像 3D 图一样绘制直方图? .... 顺便提一句。直方图输出通常是一维数组而不是图像...
-
您也不能按频率对颜色进行排序,因为颜色不是光频率(某些频率的光有颜色但向后不起作用),因此您可以按色调排序。如果您标准化颜色强度(值 = 1),那么您可以绘制直方图的 3D 图基 xy 平面是 HSV 色环,Z 是该颜色的概率......如果没有标准化,您将需要 4D 图......对于这样地块类型
-
这确实是一个二维直方图,我应该清楚这一点。我的错!另外,我将如何按色调排序?我也可以按饱和度排序以跟随每种色调吗?
-
您可以对直方图进行排序、映射、包装您喜欢的方式,例如查看我的答案...所以这实际上取决于您要输出的内容和维度...。跨度>
-
我真的很想对它进行排序,以便对直方图中最高的色调和饱和度进行排序并相互跟随。我在 opencv 中尝试了 sort() 函数并尝试了 sort(hist, hist, by rows) 和 sort(hist, hist, by columns) 但不幸的是它似乎没有那么简单。
标签: opencv image-processing histogram