Я хотел бы получить гистограмму изображения, используя Эмгу.
У меня есть двойное изображение в оттенках серого
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? Нужно ли самому писать функцию?
Это не проблема EmguCV / OpenCV, сама идея не имеет смысла, поскольку двойная гистограмма потребует намного больше памяти, чем доступно. То, что я говорю, верно, когда у вас есть гистограмма с фиксированным размером. Единственный способ обойти это — иметь гистограмму с динамическим распределением при обработке изображения. Но это было бы опасно для больших изображений, поскольку они могли бы выделить столько памяти, сколько само изображение.
Я предполагаю, что ваше двойное изображение содержит много одинаковых значений, иначе гистограмма была бы не очень полезна. Таким образом, один из способов обойти это — перераспределить ваши значения в короткие (16-битные) вместо байтовых (8-битные), так что ваша гистограмма будет очень похожа на ожидаемую от ваших двойных значений.
Я посмотрел в 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);