"Desculpe, eu reconheci ..." ou reconheça framboesas e controladores usando a API de detecção de objetos do Tensorflow

No final do ano passado, escrevi um artigo sobre como fiquei intrigado com a capacidade de reconhecer objetos em imagens usando redes neurais. Nesse artigo, usando o PyTorch, categorizamos framboesas ou um controlador semelhante ao arduino em vídeo. E apesar do fato de gostar do PyTorch, virei-me para ele porque não conseguia lidar com o TensorFlow imediatamente. Mas prometi voltar à questão do reconhecimento de objetos no vídeo. Parece que chegou a hora de cumprir a promessa.

Neste artigo, tentaremos em nossa máquina local treinar novamente o modelo finalizado no Tensorflow 1.13 e a API de detecção de objetos em nosso próprio conjunto de imagens e usá-lo para reconhecer bagas e controladores no fluxo de vídeo de uma câmera da Web usando OpenCV.

Deseja melhorar sua habilidade de reconhecimento de frutos silvestres até o verão? Então você é bem-vindo sob gato.



Conteúdo:

Parte I: introdução
Parte II: treine o modelo no TenosrFlow
Parte III: aplique o modelo no OpenCV
Parte IV: conclusão

Parte I: Introdução


Quem leu o artigo anterior sobre o PyTorch já sabe que sou amador em questões de redes neurais. Portanto, não perceba este artigo como a verdade suprema. De qualquer forma, espero poder ajudar alguém a lidar com o básico do reconhecimento de vídeo usando a API de detecção de objetos do Tensorflow.

Desta vez, não tentei fazer um tutorial, portanto, o artigo será mais curto que o normal.
Para começar, o tutorial oficial sobre o uso da API de detecção de objetos em uma máquina local, para dizer o mínimo, não é exaustivo. Como iniciante, eu era completamente inadequado e tinha que me concentrar nos artigos do blog.

Para ser sincero, gostaria de experimentar o TensorFlow 2.0, mas na maioria das publicações, no momento em que este artigo foi escrito, os problemas de migração não foram completamente resolvidos. Portanto, no final, eu decidi pelo TF 1.13.2.

Parte II: ensinando um modelo no TensorFlow


Eu desenhei instruções para ensinar o modelo neste artigo , ou melhor, desde o primeiro semestre, até a aplicação do JavaScript (se você não fala inglês, pode ver um artigo sobre o mesmo tópico em Habré ) .

É verdade que, no meu caso, existem várias diferenças:

  1. Eu usei o Linux porque o Anaconda para Linux já criou protobuf e pycocoapi, então não precisei construí-los.
  2. TensorFlow 1.13.2, Object Detection API 1.13 , TensorFlow 1.13.2. master TF 1.15, 1.13.
  3. numpy — 1.17.5, 1.18 .
  4. faster_rcnn_inception_v2_coco ssd_mobilenet_v2_coco, , .

Por precaução, direi que não usei um acelerador gráfico. O treinamento foi realizado apenas nas capacidades do processador.

Um conjunto de imagens, um arquivo de configuração, um gráfico salvo e um script para reconhecer imagens usando o OpenCV, como sempre, podem ser baixados do GitHub .

Passadas 23 horas de treinamento de modelos, todo o chá da casa já foi tomado, “O quê? Onde? Quando?" inspecionado e agora minha paciência finalmente chegou ao fim.

Paramos o treinamento e salvamos o modelo.

Instale o OpenCV no mesmo ambiente do "Anaconda" com o seguinte comando:

conda install -c conda-forge opencv

Eventualmente, instalei a versão 4.2

Além disso, as instruções deste artigo não serão mais necessárias.

Depois de salvar o modelo, cometi um erro que não era óbvio para mim: tentei imediatamente substituir o arquivo graph.pbtxt usado anteriormente na pasta training / na função:

cv2.dnn.readNetFromTensorflow()

Infelizmente, isso não funciona dessa maneira e teremos que fazer mais uma manipulação para obter o graph.pbtxt para o OpenCV.

