OPENCV Есть ли лучший способ доступа к данным по измерению? - PullRequest
1 голос
/ 12 марта 2020

У меня есть 3-мерное cv :: Mat с размером (10, строки = M, столбцы = N). Это 10 изображений с пикселями MxN, сложенными в куб. Я хотел бы нарезать куб по строкам в измерении по изображениям так, чтобы в конце у меня было M кусочков (10, N), к которым я буду применять некоторые другие алгоритмы opencv. Я обнаружил, что могу сделать это с помощью cv :: Ranges (); Тем не менее, я должен использовать Reshape, чтобы сделать его 2D, и поэтому я должен использовать Clone (), чтобы сделать срез непрерывным. Ниже приведен фрагмент кода, который я использовал для этого, но время выполнения медленное (я думаю, что делать с клоном / копией, которая делается для каждого среза строки). Есть лучший способ сделать это? Я также нашел это , что не внушает оптимизма.

const int img_dim[3] = {10, 20, 40};
Mat data = Mat::zeros(3, img_dim, CV_64FC1);
for (int row = 0; row < data.size[1]; row++ {
    std::vector<Range> range;
    range.push_back(Range(0, data.size[0]));
    range.push_back(Range(row, row+1));
    range.push_back(Range(0, data.size[2]));

    // Below slice is still 3D with (10, 1, 40) so I use reshape to make it (10, 40)
    // which requires the clone()
    Mat slice = data(&range[0]).clone();
    const int sz[] {data.size[0], data.size[2]};
    slice = slice.reshape(1, 2, sz);

    // Processing of slice
    // e.g cv::GaussianBlur(slice, dst, Size(0,0), r, r);
}

1 Ответ

1 голос
/ 12 марта 2020

Вы можете установить step (шаг байтов) и построить срез без копирования данных:

Предположим, data непрерывно в памяти:

  • Строка начинается со смещения row*N double элементов от data.data (data.data данные матрицы точек).
  • Срез step (шаг байтов между рядами) равен M * N *sizeof(double).

[В случае, если data не является непрерывным в памяти, решение является более сложным].

Вот пример кода (строит срез 5-й строки):

const int M = 20;
const int N = 40;
const int img_dim[3] = { 10, M, N };
Mat data = cv::Mat::zeros(3, img_dim, CV_64FC1);

int row = 5;

data.at<double>(0, row, 0) = 0;
data.at<double>(1, row, 0) = 1;
data.at<double>(2, row, 0) = 2;
data.at<double>(3, row, 0) = 3;

data.at<double>(0, row, 1) = 100;
data.at<double>(1, row, 1) = 101;
data.at<double>(2, row, 1) = 102;
data.at<double>(3, row, 1) = 103;

//Byte stride between M of slice equals M*N*8 bytes
size_t step = M * N *sizeof(double);

//slice begins at data.data + row*N
Mat slice(10, N, CV_64FC1, (uchar*)data.data + row*N*sizeof(double), step);

std::cout << slice.at<double>(0, 0) << std::endl << slice.at<double>(1, 0) << std::endl << slice.at<double>(2, 0) << std::endl << slice.at<double>(3, 0) << std::endl << std::endl;
std::cout << slice.at<double>(0, 1) << std::endl << slice.at<double>(1, 1) << std::endl << slice.at<double>(2, 1) << std::endl << slice.at<double>(3, 1) << std::endl << std::endl;

Примечание. Обработка данных с большими шагами может быть неэффективной из-за пропусков кэша - может быть более эффективно копировать данные (проверьте, замедляется ли обработка данных).


Выход:

0
1
2
3

100
101
102
103
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...