Я пишу некоторый код в openCV и хочу найти медианное значение очень большого матричного массива (одноканальное серое, float).
Я попробовал несколько методов, таких как сортировка массива (с использованием std:: sort) и выбор средней записи, но он очень медленный, если сравнивать с медианной функцией в Matlab. Если быть точным - то, что занимает 0,25 секунды в Matlab, занимает более 19 секунд в openCV.
Мое исходное изображение изначально представляет собой 12-битное изображение в оттенках серого с размерами 3840x2748 (~ 10,5 мегапикселей), преобразованное в float (CV_32FC1), где теперь все значения отображаются в диапазон [0,1] и в какой-то момент код я запрашиваю медианное значение, вызывая:
double myMedianValue = medianMat(Input);
Если функция medianMat:
double medianMat(cv::Mat Input){
Input = Input.reshape(0,1); // spread Input Mat to single row
std::vector<double> vecFromMat;
Input.copyTo(vecFromMat); // Copy Input Mat to vector vecFromMat
std::sort( vecFromMat.begin(), vecFromMat.end() ); // sort vecFromMat
if (vecFromMat.size()%2==0) {return (vecFromMat[vecFromMat.size()/2-1]+vecFromMat[vecFromMat.size()/2])/2;} // in case of even-numbered matrix
return vecFromMat[(vecFromMat.size()-1)/2]; // odd-number of elements in matrix
}
Я приурочил функцию medinaMat сам по себе, а также различные части - как и ожидалось, узкое место:
std::sort( vecFromMat.begin(), vecFromMat.end() ); // sort vecFromMat
Есть ли у кого-нибудь эффективное решение?
Спасибо!
ИЗМЕНИТЬ Я попытался использовать std:: nth_element, указанный в ответе Ади Шавита.
Функция medianMat теперь читается как:
double medianMat(cv::Mat Input){
Input = Input.reshape(0,1); // spread Input Mat to single row
std::vector<double> vecFromMat;
Input.copyTo(vecFromMat); // Copy Input Mat to vector vecFromMat
std::nth_element(vecFromMat.begin(), vecFromMat.begin() + vecFromMat.size() / 2, vecFromMat.end());
return vecFromMat[vecFromMat.size() / 2];}
Время работы снизилось с 19 секунд до 3,5 секунд. Это все еще не так близко к 0,25 секунды в Matlab, используя медианную функцию...