Tanque de robô Raspberry Pi com bastão de computador Intel Neural 2

Então, uma nova etapa chegou ao desenvolvimento do tanque de framboesa .

Na série anterior, verificou-se que a segmentação semântica fora da caixa era muito difícil para o Raspberry.

Brainstorming e comentários nos permitiram identificar as seguintes áreas de desenvolvimento:

  • treine sua própria rede E-net para o tamanho de imagem desejado
  • transferir o lançamento da rede neural do próprio Raspberry para um hardware especial, do qual o Intel Movidius (também conhecido como Neural Compute Stick ou NCS) foi mencionado com mais frequência.

Anexar um novo pedaço de ferro ao robô é a coisa mais interessante da robótica. Portanto, o trabalho meticuloso de treinar a rede neural foi adiado para tempos melhores.

Alguns dias - e o milagre pedaço de ferro da Intel em minhas mãos.

É muito grande e você não pode colocá-lo no conector USB inferior da framboesa. Como as portas USB certas foram obscurecidas por um tripé de câmera e a parte superior esquerda foi ocupada pelo módulo GPS, não havia muitas opções.

Como resultado, o GPS foi colocado em um cabo, desligado, e o cabo foi enrolado em um tripé, e o NCS entrou em seu lugar.

Nesta parte do hardware foi concluída.



Intel NCS


A Intel lançou recentemente a segunda versão do NCS, e a API era completamente incompatível com a versão anterior, que os usuários colocaram muita dor na Internet.

Como resultado, atualmente toda a base de conhecimento sobre a versão anterior é apenas lixo informativo.

A nova edição oferece a estrutura OpenVino, que inclui o OpenCV e muito mais, incluindo várias ferramentas para trabalhar com redes neurais.

Aqui estão alguns artigos introdutórios sobre NCS2 e OpenVino:


A introdução ao NCS mostrou-se bastante tranquila.

A Intel inicialmente deu suporte ao Raspbian, então não havia necessidade de dançar com um pandeiro.
O documento introdutório também foi muito claro e a instalação da estrutura OpenVino não causou problemas.

Acabou sendo um bom bônus o OpenVino incluir o OpenCV 4.1, o que economiza tempo, já que eu tive que criar versões anteriores do OpenCV no Raspberry.

Aqui está o que o NCS2 se parece sozinho:



Além disso, acabou sendo mais interessante.

O NCS suporta apenas seu próprio formato de rede neural, enquanto a Intel fornece a ferramenta Model Optimizer como parte do OpenVino para a conversão de gráficos das estruturas mais populares: Tensorflow, Caffe, Torch. Mais sobre isso será o próximo.

Além disso, a Intel também fornece modelos de zoológico - um conjunto de modelos prontos para muitas ocasiões.

Entre eles, dois modelos para segmentação de rodovias:


Redes neurais na NCS


Para executar uma rede neural em um dispositivo, você precisa executar várias etapas.

Inicializar dispositivo


O nome MYRIAD, a idéia do plug-in e o carregamento dinâmico dele, o caminho para o qual deve ser especificado no programa - claramente se estendem do passado sombrio.

from openvino.inference_engine import IENetwork, IEPlugin ncs_plugin = IEPlugin(device="MYRIAD", plugin_dirs="/opt/intel/openvino/inference_engine/lib/armv7l") 

Download do modelo


Em seguida, você precisa fazer o upload do modelo para o dispositivo.

Esta é uma operação difícil. Esse pequeno modelo que usei para segmentação leva cerca de 15 segundos para carregar.

A boa notícia é que você só precisa baixar o modelo uma vez e pode baixar vários modelos.

  model = IENetwork(model=xml_path, weights=bin_path) net = ncs_plugin.load(network=model) 

Executar cálculo


Agora o modelo pode ser usado.

  input_blob = next(iter(model.inputs)) out_blob = next(iter(model.outputs)) n, c, h, w = model.inputs[input_blob].shape images = np.ndarray(shape=(n, c, h, w)) images[0] = image res = net.infer(inputs={input_blob: images}) res = res[out_blob] 

Processo único


