Как вернуть многомерный массив Mat из функции

Я хочу вернуть объект cv :: Mat с размерами [w] [h] [c], где w - ширина, h - высота, а c - каналы или глубина. Но компилятор выдает ошибку.

Это мой код:

cv::Mat three_channel_convolution(cv::Mat bgr_image, cv::Mat kernel)
{
   cv::Mat feature_map[3];
   cv::Mat bgr[3];

   cv::split(bgr_image, bgr);

   for (uchar i = 0; i < 3; i++)
   {
      feature_map[i] = one_channel_convolution(bgr[i], kernel);
      std::string name_feature_map = "bgr_feature_map_" + std::to_string(i) + ".jpg";
      cv::imwrite(name_feature_map, feature_map[i]);
   }

return feature_map;
}

В этой функции я хочу сделать свертку с фильтром (ядром) для каждого из трех каналов в изображении BGR. Таким образом, функция свертки возвращает результат операции в одном канале (A single 2D Mat [] []) и сохраняет его в массиве Feature_map Mat. Как мне вернуть этот массив Mat?

Затем в моей функции main () я вызываю функцию следующим образом:

feature_map = three_channel_convolution(image, kernels[0]);

Спасибо за помощь!


person Pablo Cano    schedule 14.02.2019    source источник
comment
Какая у вас ошибка?   -  person NathanOliver    schedule 14.02.2019
comment
вы объявили метод возврата cv::Mat   -  person 463035818_is_not_a_number    schedule 14.02.2019
comment
Вы возвращаете ссылку на временный объект (временный массив). Вы можете вернуть std::shared_ptr<cv::Mat> или std::array<cv::Mat,3>   -  person Victor Gubin    schedule 14.02.2019
comment
В настоящее время вы создаете три разных cv::Mat, потому что вы cv::split входное изображение. Вам просто нужно cv::merge снова их перед возвращением.   -  person Max Langhof    schedule 14.02.2019


Ответы (1)


Возвращаемое значение функции three_channel_convolution - cv::Mat, но вы возвращаете cv::Mat[3].

Если вы хотите вернуть трехмерную матрицу, вам нужно изменить подпись функции на что-то вроде std::array<cv::Mat, 3>. Имейте в виду, что при этом могут возникнуть проблемы с производительностью.

std::array<cv::Mat, 3> three_channel_convolution(cv::Mat bgr_image, cv::Mat kernel) {
   std::array<cv::Mat, 3> feature_map;
   std::array<cv::Mat, 3> bgr;

   cv::split(bgr_image, bgr);

   for (uchar i = 0; i < 3; i++) {
      feature_map[i] = one_channel_convolution(bgr[i], kernel);
      std::string name_feature_map = "bgr_feature_map_" + std::to_string(i) + ".jpg";
      cv::imwrite(name_feature_map, feature_map[i]);
   }

    return feature_map;
}

Пс. Пожалуйста, сообщайте точное сообщение об ошибке в следующих сообщениях.

person schorsch312    schedule 14.02.2019
comment
Решение указателя работает. Я понимаю, что я возвращаю указатель на то, где хранится массив мата. Но не могли бы вы объяснить, что я буду делать, если использую std :: array ‹cv :: Mat, 3› в возвращаемом значении функции? - person Pablo Cano; 14.02.2019
comment
Обычный старый массив не может использоваться в качестве возвращаемого значения. Вы можете сделать две вещи. Во-первых (старый стиль c) вы можете вернуть указатель на начало массива. Это может быть небезопасно, и вам нужно позаботиться о памяти. Это также верно, если вы дадите указатель в качестве выходного аргумента функции. Во-вторых, вы можете использовать контейнер C ++ как возвращаемое значение. Начиная с C ++ 11, у вас будет так называемая оптимизация возвращаемого значения, которая сделает ее довольно быстрой и не будет создавать ненужных копий. - person schorsch312; 14.02.2019
comment
@PabloCano В этом случае вы возвращаете std::array<cv::Mat, 3>. std::array - это такой же объект, как std::string, std::vector или cv::Mat, и вы возвращаете один из них. Это простое решение, намного проще, чем возврат указателя. Основная проблема, с которой вы столкнулись, заключается в том, что обычные массивы не являются объектами первого класса в C ++, и есть некоторые вещи, которые они не могут делать (например, возвращаемые из функции). std::array - это способ заполнить пробелы, которые есть в обычных массивах. - person john; 14.02.2019
comment
@jhon И как только у меня есть возвращаемый объект в допустимой переменной в основной функции, могу ли я использовать методы или атрибуты cv :: Mat, как обычный объект cv :: Mat ?. - person Pablo Cano; 14.02.2019