【发布时间】:2014-05-03 15:54:43
【问题描述】:
我在 OpenCV 中有一个简单的练习,但似乎无法让它发挥作用。我正在尝试确定图像部分中的边缘密度。这是我遵循的过程: 1.从图像中拉取子图像 2.使用Canny在subImage中找边 3. 创建二值图像的阈值 4.为二值图像创建直方图 5. 获取二进制图像中“开启”的像素数(255) 6.计算“边缘密度”为numPixelsOn/totalPixels
我检查了上面 1,2,3 的结果,结果看起来还可以。第 4 步和第 5 步似乎给我带来了麻烦。
这是我计算直方图的代码:
int histSize = 256; // bin size
float range[] = { 0, 256} ;
const float* histRange = { range };
bool uniform = true;
bool accumulate = false;
Mat hist;
/// Compute the histograms:
calcHist( &gray, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate );
这似乎不起作用。当我在调用 calcHist 后检查 hist 时,它没有数据(即 data == 0)......或者我不明白我在看什么。
现在,为了访问直方图中的“bin”,我尝试了很多方法。首先我尝试了这个:
uchar* p;
p = hist.ptr<uchar>(0);
double edgePixels = p[255];
我也试过用:
cvQueryHistValue_1D(hist,255); // #include <opencv2/legacy/compat.hpp>
这不会编译。给出了 2 个错误:'cv::Mat' 没有重载成员 'operator ->',并且 'bins': is not a member of 'cv::Mat'
我想我需要一些帮助。
【问题讨论】:
-
为什么需要直方图?仅遍历渐变图像或仅使用 sum(I)/255 来获取打开的像素数不是更容易吗?最后,使用 Canny 不是一个好主意,因为它是高度非线性的,因此可重复性很差。最好使用简单的 Sobel 求和 sqrt(hor_grad^2+ver_grad^2) 来获得更好的边缘度量。
-
@Vlad - 感谢您的建议。尽管我很高兴获得有关直方图的帮助,但您的 cmets 是有道理的。我不完全理解您关于如何使用 Sobel 来更好地衡量“边缘”的评论。您是否建议我只使用 cv::Sobel 函数而不是 cv::Canny?再次感谢!
-
我建议您使用绝对值(平方和的总和或 sqrt)作为绝对梯度的估计值。它比 Canny 更快、更稳定。后者执行大量非线性操作,因此如果您需要这些属性,则不是非常可重复且不适合匹配。另一方面,它甚至对弱连续边缘也很敏感。