Ошибка прямого метода в модуле DNN OpenCV (Ptyhon) с использованием модели .onnx

Я хотел протестировать предварительно обученную модель, загруженную отсюда, для выполнения задачи ocr. Ссылка для загрузки, ее имя - CRNN_VGG_BiLSTM_CTC.onnx. Эта модель извлечена из здесь. Sample-image.png можно загрузить с здесь (см. Код ниже ).

Когда я делаю пересылку нейронной сети для прогнозирования (ocr) в большом двоичном объекте, я получаю следующую ошибку:

ошибка: OpenCV (4.4.0) /tmp/pip-req-build-xgme2194/opencv/modules/dnn/src/layers/convolution_layer.cpp:348: ошибка: (-215: сбой утверждения) ngroups ›0 && inpCn% ngroups == 0 && outCn% ngroups == 0 в функции 'getMemoryShapes'

Не стесняйтесь читать приведенный ниже код. Я много чего пробовал, это странно, потому что эта модель не требует заранее заданной формы ввода. Если вы знаете какой-либо способ прочитать эту модель и продвинуться вперед, это тоже будет полезно, но я бы предпочел решить проблему с помощью OpenCV.

import cv2 as cv
# The model is downloaded from here https://drive.google.com/drive/folders/1cTbQ3nuZG-EKWak6emD_s8_hHXWz7lAr
# model path 
modelRecognition = os.path.join(MODELS_PATH,'CRNN_VGG_BiLSTM_CTC.onnx')
# read net 
recognizer = cv.dnn.readNetFromONNX(modelRecognition)

# Download sample_image.png from https://i.ibb.co/fMmCB7J/sample-image.png  (image host website)
sample_image = cv.imread('sample-image.png')
# Height , Width and number of channels of the image
H, W, C = sample_image.shape

# Create a 4D blob from cropped image
blob = cv.dnn.blobFromImage(sample_image, size = (H, W))

recognizer.setInput(blob)

# Here is where i get the errror that I mentioned before 
result = recognizer.forward()

Огромное спасибо заранее.


person Tom    schedule 29.12.2020    source источник


Ответы (1)


На самом деле ваша проблема в том, что входные данные, которые вы вводите в модель, не соответствуют форме данных, на которых была обучена модель.

Я использовал этот ответ для проверки вашей модели onnx, и оказалось, что она ожидает ввода формы (1, 1, 32, 100). Я изменил ваш код, чтобы изменить форму изображения до 1 x 32 x 100 пикселей, и вывод фактически выполняется без ошибок.

ИЗМЕНИТЬ

Я добавил код для интерпретации результата вывода. Теперь мы отображаем изображение и предполагаемый текст OCR. Кажется, это не работает, но прочтите руководство по OpenCV, должно быть две модели:

  1. тот, который определяет, где на изображении есть текст. Эта сеть принимает изображения различных размеров, она возвращает расположение текста в изображении, а затем обрезанные части изображения размером 100x32 передаются второму
  2. тот, который на самом деле выполняет чтение и заданные участки изображения, возвращает символы. Для этого есть файл alphabet_36.txt, который предоставляется вместе с предварительно обученными моделями.

Мне непонятно, какую сеть использовать для обнаружения текста. Надеюсь, что приведенный ниже отредактированный код поможет вам в дальнейшей разработке вашего приложения.

import cv2 as cv
import os
import numpy as np
import matplotlib.pyplot as plt
# The model is downloaded from here https://drive.google.com/drive/folders/1cTbQ3nuZG-EKWak6emD_s8_hHXWz7lAr
# model path 
MODELS_PATH = './'
modelRecognition = os.path.join(MODELS_PATH,'CRNN_VGG_BiLSTM_CTC.onnx')

# read net 
recognizer = cv.dnn.readNetFromONNX(modelRecognition)

# Download sample_image.png from https://i.ibb.co/fMmCB7J/sample-image.png  (image host website)
sample_image = cv.imread('sample-image.png', cv.IMREAD_GRAYSCALE)
sample_image = cv.resize(sample_image, (100, 32))
sample_image = sample_image[:,::-1].transpose()

# Height and Width of the image
H,W = sample_image.shape

# Create a 4D blob from image
blob = cv.dnn.blobFromImage(sample_image, size=(H,W))
recognizer.setInput(blob)

# network inference
result = recognizer.forward()

# load alphabet
with open('alphabet_36.txt') as f:
    alphabet = f.readlines()
alphabet = [f.strip() for f in alphabet]

# interpret inference results
res = []
for i in range(result.shape[0]):
    ind = np.argmax(result[i,0])
    res.append(alphabet[ind])
ocrtxt = ''.join(res)

# show image and detected OCR characters
plt.imshow(sample_image)
plt.title(ocrtxt)
plt.show()

Надеюсь, это поможет. Ваше здоровье

person Christian    schedule 08.01.2021
comment
Привет, Криситиан, большое спасибо за ответ. Я был вполне уверен, что архитектура этой сети не требует фиксированного размера ввода (из-за операций свертки внутри них), но я был не прав. Такая ошибка! Вы определенно решили проблему, которую я опубликовал, и поэтому заслужили ответ, помеченный как правильный. Как бы то ни было, эта сеть предназначена для модели OCR, знаете ли вы, почему изменение размера до 100,32 имеет смысл? Я думал, что эта модель ocr подойдет для слов. Но, может быть, эта модель работает только для персонажей и ей нужна предыдущая модель сегментации? - person Tom; 08.01.2021
comment
Если вы хотите поделиться своими мыслями по этому поводу, это было бы очень полезно. Огромное спасибо заранее! - person Tom; 08.01.2021
comment
Привет, Том, добро пожаловать! Ну, я не знаком с этой конкретной сетью (у вас есть где-нибудь ее архитектура, из бумаги или около того?), Но если в ней есть полностью связанные слои после сверточных слоев, тогда сеть фактически зависит от формы входа. - person Christian; 08.01.2021
comment
Относительно того, имеет ли смысл изменение размера, это хороший вопрос. Имеет смысл, если символы примерно того же размера после изменения размера, что и при обучении. В противном случае сеть, вероятно, будет пытаться вернуть правильные символы. - person Christian; 08.01.2021
comment
Привет, Том, посмотри мои правки в моем ответе, надеюсь, это поможет тебе в дальнейшем - person Christian; 09.01.2021
comment
Привет, Кристиан, да, меня смутил тот факт, что говорится о сети VGG, поэтому я подумал, что она использует сеть VGG в начальной точке архитектуры и, следовательно, не полагается на форму ввода, но ясно, что она зависит от формы ввода, поэтому забудь эти слова, ха-ха. Нет, к сожалению, я еще не нашел для этого бумаги. - person Tom; 10.01.2021
comment
Наконец, я взглянул на эту реализацию веб-камер github.com / opencv / opencv / blob / master / samples / dnn / и понимаю, что я не масштабировал изображение, и это сильно ухудшало производительность модели. Если вы измените масштаб изображения на mean = 127,5 и std = 127,5, вы начнете получать приличные результаты, я также использовал распознавание уровня символов. - person Tom; 10.01.2021
comment
Я не думал о масштабировании данных, молодец! - person Christian; 10.01.2021