Ошибка OpenCV (4.8.0): функция/функция не реализована () в cv::debug_build_guard::_OutputArray::assign

Я пытаюсь перевести код Python на C++ и натыкаюсь на этот код:

self.net = cv.dnn.readNetFromDarknet(cfg_file, weights_file)
self.net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
self.ln = self.net.getLayerNames()
self.ln = [self.ln[i-1] for i in self.net.getUnconnectedOutLayers()]
     ...
blob = cv.dnn.blobFromImage(img, 1/255.0, (416, 416), swapRB=True, crop=False)
self.net.setInput(blob)
outputs = self.net.forward(self.ln)
outputs = np.vstack(outputs)

Как видите, код пересылает выходные данные из сети из имен несвязанных слоев, указанных в self.ln. Вот мой код на C++:

static Mat blobFromImg;
bool swapRB = true;
blobFromImage(img, blobFromImg, 1/255.0, Size(416, 416), Scalar(), swapRB, false);
network.setInput(blobFromImg);
Mat outMat;
network.forward(outMat , network.getUnconnectedOutLayersNames());
vconcat(outMat, outMat);

Как видите, я использую cv::vconcat вместо np.vstack вместо создания нового std::vector<<cv::String>> для перехода к network.forward(). Я использую getUnconnectedOutLayersNames(). Тем не менее, я получаю эту ошибку:

OpenCV(4.8.0) Error: The function/feature is not implemented () in cv::debug_build_guard::_OutputArray::assign, file D:\vcpkg\buildtrees\opencv4\src\4.8.0-2bf495557d.clean\modules\core\src\matrix_wrap.cpp, line 2052

Строка, в которой возникает исключение, — network.forward(). Именно благодаря этому методу network.getUnconnectedOutLayersNames() сам по себе не выдает исключение.

Если я сделаю:

std::vector<cv::String> ln;
auto layers = network.getLayerNames();
for (auto i : network.getUnconnectedOutLayers()){
   ln.push_back(layers[i-1]);
}
   ...
network.setInput(blobFromImg);
Mat outMat;
network.forward(outMat , ln);
vconcat(outMat, outMat);

Я получаю тот же результат.

Почему функция не реализована? Почему Python имеет эту реализацию.

Примечание. Я использую darknet/yolo.

Просто догадайтесь: сделайте outMatstd::vector<cv::Mat>... Это последовательность капель.

Dan Mašek 17.06.2024 20:06

@DanMašek, это сработало отлично. Спасибо!

S.T.A.L.K.E.R 17.06.2024 20:21

любой из вас должен опубликовать это в качестве ответа. ответы на вопросы занимают более высокие позиции в результатах поиска.

Christoph Rackwitz 18.06.2024 00:13

@ChristophRackwitz Верно, мне просто нужно было найти что-то, подтверждающее мое предположение. :)

Dan Mašek 19.06.2024 00:37
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Судя по контексту, мы имеем дело со следующей перегрузкой cv::dnn::Net::forward, в документации которой говорится:

void cv::dnn::Net::forward(OutputArrayOfArrays outputBlobs, const std::vector<String>& outBlobNames)

Параметры:

  • outputBlobs содержит BLOB-объекты для первых выходных данных указанных слоев.
  • outBlobNames названия слоев, для получения которых необходимы результаты

Проблема в первом параметре outputBlobs. В документации говорится, что cv::OutputArrayOfArrays это псевдоним для cv::_OutputArray:

typedef OutputArray OutputArrayOfArrays;

Кроме этого, на этой странице мало что можно найти. Для получения более полезной информации нам нужно просмотреть документацию cv::_InputArray, из которой он получен:

... можно составить из ..., std::vector<std::vector<T>>, std::vector<Mat>, std::vector<Mat_<T>>

...

Существует еще один родственный тип InputArrayOfArrays, который в настоящее время определяется как синоним InputArray:

typedef InputArray InputArrayOfArrays;

Он обозначает аргументы функции, которые являются либо векторами векторов, либо векторами матриц. Для правильной генерации оболочек Python/Java и т. д. необходим отдельный синоним. На уровне реализации функции их использование аналогично, но _InputArray::getMat(idx) следует использовать для получения заголовка для idx-го компонента внешнего вектора, а _InputArray::size().area() следует использовать для определения количества компонентов (векторов/матриц) внешнего вектора.

И вдруг становится ясно. Мы вызываем функцию с последовательностью имен слоев, мы должны вернуть последовательность больших двоичных объектов. Мы знаем, что каплю можно представить в виде 4D cv::Mat. Их последовательность в C++ будет представлять собой vector из Mat: std::vector<cv::Mat>. Итак, измените первый параметр forward на этот тип. И, как вы говорите, «это сработало идеально».

Другие вопросы по теме