c # — вычисление гистограммы с помощью Emgu OpenCV

Я хотел бы получить гистограмму изображения, используя Эмгу.

У меня есть двойное изображение в оттенках серого

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);

Беда в том, что мне трудно найти, как правильно использовать эту функцию

ошибка

Позволяет ли мне это делать через emgu / opencv? Нужно ли самому писать функцию?

0

Решение

Это не проблема EmguCV / OpenCV, сама идея не имеет смысла, поскольку двойная гистограмма потребует намного больше памяти, чем доступно. То, что я говорю, верно, когда у вас есть гистограмма с фиксированным размером. Единственный способ обойти это — иметь гистограмму с динамическим распределением при обработке изображения. Но это было бы опасно для больших изображений, поскольку они могли бы выделить столько памяти, сколько само изображение.

Я предполагаю, что ваше двойное изображение содержит много одинаковых значений, иначе гистограмма была бы не очень полезна. Таким образом, один из способов обойти это — перераспределить ваши значения в короткие (16-битные) вместо байтовых (8-битные), так что ваша гистограмма будет очень похожа на ожидаемую от ваших двойных значений.

1

Другие решения

Я посмотрел в histogram.cpp в исходном коде opencv.

Внутренняя функция

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, "");

Пока двойные изображения здесь не обрабатываются, float есть.

Хотя с плавающей запятой теряет немного точности от двойной, это не является существенной проблемой.

Следующий фрагмент кода работал хорошо для меня

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);
0

По вопросам рекламы [email protected]