De repente, descobriu-se que você não pode usar o NCS de dois processos diferentes ao mesmo tempo.
Qualquer pessoa atrasada não pode carregar o modelo:

 E: [ncAPI] [ 684447] resetAll:348 Failed to connect to stalled device, rc: X_LINK_ERROR E: [ncAPI] [ 691700] ncDeviceOpen:672 Failed to find suitable device, rc: X_LINK_DEVICE_NOT_FOUND Traceback (most recent call last): net = ncs_plugin.load(network=model) File "ie_api.pyx", line 395, in openvino.inference_engine.ie_api.IEPlugin.load File "ie_api.pyx", line 406, in openvino.inference_engine.ie_api.IEPlugin.load RuntimeError: Can not init USB device: NC_ERROR 

Nem o Google nem o fórum de suporte da Intel tornaram possível entender qual era o problema - ou o dispositivo é realmente exclusivo ou simplesmente não sei como prepará-lo.

Segmentação OpenVino


Como já mencionado, pronto para uso, o OpenVino fornece um modelo e exemplos de segmentação de estradas.

Os resultados do teste são um tanto contraditórios. Às vezes é reconhecido de maneira torta, mas na maioria é normal.

A Enet funcionou melhor, mas ainda precisamos tentar a Enet no NCS, então vamos tentar com o que temos.



Curiosamente, para aprender mais sobre o modelo no OpenVino e treinar novamente, não é tão simples.

Os usuários estão interessados , mas a pessoa da Intel disse estritamente que o código e os dados do modelo estão fechados, e aqueles que desejarem podem usar uma rede neural semelhante no PyTorch , treinar, converter e usá-lo.

A vantagem da velocidade é muito significativa:
Se a segmentação da Enet demorar 6 segundos, esse modelo levará 0,8 segundos para processar uma foto (enquanto levava 14 segundos para carregar o modelo no dispositivo, mas isso é feito ao mesmo tempo).

Classificação das direções


Para tomar decisões sobre a direção do movimento, o tanque usa uma rede neural simples, conforme descrito no artigo correspondente .

A rede neural é treinada em Keras e é executada em Raspberry através do Tensorflow, que possui um adaptador interno para esse formato.

O modelo é muito simples e até o Raspberry mostra resultados de velocidade aceitáveis.
(0,35 segundos por foto).

No entanto, com a glândula Intel, você pode esperar obter melhores resultados.
Entre os formatos que o Model Optimizer da Intel aceita para conversão, há o Tensorflow, mas não o Keras.

Converter Keras para TF é uma coisa bastante popular, há material suficiente sobre esse tópico, fui guiado por este artigo .

O mesmo autor tem um artigo mais extenso , apenas sobre o tópico de como executar o modelo Keras no OpenVino.

Você também pode usar as orientações da Intel .

Em geral, compilando as fontes, recebi um script para converter o modelo Keras em TF:

 import tensorflow as tf from tensorflow.python.framework.graph_util import convert_variables_to_constants from keras import backend as K from keras.models import load_model from keras.models import model_from_json def load_keras_model(json_file, model_file): jf = open(json_file, 'r') loaded_model_json = jf.read() jf.close() loaded_model = model_from_json(loaded_model_json) loaded_model.load_weights(model_file) return loaded_model def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True): graph = session.graph with graph.as_default(): freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or [])) output_names = output_names or [] output_names += [v.op.name for v in tf.global_variables()] # Graph -> GraphDef ProtoBuf input_graph_def = graph.as_graph_def() if clear_devices: for node in input_graph_def.node: node.device = "" frozen_graph = convert_variables_to_constants(session, input_graph_def, output_names, freeze_var_names) return frozen_graph model = load_keras_model('./model.json', './model.h5') frozen_graph = freeze_session(K.get_session(), output_names=[out.op.name for out in model.outputs]) tf.train.write_graph(frozen_graph, ".", "ktf_model.pb", as_text=False) 

O mesmo código está no github .

O modelo TF resultante é mais destilado no formato OpenVino:

 python mo_tf.py --input_model "model/ktf_model.pb" --log_level=DEBUG -b1 --data_type FP16 

