使用Emgu OpenCV进行直方图计算

时间:2014-10-16 06:59:51

标签: c# c++ opencv emgucv

我想使用Emgu获取图像的直方图。

我有一个灰度双重图像

Image<Gray, double> Crop;

我可以使用

获得直方图
Image<Gray, byte> CropByte = Crop.Convert<Gray, byte>(); 
DenseHistogram hist = new DenseHistogram(BinCount, new RangeF(0.0f, 255.0f));
hist.Calculate<Byte>(new Image<Gray, byte>[] { CropByte }, true, null);

问题是,这样做我需要转换为字节图像。这是有问题的,因为它会扭曲我的结果。如果可以使用双重图像,这会给我一个稍微不同的直方图。

我尝试使用CvInvoke来使用内部opencv函数来计算直方图。

IntPtr[] x = { Crop }; 

DenseHistogram cropHist = new DenseHistogram  
( 
    BinCount,  
    new RangeF 
    (
        MinCrop,
        MaxCrop
    ) 
); 

CvInvoke.cvCalcArrHist(x, cropHist, false, IntPtr.Zero); 

麻烦在于我发现很难找到如何正确使用此功能

Error

emgu / opencv允许我这样做吗?我需要自己编写这个功能吗?

2 个答案:

答案 0 :(得分:1)

这不是一个EmguCV / OpenCV问题,这个想法本身没有意义,因为双直方图需要比可用内存更多的内存。当您使用固定大小分配直方图时,我说的是真的。解决这个问题的唯一方法是在处理图像时使用动态分配的直方图。但是这对于大图像来说会很危险,因为它可以分配与图像本身一样多的内存。

我猜你的双重图像包含许多相同的值,否则直方图不会非常有用。因此,解决这个问题的一种方法是将值重新映射为短(16位)而不是字节(8位),这样您的直方图将与您对双精度值的预期非常相似。

答案 1 :(得分:0)

我在opencv源代码中查看了histogram.cpp。

内幕功能

void cv::calcHist( const Mat* images, int nimages, const int* channels,
                   InputArray _mask, OutputArray _hist, int dims, const int* histSize,
                   const float** ranges, bool uniform, bool accumulate )

有一个处理不同图像类型的部分

if( depth == CV_8U )
        calcHist_8u(ptrs, deltas, imsize, ihist, dims, ranges, _uniranges, uniform );
    else if( depth == CV_16U )
        calcHist_<ushort>(ptrs, deltas, imsize, ihist, dims, ranges, _uniranges, uniform );
    else if( depth == CV_32F )
        calcHist_<float>(ptrs, deltas, imsize, ihist, dims, ranges, _uniranges, uniform );
    else
        CV_Error(CV_StsUnsupportedFormat, "");

虽然这里没有处理双重图像,但浮动是。

虽然浮点数从双精度中略微精确,但这不是一个重要的问题。

以下代码段对我来说效果很好

Image<Gray, float> CropByte = Crop.Convert<Gray, float>(); 
DenseHistogram hist = new DenseHistogram(BinCount, new RangeF(0.0f, 255.0f));
hist.Calculate<float>(new Image<Gray, float>[] { CropByte }, true, null);