如何用OpenCV获取直方图峰值后最左侧的最低bin编号?
解决直方图峰值区域最左侧bin的获取问题
看起来你遇到了两个核心问题:一是minMaxLoc返回了错误的峰值位置(0,0),二是需要找到峰值区域最左侧的bin编号。我来一步步帮你解决:
为什么你的minMaxLoc返回(0,0)?
最可能的原因有两个:
- 变量混淆:你代码里用的是
g_hist,但你描述的目标直方图是l_hist,如果g_hist是一个全零矩阵,自然会返回(0,0)的位置。先确认你用对了目标直方图变量。 - Mat维度处理错误:OpenCV的
calcHist返回的直方图通常是二维Mat(比如Size(1, 165)或者Size(165, 1)),minMaxLoc返回的Point是**(y坐标, x坐标)**,也就是行在前、列在后。如果你的直方图是165行1列的结构,那峰值的bin索引应该取max_loc.y,而不是max_loc.x(x始终为0),这会导致你误以为返回了第一个全零bin。
获取峰值区域最左侧bin的解决方案
假设你已经修正了变量和维度的问题,我们可以通过以下步骤实现需求:
- 正确找到峰值的bin索引
- 从峰值位置向左遍历,找到连续非零区域的最左侧边界
完整代码示例
// 确保使用你的目标直方图变量(这里用l_hist) cv::Mat hist = l_hist; double min_val, max_val; cv::Point min_loc, max_loc; // 找到直方图的最大值和对应位置 cv::minMaxLoc(hist, &min_val, &max_val, &min_loc, &max_loc); // 根据直方图的维度,获取峰值的bin编号 int peak_bin; if (hist.rows == 1) { // 直方图是1行165列,bin索引对应x坐标 peak_bin = max_loc.x; } else { // 直方图是165行1列,bin索引对应y坐标 peak_bin = max_loc.y; } // 向左遍历,找到峰值区域最左侧的bin int leftmost_bin = peak_bin; while (leftmost_bin > 0) { double current_val; // 根据维度读取当前左侧bin的值(注意:calcHist返回的是float类型的Mat) if (hist.rows == 1) { current_val = hist.at<float>(0, leftmost_bin - 1); } else { current_val = hist.at<float>(leftmost_bin - 1, 0); } // 遇到0就停止,此时leftmost_bin就是最左侧的非零bin if (current_val == 0.0) { break; } leftmost_bin--; } // 输出结果 cout << "峰值大小: " << max_val << endl; cout << "峰值所在bin编号: " << peak_bin << endl; cout << "峰值区域最左侧bin编号: " << leftmost_bin << endl; cout << "该bin的值: " << (hist.rows == 1 ? hist.at<float>(0, leftmost_bin) : hist.at<float>(leftmost_bin, 0)) << endl;
关键注意事项
- Mat类型:
calcHist默认返回CV_32F(float类型)的Mat,一定要用at<float>来访问元素,否则会读取错误的内存值。 - 边界处理:如果峰值左侧的所有bin都是非零的,循环会停在
leftmost_bin = 0,这符合逻辑(最左侧的bin就是第一个)。
内容的提问来源于stack exchange,提问作者ZMS
相关产品推荐
相关产品推荐

