Преобразование строки из cv :: Mat в std :: vector - PullRequest
9 голосов
/ 20 марта 2012

У меня довольно простой вопрос: как взять одну строку cv::Mat и получить все данные в std::vector?cv::Mat содержит doubles (это может быть любой простой тип данных для целей вопроса).

Просмотр документации OpenCV просто очень запутанный, если я не добавлю в закладки страницу, я не смогу найти страницу документацииДважды по Googling, многое из этого и не так легко ориентироваться.

Я нашел cv::Mat::at(..) для доступа к элементу Matrix, но я помню из C OpenCV, что было как минимум 3 разных способачтобы получить доступ к элементам, все они использовались для разных целей ... Не могу вспомнить, для чего использовался: /

Так что, хотя копирование элемента Matrix по элементам, безусловно, будет работать, я ищуспособ, который более эффективен и, если возможно, немного более элегантен , чем цикл for для каждой строки.

Ответы [ 5 ]

29 голосов
/ 20 марта 2012

Это должно быть просто:

m.row(row_idx).copyTo(v);

Где m равно cv::Mat с CV_64F глубиной и v равно std::vector<double>

17 голосов
/ 20 марта 2012

Данные в матрицах OpenCV располагаются в главном порядке строк, так что каждая строка гарантированно будет смежной.Это означает, что вы можете интерпретировать данные в строке как простой C-массив.Следующий пример взят непосредственно из документации :

// compute sum of positive matrix elements
// (assuming that M is double-precision matrix)
double sum=0;
for(int i = 0; i < M.rows; i++)
{
    const double* Mi = M.ptr<double>(i);
    for(int j = 0; j < M.cols; j++)
        sum += std::max(Mi[j], 0.);
}

Поэтому самый эффективный способ - передать простой указатель на std::vector:

// Pointer to the i-th row
const double* p = mat.ptr<double>(i);

// Copy data to a vector.  Note that (p + mat.cols) points to the
// end of the row.
std::vector<double> vec(p, p + mat.cols);

Thisбезусловно, быстрее, чем использование итераторов, возвращаемых begin() и end(), поскольку они требуют дополнительных вычислений для поддержки промежутков между строками.

6 голосов
/ 20 марта 2012

Из документации здесь вы можете получить определенную строку через cv::Mat::row, которая вернет новый cv::Mat, по которому вы можете выполнять итерацию с cv::Mat::begin и cv::Mat::end. Таким образом, должно работать следующее:

cv::Mat m/*= initialize */;
// ... do whatever...
cv::Mat first_row(m.row(0));
std::vector<double> v(first_row.begin<double>(), first_row.end<double>());

Обратите внимание, что я не знаю OpenCV, но поиск в Google "OpenCV mat" привел непосредственно к документации по базовым типам, и в соответствии с этим, это должно работать нормально.

Матричные итераторы являются итераторами с произвольным доступом, поэтому их можно передавать любому алгоритму STL, включая std :: sort ().

Это также из документации, так что вы можете сделать это без копии:

cv::Mat m/*= initialize */;
// ... do whatever...
// first row          begin              end
std::vector<double> v(m.begin<double>(), m.begin<double>() + m.size().width);

Чтобы получить доступ больше, чем к первой строке, я бы порекомендовал первый фрагмент, поскольку в этом случае он будет намного чище, и нет необходимости выполнять тяжелое копирование, поскольку типы данных кажутся подсчитанными по ссылкам.

2 голосов
/ 24 августа 2013

Вы также можете использовать cv::Rect

m(cv::Rect(0, 0, 1, m.cols)) 

даст вам первый ряд.

matrix(cv::Rect(x0, y0, len_x, len_y);

означает, что вы получите sub_matrix от matrix, левый верхний угол которого (x0,y0) и размер (len_x, len_y).(row,col)

0 голосов
/ 19 декабря 2014

Я думаю, что это работает,

пример:

Mat Input(480, 720, CV_64F, Scalar(100));

обрезка 1-й строки матрицы:

Rect roi(Point(0, 0), Size(720, 1));

затем:

std::vector<std::vector<double> > vector_of_rows;

vector_of_rows.push_back(Input(roi));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...