Попытка сделать обратное проецирование гистограммы на трехканальном изображении приводит к следующей ошибке:
Ошибка OpenCV: утверждение не выполнено (j < nimages) в histPrepareImages, файл ../modules/imgproc/src/histogram.cpp, строка 148
Код, который не работает:
cv::Mat _refImage; //contains reference image of type CV_8UC3
cv::Mat output; //contains image data of type CV_8UC3
int histSize[] = {16, 16, 16};
int channels[] = {0, 1, 2};
const float hRange[] = {0.f, 256.f};
const float* ranges[] = {hRange, hRange, hRange};
int nChannels = 3;
cv::Mat hist;
cv::calcHist(&_refImage, 1, channels, cv::noArray(), hist, nChannels, histSize, ranges);
cv::calcBackProject(&output, 1, channels, hist, output, ranges); //This line causes assertion failure
Запуск почти идентичного кода на одноканальном изображении работает. Согласно документации, многоканальные изображения также поддерживаются. Почему этот код не работает?
Краткий ответ: cv::calcBackProject()
не поддерживает работу на месте, хотя это не упоминается в документации.
Копание в источник OpenCV приводит к следующему фрагменту:
void calcBackProject( const Mat* images, int nimages, const int* channels,
InputArray _hist, OutputArray _backProject,
const float** ranges, double scale, bool uniform )
{
//Some code...
_backProject.create( images[0].size(), images[0].depth() );
Mat backProject = _backProject.getMat();
assert(backProject.type() == CV_8UC1);
histPrepareImages( images, nimages, channels, backProject, dims, hist.size, ranges,
uniform, ptrs, deltas, imsize, uniranges );
//More code...
}
Строка, которая вызывает проблему:
_backProject.create( images[0].size(), images[0].depth() );
который, если источник и назначение совпадают, перераспределяет данные входного изображения. images[0].depth()
оценивает CV_8U
, который численно эквивалентен спецификатору типа CV_8UC1
, Таким образом, данные создаются как одноканальное изображение.
Это проблема, потому что histPrepareImages
по-прежнему ожидает, что входное изображение имеет 3 канала, и утверждение выбрасывается.
К счастью, обходной путь прост. Выходной параметр должен отличаться от входного, например:
cv::Mat result;
cv::calcBackProject(&output, 1, channels, hist, result, ranges);
Других решений пока нет …