Какое наиболее эффективное матричное представление в C++?

Я надеюсь, что этот вопрос не ОТ.

Я реализую кодировщик VLAD, используя реализация VLFeat и SIFT дескрипторы из разных реализаций для их сравнения (OpenCV, VLFeat, OpenSIFT< /а>).

Это должно быть высокопроизводительное приложение на C++ (я знаю, что SIFT очень неэффективен, я реализую его параллельную версию).

Теперь VLAD хочет получить в качестве входных данных указатель на набор смежных дескрипторов (математических векторов). Дело в том, что обычно эти SIFT-дескрипторы представляются в виде матрицы, поэтому ими проще управлять.

Итак, предположим, что у нас есть матрица из 3 дескрипторов в 3 измерениях (я использую эти числа для простоты, на самом деле это тысячи дескрипторов в 128 измерениях):

1 2 3
4 5 6
7 8 9

Мне нужно сделать фид vl_vlad_encode с указателем на:

1 2 3 4 5 6 7 8 9

Простое решение — сохранить дескрипторы в объекте cv::Mat m, а затем передать m.data в vl_vlad_encode.

Однако я не знаю, является ли cv::Mat эффективным матричным представлением. Например, альтернативой является Eigen::Matrix (я думаю, что легко получить представленное выше представление, используя это объект), но я не знаю, какая реализация быстрее/эффективнее или есть какая-то другая причина, потому что я должен предпочесть одну вместо другой.

Другой возможной альтернативой является использование std::vector<std::vector<float>> v, но я не знаю, получу ли я с помощью v.data() приведенное выше представление вместо: 1 2 3 *something* 4 5 6 *something* 7 8 9

Очевидно, что *something* испортит vl_vlad_encode.

Любое другое предложение более чем приветствуется!


person justHelloWorld    schedule 14.12.2016    source источник
comment
float [9]? Согласитесь с соглашением о столбцах или строках, и тогда вы сможете расположить все последовательно, один столбец или одну строку за другой.   -  person Andon M. Coleman    schedule 14.12.2016
comment
@AndonM.Coleman не хочешь объяснить разницу между float[9] и float[3][3]? Они оба являются смежными, и соглашение о столбцах и строках может быть изменено для обоих.   -  person UKMonkey    schedule 14.12.2016
comment
Я забыл сказать, что размер матрицы определяется во время выполнения, поэтому использование std::vector<float> v, а затем v.resize(dim) (или v.reserve(dim)) может быть лучшим решением, где dim=9 в данном случае.   -  person justHelloWorld    schedule 14.12.2016
comment
Если вы не делаете каких-то странных вещей (подробнее см. здесь), данные в Mat непрерывны. Вы можете думать о Mat как о легкой оболочке над float* (или другими типами), которая обеспечивает более легкий доступ к данным. Таким образом, он так же эффективен, как указатель, но с несколькими приятными абстракциями.   -  person Miki    schedule 14.12.2016
comment
Это то, что я хотел услышать @Miki, большое спасибо. Было бы намного проще использовать Mat для SIFT и записывать/читать его в файлы (используя xml и yaml). То есть вы говорите, что потерь во времени/памяти нет, но ими легче управлять, да?   -  person justHelloWorld    schedule 14.12.2016
comment
Правильный. Вы также можете повысить производительность записи/чтения в файл с помощью этого. Использование xml или yaml может быть слишком медленным. если вам не нужны человекочитаемые файлы, вы можете сохранить в бинарном виде с функциями в ссылке   -  person Miki    schedule 14.12.2016
comment
@Miki абсолютно лучше, я искал двоичное представление Mat. Если вы опубликуете это как ответ, и никто не предложит лучшего решения, я выберу его!   -  person justHelloWorld    schedule 14.12.2016
comment
проверьте, является ли коврик непрерывным, а если нет: используйте mat.clone(), чтобы создать непрерывную копию вашего коврика. Насколько велики ваши матрицы? Будет ли это иметь какое-либо реальное влияние на скорость обработки, если вы просто скопируете их в вектор с плавающей запятой (не вектор вектора с плавающей запятой!)?   -  person Micka    schedule 14.12.2016


Ответы (2)


Если вы не делаете каких-то странных вещей (подробнее см. здесь), данные в Mat гарантированно будут непрерывными. Вы можете думать о Mat как о легкой оболочке над float* (или другими типами), которая обеспечивает более легкий доступ к данным. Таким образом, он так же эффективен, как указатель, но с несколькими приятными абстракциями.

Если вам нужно эффективно загружать/сохранять из/в файл, вы можете сохранить Mat в двоичном формате, используя matread и matwrite.

person Miki    schedule 14.12.2016

std::vector<std::vector<float>> v не будет работать очень хорошо без некоторых усилий, так как память не будет непрерывной.

Как только ваша память будет непрерывной, будь то float[], float[][] или std::array/vector, насколько хорошо она будет работать, будет зависеть от того, как вы перебираете свою матрицу. Если это произвольный доступ, то это мало что меняет; если вы повторяете все столбцы для каждого, то лучше сгруппировать данные по столбцу, а не по строке.

person UKMonkey    schedule 14.12.2016