Muito provavelmente, o fato de agora aconselhar não é uma maneira muito boa, mas para mim funciona.

Baixe tf_text_graph_ssd.py e também tf_text_graph_common.py coloque-os na pasta onde está localizado o gráfico salvo (eu tenho essa pasta inference_graph).
Em seguida, vá para o console nesta pasta e execute a partir dele um comando com aproximadamente o seguinte conteúdo:

python tf_text_graph_ssd.py --input frozen_inference_graph.pb --config pipeline.config --output graph.pbtxt

E isso é tudo o que resta para carregar nosso modelo no OpenCV.


Parte III: aplique o modelo no OpenCV


Como no artigo sobre PyTorch sobre o trabalho com o OpenCV, tomei como base o código do programa desta publicação .

Fiz pequenas alterações para simplificá-lo um pouco mais, mas como não entendo completamente o código, não vou comentar. Funciona e agradável. Está claro que o código poderia ter sido melhor, mas ainda não tenho tempo para me sentar nos tutoriais do OpenCV .

Código OpenCV

# USAGE
# based on this code https://proglib.io/p/real-time-object-detection/
# import the necessary packages
from imutils.video import VideoStream
from imutils.video import FPS
import numpy as np
import imutils
import time
import cv2

prototxt="graph.pbtxt"
model="frozen_inference_graph.pb"
min_confidence = 0.5

# initialize the list of class labels MobileNet SSD was trained to
# detect, then generate a set of bounding box colors for each class
CLASSES = ["background", "duino","raspb"]
COLORS = [(40,50,60),((140,55,130)),(240,150,25)]

# load our serialized model from disk
print("[INFO] loading model...")

net =cv2.dnn.readNetFromTensorflow(model,prototxt)

# initialize the video stream, allow the cammera sensor to warmup,
# and initialize the FPS counter
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(0.5)
fps = FPS().start()

# loop over the frames from the video stream
while True:
	# grab the frame from the threaded video stream and resize it
	# to have a maximum width of 400 pixels
	frame = vs.read()
	frame = imutils.resize(frame, width=300)

	# grab the frame dimensions and convert it to a blob
	(h, w) = frame.shape[:2]
	blob = cv2.dnn.blobFromImage(frame, size=(300, 300), swapRB=True)

	# pass the blob through the network and obtain the detections and
	# predictions
	net.setInput(blob)
	detections = net.forward()

	# loop over the detections
	for i in np.arange(0, detections.shape[2]):
		# extract the confidence (i.e., probability) associated with
		# the prediction
		print (detections)
		confidence = detections[0, 0, i, 2]

		if confidence > min_confidence:
			# extract the index of the class label from the
			# `detections`, then compute the (x, y)-coordinates of
			# the bounding box for the object
			idx = int(detections[0, 0, i, 1])
			box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
			(startX, startY, endX, endY) = box.astype("int")

			# draw the prediction on the frame
			label = "{}: {:.2f}%".format(CLASSES[idx],
				confidence * 100)
			cv2.rectangle(frame, (startX, startY), (endX, endY),
				COLORS[idx], 2)
			y = startY - 15 if startY - 15 > 15 else startY + 15
			cv2.putText(frame, label, (startX, y+3),
				cv2.FONT_HERSHEY_SIMPLEX, 0.5, COLORS[idx], 1)

	# show the output frame
	cv2.imshow("Frame", frame)
	key = cv2.waitKey(1) & 0xFF

	# if the `q` key was pressed, break from the loop
	if key == ord("q"):
		break

	# update the FPS counter
	fps.update()

# stop the timer and display FPS information
fps.stop()
print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))

# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()


Então, está tudo pronto. Lançamos o modelo, apontamos as lentes para o meu velho CraftDuino e apreciamos o resultado:



À primeira vista, não é nada ruim, mas é apenas à primeira vista.
Parece que em 23 horas, o modelo foi treinado novamente, portanto, apresenta erros graves ao definir objetos.

Aqui está uma demonstração visual:



