agrobot_base/Python/OAK/OAK-D-Lite_depthData.py

190 lines
7.1 KiB
Python
Raw Permalink Normal View History

2025-02-21 19:50:54 +00:00
import depthai as dai
import cv2
import numpy as np
import time
import json
import sys
import threading
import paho.mqtt.client as mqtt
import uuid
2025-03-05 10:34:43 +00:00
from flask import Flask, Response, request
2025-02-21 19:50:54 +00:00
# 🔹 Configurações MQTT
mqtt_client = mqtt.Client(f"client_oak_d_lite_{uuid.uuid4()}")
mqtt_client.connect("localhost", port=1883)
# 🔹 Parâmetros de entrada
output_folder = 'Python/Output/'
mqtt_topic = sys.argv[1] # Tópico MQTT para envio dos dados de profundidade
porta = int(sys.argv[2]) # Porta do Flask
url = sys.argv[3] # URL do vídeo
2025-03-05 10:34:43 +00:00
max_readings = int(sys.argv[4])
2025-02-21 19:50:54 +00:00
# 🔹 Flask App
app = Flask(__name__)
# 🔹 Criando o pipeline
pipeline = dai.Pipeline()
2025-03-05 10:34:43 +00:00
width, height = 1280, 720
2025-02-21 19:50:54 +00:00
# 📷 Câmera RGB
cam_rgb = pipeline.create(dai.node.ColorCamera)
2025-03-05 10:34:43 +00:00
cam_rgb.setPreviewSize(width, height)
2025-02-21 19:50:54 +00:00
cam_rgb.setBoardSocket(dai.CameraBoardSocket.RGB)
cam_rgb.setInterleaved(False)
# Criar XLinkOut para saída RGB
xout_rgb = pipeline.create(dai.node.XLinkOut)
xout_rgb.setStreamName("rgb")
cam_rgb.preview.link(xout_rgb.input)
# 🔹 Câmera de Profundidade
mono_left = pipeline.create(dai.node.MonoCamera)
mono_right = pipeline.create(dai.node.MonoCamera)
stereo = pipeline.create(dai.node.StereoDepth)
mono_left.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
mono_right.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
mono_left.setBoardSocket(dai.CameraBoardSocket.LEFT)
mono_right.setBoardSocket(dai.CameraBoardSocket.RIGHT)
# Configuração do StereoDepth
stereo.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
stereo.setLeftRightCheck(True)
stereo.setSubpixel(True)
mono_left.out.link(stereo.left)
mono_right.out.link(stereo.right)
# Criar XLinkOut para profundidade
xout_depth = pipeline.create(dai.node.XLinkOut)
xout_depth.setStreamName("depth")
stereo.depth.link(xout_depth.input)
2025-03-05 10:34:43 +00:00
# 🔹 Função para enviar vídeo via Flask
def generate_video(camera_index):
# Listar todas as câmeras conectadas
devices = dai.Device.getAllAvailableDevices()
2025-02-21 19:50:54 +00:00
2025-03-05 10:34:43 +00:00
if len(devices) == 0:
print("Nenhuma câmera OAK conectada.")
return
if camera_index >= len(devices):
print(f"Índice da câmera ({camera_index}) inválido. Apenas {len(devices)} câmeras disponíveis.")
return
2025-02-21 19:50:54 +00:00
2025-03-05 10:34:43 +00:00
selected_device_info = devices[camera_index] # Seleciona a câmera correta pelo índice
print(f"Usando câmera: {selected_device_info.name} (ID: {selected_device_info.mxid})")
2025-02-21 19:50:54 +00:00
2025-03-05 10:34:43 +00:00
with dai.Device(pipeline, selected_device_info) as device: # 🔹 Agora usa a câmera correta
rgb_queue = device.getOutputQueue(name="rgb", maxSize=1, blocking=True)
depth_queue = device.getOutputQueue(name="depth", maxSize=1, blocking=True)
2025-02-21 19:50:54 +00:00
2025-03-05 10:34:43 +00:00
readings = []
rgb_frame = None
depth_frame = None
2025-02-21 19:50:54 +00:00
while True:
timestamp = time.time()
2025-03-05 10:34:43 +00:00
# Pega os dois frames ao mesmo tempo, para evitar desincronização
in_rgb = rgb_queue.tryGet()
in_depth = depth_queue.tryGet()
if in_rgb is not None and in_depth is not None:
rgb_frame = in_rgb.getCvFrame()
depth_frame = in_depth.getFrame()
# 🔹 Verifica se depth_frame está vazio antes de processar
if depth_frame is None or depth_frame.size == 0:
print("⚠️ Frame de profundidade inválido. Pulando esta iteração.")
continue
2025-02-21 19:50:54 +00:00
# Normaliza a profundidade para visualização (mapa de calor)
depth_visual = cv2.normalize(depth_frame, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
depth_visual = cv2.applyColorMap(depth_visual, cv2.COLORMAP_JET)
# 📡 Enviar dados via MQTT (Apenas a matriz de profundidade reduzida)
depth_data = depth_frame.tolist() # Converte a matriz para lista JSON
2025-03-05 10:34:43 +00:00
depth_small = cv2.resize(depth_frame, (width // 2, height // 2)) # Reduz para metade
depth_data = depth_small.tolist()
try:
memory_usage = device.getDdrMemoryUsage()
memory_info = {
"remaining": memory_usage.remaining,
"total": memory_usage.total,
"used": memory_usage.used
}
except:
memory_info = None # Se houver erro, define como None
try:
temp = device.getChipTemperature()
temp_info = {
"css": temp.css,
"mss": temp.mss,
"upa": temp.upa,
"dss": temp.dss
}
except:
temp_info = None # Se houver erro, define como None
device_data = {
"id": selected_device_info.getMxId(), # ID do dispositivo
"name": selected_device_info.name, # Nome do dispositivo
"state": selected_device_info.state.name, # Estado do dispositivo
"usb_speed": str(device.getUsbSpeed().name) if hasattr(device, 'getUsbSpeed') else None, # Velocidade USB
"available_camera_sensors": [sensor.name for sensor in device.getConnectedCameras()], # Sensores de câmera disponíveis
"version": str(device.getDeviceInfo().protocol) if hasattr(device, 'getDeviceInfo') else None, # Versão do protocolo
"memory_usage": memory_info, # Uso de memória DDR
"temperature": temp_info, # Temperatura do chip
"bootloader_version": str(device.getBootloaderVersion()) if hasattr(device, 'getBootloaderVersion') else None, # Bootloader
"is_pipeline_running": device.isPipelineRunning() if hasattr(device, 'isPipelineRunning') else None # Pipeline rodando?
}
2025-02-21 19:50:54 +00:00
json_data = {
'timestamp': timestamp,
2025-03-05 10:34:43 +00:00
'device_data': device_data,
'x_max': width,
'y_max': height,
'depth_data': depth_data,
2025-02-21 19:50:54 +00:00
}
2025-03-05 10:34:43 +00:00
readings.append(json_data)
# Enviar apenas a cada max_readings capturas
if len(readings) >= max_readings:
mensagem_relevante = readings[-1]
mqtt_client.publish(mqtt_topic, json.dumps(mensagem_relevante).encode('utf-8'))
readings.clear()
frame = rgb_frame.getCvFrame()
ret, buffer = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 80]) # Reduz qualidade para 80%
2025-02-21 19:50:54 +00:00
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
2025-03-05 10:34:43 +00:00
def send_script_ready():
mqtt_client.publish(mqtt_topic, "OK")
def run_flask_server():
app.run(host='0.0.0.0', port=porta, threaded=True, debug=False)
2025-02-21 19:50:54 +00:00
@app.route('/' + url, methods=['GET'])
def video_feed():
2025-03-05 10:34:43 +00:00
camera_index = int(request.args.get('camera_index'))
return Response(generate_video(camera_index), mimetype='multipart/x-mixed-replace; boundary=frame')
2025-02-21 19:50:54 +00:00
if __name__ == '__main__':
2025-03-05 10:34:43 +00:00
mqtt_thread = threading.Thread(target=send_script_ready)
mqtt_thread.start()
run_flask_server()