从OpenCV直方图中获取值
我在OpenCV中有一个简单的练习,但似乎无法让它工作。我试图确定图像某一部分边缘的密度。这是我遵循的过程: 1.从图像中提取子图像 2.使用Canny在子图像中查找边 3.创建二值图像的阈值 4.为二值图像创建直方图 5.获取二进制图像中“打开”的像素数(255) 6.将“边缘密度”计算为numPixelsOn/totalPixels 我已经检查了上面1、2和3的结果,结果似乎还可以。第4步和第5步似乎给我带来了麻烦 以下是我计算直方图的代码:从OpenCV直方图中获取值,opencv,histogram,Opencv,Histogram,我在OpenCV中有一个简单的练习,但似乎无法让它工作。我试图确定图像某一部分边缘的密度。这是我遵循的过程: 1.从图像中提取子图像 2.使用Canny在子图像中查找边 3.创建二值图像的阈值 4.为二值图像创建直方图 5.获取二进制图像中“打开”的像素数(255) 6.将“边缘密度”计算为numPixelsOn/totalPixels 我已经检查了上面1、2和3的结果,结果似乎还可以。第4步和第5步似乎给我带来了麻烦 以下是我计算直方图的代码: int histSize = 256
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时,它没有数据(即数据==0)。。。也许我不明白我在看什么
现在,为了访问直方图中的“垃圾箱”,我尝试了很多方法。首先,我尝试了这个:
uchar* p;
p = hist.ptr<uchar>(0);
double edgePixels = p[255];
uchar*p;
p=hist.ptr(0);
双边缘像素=p[255];
我还尝试使用:
cvQueryHistValue_1D(hist,255); // #include <opencv2/legacy/compat.hpp>
cvQueryHistValue_1D(hist,255);//#包括
这不会编译。给出了2个错误:“cv::Mat”没有重载成员“operator->”,而“bins”:不是“cv::Mat”的成员
我想我需要一些帮助。您的第三个参数通道中有一个错误,它应该是一个数组,所以您应该这样调用它
int histSize = 256; // bin size
float range[] = { 0, 256} ;
const float* histRange = { range };
bool uniform = true;
bool accumulate = false;
Mat hist;
int channels[] = {0};
/// Compute the histograms:
calcHist( &gray, 1, channels, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate );
你亦应致电:
hist.at<float>(0);
hist.at(0);
为了获得您的值,OpenCV将它们存储为浮点值,这就是使用uchar时得到0的原因,因为uchar小于浮点值,并且数字存储得足够小,无法填充第一个比特。谢谢!!检查得很好。为什么需要柱状图?仅仅遍历渐变图像或者仅仅使用sum(I)/255获得打开的像素数不是更容易吗?最后,使用Canny不是一个好主意,因为它是高度非线性的,因此可重复性差。最好使用一个简单的Sobel求和sqrt(hor_grad^2+ver_grad ^2)来更好地衡量尖锐程度。@Vlad-谢谢你的建议。虽然我很感激得到直方图方面的帮助,但你的评论是有道理的。我不完全理解你关于如何使用Sobel来更好地衡量“急躁”的评论。您是否建议我只使用cv::Sobel函数而不是cv::Canny?再次感谢!我建议您使用绝对值(平方和的和或sqrt)作为绝对梯度的估计值。它比Canny更快、更稳定。后者执行大量的非线性操作,因此不具有很强的可重复性,如果需要这些属性,则不适合进行匹配。另一方面,它甚至对弱边也很敏感。