Como você pode ver, não apenas uma faca, mas mesmo apenas um fundo preto, este modelo define-o como um controlador semelhante ao arduino. Talvez isso ocorra porque nos dados de treinamento havia imagens escuras com o Arduino e seus análogos, nas quais o modelo conseguiu esbarrar em 23 horas.

Como resultado, tive que carregar meu computador por mais 8 horas e treinar um novo modelo.

As coisas estão muito melhores com ela.

Aqui está um exemplo com o CraftDuino:



Framboesas vivas não estão à mão. Eu tive que imprimir fotos. Na tela do telefone ou monitor, você também pode reconhecer, mas no papel era mais conveniente.



Vamos verificar como o modelo reconhece o Arduino nano, que no devido tempoDrzugrikpara mim, soldei meu mega dispositivo com sensores:



como você pode ver, ele reconhece muito bem, mas com um ângulo muito ruim e com iluminação quente, ele reconhece alguns fragmentos como framboesas. Mas, na verdade, era difícil capturar uma moldura com erro na lente.

Agora vamos verificar como ela classifica os objetos nos quais não foi treinada.

Novamente, um exemplo com uma faca e um fundo preto:



desta vez tudo funciona como deveria.

Vamos oferecer nosso modelo para reconhecer o pequeno controlador Canny 3, sobre o qual escrevi em um artigo anterior .



Como nosso modelo não sabe nada, exceto framboesas e controladores do tipo arduino, podemos dizer que o modelo reconheceu o controlador Canny com bastante êxito.

É verdade que, como no caso do Arduino nano, muito depende do ângulo e da iluminação.

Com a luz quente de uma lâmpada incandescente e com um ângulo malsucedido, o controlador pode não apenas ser reconhecido, mas também definido como framboesa. É verdade que, como no caso anterior, esses ângulos ainda precisavam tentar capturar a lente.



Bem, o último caso é uma espécie de reverência para o artigo sobre a classificação de imagens no PyTorch . Como na última vez, o computador de placa única Raspberry Pi 2 e seu logotipo são compatíveis em um quadro. Diferentemente do artigo anterior, no qual resolvemos o problema de classificação e escolhemos um objeto mais provável para a imagem, neste caso, o logotipo e o próprio Raspberry são reconhecidos.




Parte IV: Conclusão


Concluindo, quero dizer que, apesar da inexperiência desse pequeno exemplo de trabalho com a API de detecção de objetos do Tensorflow, demorou dois dias de folga e parte de segunda-feira, não me arrependo. Quando pelo menos um pouco de compreensão de como usar tudo se torna insanamente curioso. No processo de aprendizagem, você começa a considerar o modelo como um modelo vivo, acompanha seus sucessos e fracassos.
Portanto, recomendo a todos que não estão familiarizados com isso um dia tentar reconhecer algo próprio.

Além disso, como ele aumentou no processo, você nem precisa comprar uma webcam real. O fato é que, durante a preparação do artigo, eu consegui quebrar minha webcam (quebrei o mecanismo de foco) e já pensei que teria que abandonar tudo. Mas, com a ajuda do Droidcam, você pode usar um smartphone em vez de uma webcam (não conte para publicidade). Além disso, a qualidade da fotografia acabou sendo muito melhor do que a de uma câmera quebrada, e isso influenciou bastante a qualidade do reconhecimento de objetos na imagem.

A propósito, como o Anaconda tem uma compilação normal de pycocotoolsEncontrei-o apenas para Linux e fiquei com preguiça de alternar entre sistemas operacionais. Preparei este artigo inteiro apenas usando software de código aberto. Havia análogos do Word e do Photoshop e até um driver para a impressora. A primeira vez na minha vida isso aconteceu. Verificou-se que as versões modernas do Linux OS e dos aplicativos podem ser muito convenientes, mesmo para quem usa o Microsoft OS há mais de 25 anos.

PS Se alguém souber executar corretamente a API de detecção de objeto
para Tensorflow versão 2 e superior, cancele a inscrição em PM ou em um comentário.

Tenha um bom dia e boa saúde!

All Articles