Integração da Inteligência Artificial
Conforme descrito na proposta de solução, o sistema desenvolvido pela equipe SugarZ3ro conta com uma análise de imagens feita por IA (Inteligência Artificial). De maneira mais específica, o robô utilizado pela equipe recebeu uma câmera acoplada, a qual será responsável por captar imagens em tempo real dos canos dos reboilers contidos nas usinas da Atvos. A IA, como dito na seção referente, terá a função de analisar as imagens dos canos captadas e determinar, através de uma rede neural pré-treinada com YOLO, se o cano da imagem está sujo ou não.
Para que essa funcionalidade se adequasse à necessidade da empresa parceira e ao contexto dos usuários finais do protótipo, este modelo de IA desenvolvido na sprint 4 foi integrado à interface de usuário na sprint 5. Desse modo, o usuário pode ativar a detecção de impurezas a qualquer momento apertando o respectivo botão na tela de teloperação.
Para realizar a integração, foram desenvolvidos codigos nos seguintes arquivos: app.py
, camera.jsx
, aiButton.jsx
.
No arquivo app.py
foi configurado o caminho para o banco de dados TinyDB e cria a tabela pipes
para armazenar os dados recebidos.
db_path = os.path.join(os.path.dirname(__file__), '../data-base/pipes.json')
db = TinyDB(db_path)
pipes_table = db.table('pipes')
Pipes = Query()
Variáveis Globais
imgStringBase64 = None
model = YOLO('./best.pt')
- Define variáveis globais para armazenar a imagem recebida em base64 e o modelo de IA YOLO para processamento das imagens.
Dados Atualizados
updated_data = {
'id': 0,
'status': None,
'id-reboiler': None,
'datetime': None
}
- Dicionário para armazenar os dados atualizados que serão salvos no banco de dados.
Rotas
Rota para Receber ID do Reboiler
@app.route('/post_reboiler_id', methods=['POST', 'GET'])
def post_reboiler_id():
data = request.get_json()
reboiler_id = data.get('reboilerID')
updated_data['id-reboiler'] = reboiler_id
print(f"Id recebido para o reboiler atual: {updated_data['id-reboiler']}")
return jsonify({"reboilerID": reboiler_id}), 200
- Esta rota recebe o ID do reboiler inserido pelo usuário no frontend e o armazena na variável updated_data.
Rota para Receber a Imagem do Frame
@app.route('/post_img_string', methods=['POST', 'GET'])
@cross_origin() # Adiciona CORS para esta rota específica
def post_img_string():
global imgStringBase64
if request.method == 'POST':
data = request.get_json()
imgStringBase64 = data.get('currentFrame')
print(f"imagem convertida")
# converte a string da img em base64 p/ variável legível pro opencv
decoded_data = base64.b64decode(imgStringBase64)
np_data = np.fromstring(decoded_data, np.uint8)
img = cv2.imdecode(np_data, cv2.IMREAD_COLOR)
results = model(img)
updated_data['id'] += 1
updated_data['datetime'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
for result in results:
updated_data['status'] = False
# se mais de 0 sujeiras forem detectadas no frame
if len(result.boxes.cls) > 0:
updated_data['status'] = True
pipes_table.insert(updated_data)
return jsonify({"message": "Imagem recebida com sucesso"}), 200
return jsonify({"imgStringBase64": imgStringBase64}), 200
- Esta rota recebe uma imagem do frame atual capturado pelo usuário, convertida em uma string base64, e a processa usando o modelo YOLO. A imagem é decodificada e convertida para um formato legível pelo OpenCV. O modelo de IA processa a imagem e atualiza o status de acordo com a presença de sujeira detectada no frame. Os dados são então inseridos no banco de dados TinyDB.
Estas rotas são uteis para monitoramento em tempo real de reboilers, utilizando IA para detectar sujeiras em frames capturados, e armazenando todas as informações relevantes para análises futuras.
Componente camera.jsx
O trecho do codigo a seguir em JavaScript é parte de um componente React que usa o hook useEffect
para monitorar e enviar uma imagem capturada quando um botão de IA é pressionado. O código também gerencia o estado para evitar envios duplicados de imagens.
Importação do Hook useEffect
useEffect(() => {
if (aiButtonState && currentFrame && !hasSentImageString) {
console.log('botao apertado'); // Log the currentFrame
O useEffect
é utilizado para executar efeitos colaterais em componentes funcionais. Neste caso, ele monitora as mudanças no estado do botão de IA (aiButtonState
), no frame atual (currentFrame
), e na flag (hasSentImageString
) que indica se a imagem já foi enviada. Se o botão de IA estiver pressionado, existir um frame atual, e a imagem ainda não tiver sido enviada, ele executa o bloco de código dentro do if
.
Envio da Imagem para o Backend
fetch('http://127.0.0.1:5000/post_img_string', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ currentFrame: currentFrame }),
})
Aqui, o código faz uma requisição POST
para o endpoint do backend (http://127.0.0.1:5000/post_img_string
), enviando o frame atual convertido para uma string JSON no corpo da requisição. Os cabeçalhos especificam que o conteúdo é do tipo JSON.
Atualização do Estado para Evitar Envios Duplicados
setHasSentImageString(true); // Mark that the frame has been logged
Após enviar a imagem, o código atualiza a flag hasSentImageString
para true, evitando que a mesma imagem seja enviada novamente enquanto o botão de IA permanece pressionado.
De forma resumida, esse trecho de código tem as seguintes funções:
- Monitoramento do Estado: O
useEffect
monitora os estados do botão de IA, do frame atual, e da flag de envio. - Envio da Imagem: Quando o botão de IA é pressionado, existe um frame atual e a imagem ainda não foi enviada, a imagem é enviada para o backend.
- Evitar Envios Duplicados: A flag hasSentImageString é atualizada para true após o envio da imagem, evitando envios duplicados.
- Reset da Flag: Quando o botão de IA não está pressionado, a flag é redefinida para false, permitindo novos envios na próxima vez que o botão for pressionado.
Este código assegura que a imagem do frame atual seja enviada de forma eficiente e controlada ao backend sempre que o usuário interagir com o botão de IA.
Componente aiButton.jsx
O trecho de código a seguir define um componente React chamado aiButton
, que é um botão interativo utilizado para controlar o estado do envio de imagens processadas para o backend. Abaixo está uma explicação detalhada de como este componente se relaciona com os códigos anteriores do arquivo camera.jsx e do backend em Flask.
Função de Manipulação de Clique
const handleClick = () => {
const newState = !buttonState;
setButtonState(newState);
if (typeof onButtonStateChange === 'function') {
onButtonStateChange(newState);
}
}
A função handleClick alterna o estado do botão entre true e false sempre que o botão é clicado. Após atualizar o estado, verifica se a prop onButtonStateChange
é uma função e, se for, chama essa função passando o novo estado do botão.
No arquivo camera.jsx
, o useEffect
monitora o estado do botão de IA (aiButtonState
). O componente aiButton
altera este estado através da prop onButtonStateChange
. Quando o botão é clicado, handleClick
muda o estado de buttonState e chama onButtonStateChange
, passando o novo estado.
O backend em Flask possui a rota /post_img_string
para receber a imagem do frame atual. Quando o botão AiButton é pressionado, o estado aiButtonState muda para true, desencadeando o envio da imagem pelo useEffect
em camera.jsx
.
A rota Flask /post_img_string
recebe a imagem enviada pelo frontend e a processa utilizando o modelo YOLO. A interação entre o frontend (React) e o backend (Flask) é facilitada pelo componente aiButton
, que controla quando as imagens são enviadas.
Demonstração
A seguir, na figura 1, pode-se verificar uma imagem de exemplo capturada com a câmera acoplada ao robô e analisada a partir do modelo desenvolvido pela equipe.
Figura 1 - Detecção de impurezas em simulação do cano
Fonte: Elaborado pela equipe SugarZ3ro
Tal imagem refere-se à fotografia de uma lata de lixo preta com bolas papel coladas em seu interior, de forma a simular um cano de um reboiler. Na figura, é possível notar quadrados coloridos com palavras e números inscritos em seus cantos superiores direitos. Cada um desses nomes representa um elemento de sujeira diferente detectado, o que também se relaciona com o número registrado em cada quadrado, que representa a precisão de cada detecção destes elementos.
Conclusão
Esta integração assegura que as imagens capturadas sejam enviadas de forma controlada e eficiente, acionando a lógica de backend para processamento de imagens apenas quando necessário.