Я пишу код в openCV и хочу найти медианное значение очень большого матричного массива (одноканальный оттенки серого, поплавок).сверхбыстрая медиана матрицы в opencv (так быстро, как matlab)
Я пробовал несколько методов, таких как сортировка массива (с использованием 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 самого по себе, а также различным частям - как и ожидался узкой является in:
std::sort(vecFromMat.begin(), vecFromMat.end()); // sort vecFromMat
У кого-нибудь есть эффективное решение?
Спасибо!
EDIT Я попытался использовать 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, используя среднюю функцию ...
Попробуйте этот алгоритм: http://www.i-programmer.info/babbages-bag/ 505-быстро-median.html. Сортировка в лучшем случае * O (n log n) *, но этот сайт требует медианного алгоритма поиска, который равен * O (n) * – Dan
Мне кажется странным, что это занимает много времени, используя OpenCV. Учитываете ли вы время для чтения данных в Mat? Каков размер вашего ввода и вашего кода? – coincoin
можете ли вы разместить свой код? возможно, вы получаете доступ к элементам в неправильном порядке, что дает вам плохое кэширование. – Micka