Os testes mostraram que a classificação da imagem leva 0,007 segundos.
Este resultado é muito agradável.

Todos os modelos treinados (Keras, TF, OpenVino) também são carregados no github .

Reconhecimento de Objetos


A tarefa de segmentação não é a única que um robô precisa resolver em sua vida difícil.

No começo, havia um detector de gato, que mais tarde se transformou em um detector universal baseado no MobileSSD e OpenCV-DNN.

Agora é hora de ativar a mesma tarefa no NCS.

No model_zoo da Intel, os detectores de especificidade mais restrita baseados no MobileSSD são suficientes, mas não há analógico exato.

No entanto, esta rede está listada como compatível na lista de modelos TF suportados .

Curiosamente, no momento da redação deste artigo, a versão do MobileSSD 2018_01_28 é indicada aqui.

No entanto, o OpenCV se recusa a ler este modelo:

 cv2.error: OpenCV(4.1.0-openvino) /home/jenkins/workspace/OpenCV/OpenVINO/build/opencv/modules/dnn/src/tensorflow/tf_importer.cpp:530: error: (-2:Unspecified error) Const input blob for weights not found in function 'getConstBlob' 

(Mas descobrimos que eles usam Jenkins).

Ao mesmo tempo, a conversão para o OpenVino é bem-sucedida.

Se tentarmos converter a versão do Mobile SSD compatível com o OpenCV-DNN (11_06_2017), obtemos o seguinte:

 [E0919 main.py:317] Unexpected exception happened during extracting attributes for node FeatureExtractor/MobilenetV1/Conv2d_13_pointwise_1_Conv2d_2_1x1_256/Relu6. Original exception message: operands could not be broadcast together with remapped shapes [original->remapped]: (0,) and requested shape (1,0,10,256) 

Algo assim, tecnicamente OpenVino e OpenCV-DNN estão no mesmo pacote, mas são incompatíveis com as versões das redes neurais usadas.

Ou seja, se você quiser usar as duas abordagens simultaneamente, precisará arrastar duas versões do MobileSSD.

Em termos de velocidade, a comparação é certamente a favor do NCS: 0,1 segundos versus 1,7.

Em termos de qualidade ... (Embora isso não seja uma questão do NCS, mas da evolução do SSD móvel).



Classificação da imagem


O tanque é capaz de classificar imagens através do Tensorflow, usando o Inception no Imagenet.
E eu usei o Inception 05-12-2015, quando era outro.

Aconteceu que eu estava muito atrasada na vida, porque os caras do Google não estão à toa comendo o pão e já produziram quatro versões!

Mas os caras da Intel não estão por trás deles e todas as quatro versões foram suportadas no OpenVino.

Aqui está um artigo que descreve várias versões do Inception.
Mas não vamos brincar, baixamos imediatamente o último, quarto.

Classificamos a foto com o gato e o laptop em cima da mesa.

Lembramos os resultados da versão atual:

  • laptop 62%
  • notebook, notebook 11%
  • 13 segundos
  • onde esta o gato

Agora lemos as instruções para converter o Inception em OpenVino.

A conversão foi bem-sucedida, iniciamos o classificador no NCS:

  • laptop, computador portátil 85%
  • notebook, notebook 8%
  • 0,2 segundos
  • não há gato de novo

Conclusão


Assim, todos os cenários que exigiam o Tensorflow foram reproduzidos usando o NCS, e isso significa que você pode optar por não usar o Tensorflow.

Mesmo assim, essa estrutura é pesada para o Raspberry.

A velocidade com que o NCS digere a rede neural permite expandir seus horizontes.

Há tarefas que o robô já realiza, por exemplo, segmentação e classificação semânticas, mas há outras como segmentação de objetos ou transmissão de vídeo com objetos detectados em tempo real. (que não poderia ter sido pensado na framboesa nua).

Os problemas com o multiprocessamento são um pouco confusos, mas mesmo que não possam ser resolvidos, sempre há uma opção na forma de o NCS agrupar um serviço separado.

Referências


Source: https://habr.com/ru/post/pt459126/


All Articles