adicionado ia de deteccao de objetos ao visual worker

This commit is contained in:
Diego Freitas 2025-08-15 16:03:05 -03:00
parent c43e1daab8
commit 6853d3f264
16 changed files with 418 additions and 50 deletions

View File

@ -7,9 +7,10 @@ from shared.enums import StatusModulo, T_Code
from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey
class CameraOak:
def __init__(self, mostrar_log, mx_id, modelo_ia_onboard=None):
def __init__(self, mostrar_log, mx_id, modelo_ia_seg=None, modelo_ia_det=None):
self.mostrar_log = mostrar_log
self.modelo_ia_onboard = modelo_ia_onboard
self.modelo_ia_seg = modelo_ia_seg
self.modelo_ia_det = modelo_ia_det
disp_list = dai.Device.getAllAvailableDevices()
disp_info = next((d for d in disp_list if d.getMxId() == mx_id), None)
@ -81,8 +82,11 @@ class CameraOak:
self.q_imu = self.device.getOutputQueue(name="imu", maxSize=50, blocking=False)
self.imu = IMUCamera(self.q_imu, freq=100, angulo_inicial=26.3)
if self.modelo_ia_onboard is not None:
self.q_nn = self.device.getOutputQueue(name="nn", maxSize=1, blocking=False)
if self.modelo_ia_seg is not None:
self.q_seg = self.device.getOutputQueue(name="seg", maxSize=1, blocking=False)
if self.modelo_ia_det is not None:
self.q_det = self.device.getOutputQueue(name="det", maxSize=4, blocking=False)
if self.dispositivo == T_Code.Snr:
dadosSnr = ContextoGlobalRedis.get_operacao().get("Snr", {})
@ -195,18 +199,36 @@ class CameraOak:
except Exception as e:
self.mostrar_log(f"[WARN] Falha ao montar pipeline imu: {e}")
if self.modelo_ia_onboard is not None:
if self.modelo_ia_seg is not None or self.modelo_ia_det is not None:
N_seg = self.modelo_ia_seg["det_every_n"]
N_det = self.modelo_ia_det["det_every_n"]
script = pipeline.create(dai.node.Script)
script.setProcessor(dai.ProcessorType.LEON_CSS)
script.setScript(f"""
from time import monotonic
i = 0
while True:
f = node.io['in'].get()
if i % {N_seg} == 0:
node.io['toSeg'].send(f)
if i % {N_det} == 0:
node.io['toDet'].send(f)
i += 1
""")
cam.video.link(script.inputs['in'])
if self.modelo_ia_seg is not None:
try:
from shared.utils import carregar_labelmap_completo
# Carregar mapa de cores
labelmap_path = self.modelo_ia_onboard["ia_labelmap_path"]
self.cor_para_id, self.colormap_rgb, self.classes, self.ignore_rgb = carregar_labelmap_completo(labelmap_path)
labelmap_path = self.modelo_ia_seg["ia_labelmap_path"]
self.modelo_ia_seg["cor_para_id"], self.modelo_ia_seg["colormap_rgb"], self.modelo_ia_seg["classes"], self.modelo_ia_seg["ignore_rgb"] = carregar_labelmap_completo(labelmap_path)
RESOLUCAO = self.modelo_ia_onboard["ia_resolution"]
ROI_INICIO = self.modelo_ia_onboard["ia_roi_begin"]
ROI_TAMANHO = self.modelo_ia_onboard["ia_roi_size"]
blob_path = self.modelo_ia_onboard["ia_model_path"]
RESOLUCAO = self.modelo_ia_seg["ia_resolution"]
ROI_INICIO = self.modelo_ia_seg["ia_roi_begin"]
ROI_TAMANHO = self.modelo_ia_seg["ia_roi_size"]
blob_path = self.modelo_ia_seg["ia_model_path"]
y1 = 1.0 - (ROI_INICIO + ROI_TAMANHO)
y2 = 1.0 - ROI_INICIO
@ -216,20 +238,66 @@ class CameraOak:
manip.initialConfig.setResize(RESOLUCAO[0], RESOLUCAO[1])
manip.initialConfig.setFrameType(dai.RawImgFrame.Type.RGB888p)
manip.initialConfig.setKeepAspectRatio(False)
cam.video.link(manip.inputImage)
#cam.video.link(manip.inputImage)
nn = pipeline.createNeuralNetwork()
nn.setBlobPath(blob_path)
manip.out.link(nn.input)
xout_nn = pipeline.createXLinkOut()
xout_nn.setStreamName("nn")
xout_nn.setStreamName("seg")
nn.out.link(xout_nn.input)
script.outputs['toSeg'].link(manip.inputImage)
self.mostrar_log("Pipeline de segmentação onboard criado")
except Exception as e:
self.mostrar_log(f"[WARN] Falha ao montar pipeline IA Onboard: {e}")
if self.modelo_ia_det is not None:
try:
RESOLUCAO = self.modelo_ia_det["ia_resolution"]
ROI_INICIO = self.modelo_ia_det["ia_roi_begin"]
ROI_TAMANHO = self.modelo_ia_det["ia_roi_size"]
CONF = self.modelo_ia_det["ia_conf"]
blob_path = self.modelo_ia_det["ia_model_path"]
y1 = 1.0 - (ROI_INICIO + ROI_TAMANHO)
y2 = 1.0 - ROI_INICIO
if blob_path:
manip_det = pipeline.createImageManip()
manip_det.initialConfig.setCropRect(0.0, y1, 1.0, y2)
manip_det.initialConfig.setResize(RESOLUCAO[0], RESOLUCAO[1])
manip_det.initialConfig.setKeepAspectRatio(True)
manip_det.initialConfig.setFrameType(dai.RawImgFrame.Type.RGB888p)
det = pipeline.createMobileNetDetectionNetwork()
det.setBlobPath(blob_path)
det.setConfidenceThreshold(CONF)
det.setNumInferenceThreads(2)
det.input.setBlocking(False)
det.input.setQueueSize(2)
manip_det.out.link(det.input)
xout_det = pipeline.createXLinkOut()
xout_det.setStreamName("det")
det.out.link(xout_det.input)
script.outputs['toDet'].link(manip_det.inputImage)
# (opcional) passthrough para sincronizar timestamp/frame com a detecção
# xout_det_img = pipeline.createXLinkOut()
# xout_det_img.setStreamName("det_img")
# det.passthrough.link(xout_det_img.input)
self.mostrar_log("Pipeline de detecção leve (MobileNet-SSD) criado")
else:
self.mostrar_log("[INFO] Detector não configurado (detector_blob_path ausente). Pulando.")
except Exception as e:
self.mostrar_log(f"[WARN] Falha ao montar pipeline detecção: {e}")
return pipeline
def _set_calib(self):
@ -297,15 +365,15 @@ class CameraOak:
}
def requisitar_segmentacao(self):
if not hasattr(self, "q_nn"):
return None, {"erro": "Segmentação não disponível", "duracao": 0, "frame_valido": False}
if not hasattr(self, "q_seg"):
return None, {"erro": "Segmentacao nao disponivel", "duracao": 0, "frame_valido": False}
start = time.time()
try:
w, h = self.modelo_ia_onboard["ia_resolution"]
in_nn = self.q_nn.get()
out_raw = in_nn.getFirstLayerFp16()
w, h = self.modelo_ia_seg["ia_resolution"]
in_seg = self.q_seg.get()
out_raw = in_seg.getFirstLayerFp16()
arr16 = np.frombuffer(np.asarray(out_raw, dtype=np.float16), dtype=np.float16)
arr16 = arr16.reshape(len(self.classes), h, w)
arr16 = arr16.reshape(len(self.modelo_ia_seg["classes"]), h, w)
pred_ids = arr16.argmax(axis=0).astype(np.uint8, copy=False)
dur = time.time() - start
self.timestamp_ultima_segmentacao = time.time()
@ -314,6 +382,103 @@ class CameraOak:
dur = time.time() - start
return None, {"erro": str(e), "duracao": dur, "frame_valido": False}
def requisitar_deteccao(self, mapear_para_fullframe: bool = False):
"""
uma predição do detector leve (MobileNet-SSD/YOLO).
Retorna (lista_de_deteccoes, meta).
Cada detecção:
{
"label_id": int,
"label": str|None,
"conf": float,
"bbox_norm": [x0, y0, x1, y1], # 0..1, relativo ao input do detector (ROI)
"bbox_px": [x0, y0, x1, y1], # em pixels do input do detector (ex.: 300x300)
"bbox_full": [x0, y0, x1, y1], # opcional, só se mapear_para_fullframe=True e houver ROI/size salvos
"xyz_m": [x,y,z] # opcional, se for SpatialDetectionNetwork
}
"""
if not hasattr(self, "q_det"):
return [], {"erro": "Deteccao não disponivel", "duracao": 0, "frame_valido": False}
# defaults caso você não tenha setado antes
det_W, det_H = self.modelo_ia_det["ia_resolution"]
def _clamp01(v):
return float(min(1.0, max(0.0, v)))
def _map_bbox_to_full(bn):
# precisa: self.det_roi_frac = (rx1, ry1, rx2, ry2) em 0..1 no frame FULL
# self.frame_size = (W_full, H_full)
if not (hasattr(self, "det_roi_frac") and hasattr(self, "frame_size")):
return None
rx1, ry1, rx2, ry2 = self.det_roi_frac
Wf, Hf = self.frame_size
sx = (rx2 - rx1)
sy = (ry2 - ry1)
x0n, y0n, x1n, y1n = bn
fx0 = (rx1 + x0n * sx) * Wf
fy0 = (ry1 + y0n * sy) * Hf
fx1 = (rx1 + x1n * sx) * Wf
fy1 = (ry1 + y1n * sy) * Hf
return [int(round(fx0)), int(round(fy0)), int(round(fx1)), int(round(fy1))]
start = time.time()
try:
pkt = self.q_det.get() # ImgDetections
raw_dets = getattr(pkt, "detections", [])
dets = []
for d in raw_dets:
# normalizados 0..1 (clamp por segurança)
x0n = _clamp01(getattr(d, "xmin", 0.0))
y0n = _clamp01(getattr(d, "ymin", 0.0))
x1n = _clamp01(getattr(d, "xmax", 0.0))
y1n = _clamp01(getattr(d, "ymax", 0.0))
# em pixels do input do detector (ex.: 300x300)
x0p = int(round(x0n * det_W)); y0p = int(round(y0n * det_H))
x1p = int(round(x1n * det_W)); y1p = int(round(y1n * det_H))
label_id = int(getattr(d, "label", -1))
conf = float(getattr(d, "confidence", 0.0))
label = None
labels = self.modelo_ia_det.get("classes", [])
if 0 <= label_id < len(labels):
if label_id != 0: # 0 = background
label = labels[label_id]
else:
label = None
item = {
"label_id": label_id,
"label": label,
"conf": conf,
"bbox_norm": [x0n, y0n, x1n, y1n],
"bbox_px": [x0p, y0p, x1p, y1p],
}
# Se for SpatialDetectionNetwork, adiciona XYZ (em metros)
if hasattr(d, "spatialCoordinates"):
sc = d.spatialCoordinates
item["xyz_m"] = [float(sc.x) / 1000.0, float(sc.y) / 1000.0, float(sc.z) / 1000.0]
# Opcional: mapear para o frame completo (leva em conta ROI da detecção)
if mapear_para_fullframe:
bf = _map_bbox_to_full(item["bbox_norm"])
if bf is not None:
item["bbox_full"] = bf
dets.append(item)
dur = time.time() - start
self.timestamp_ultima_deteccao = time.time()
return dets, {"erro": None, "duracao": dur, "frame_valido": True}
except Exception as e:
dur = time.time() - start
return [], {"erro": str(e), "duracao": dur, "frame_valido": False}
def atualizar_saude(self):
#self.mostrar_log(f"[{self.mx_id}] Atualizando saude {self.dispositivo.name}...")

View File

@ -33,11 +33,13 @@ class CameraManager:
self._ultima_analise_solo = {}
self._ultima_analise_radar = {}
self._ultima_analise_segmentacao = {}
self._ultima_analise_deteccao = {}
self._ultima_analise_matriz_confianca = {}
self._ultima_analise_matriz_custo = {}
self._ultimo_rgb_frame = None
self._ultimo_depth_frame = None
self._ts_segmentacao_anterior = 0
self._ts_deteccao_anterior = 0
self._pool = ThreadPoolExecutor(max_workers=6)
def inicializar(self, mx_id):
@ -56,11 +58,12 @@ class CameraManager:
self.mx_id = mx_id
from visual_worker.config import load_config
camera_config = load_config()
from visual_worker.config import load_seg_config, load_det_config
seg_config = load_seg_config()
det_config = load_det_config()
try:
nova = CameraOak(self.mostrar_log, mx_id, modelo_ia_onboard=camera_config)
nova = CameraOak(self.mostrar_log, mx_id, modelo_ia_seg=seg_config, modelo_ia_det=det_config)
if nova.iniciado:
self.camera = nova
except Exception as e:
@ -78,7 +81,7 @@ class CameraManager:
self.setores_referencia = None
self.anomalias_manager = AnaliseAnomaliasManager()
self.solo_manager = AnaliseSoloManager()
self.segmentacao_manager = SegmentacaoManager(self.camera.colormap_rgb, self.camera.classes)
self.segmentacao_manager = SegmentacaoManager(self.camera.modelo_ia_seg.get("colormap_rgb"), self.camera.modelo_ia_seg.get("classes"))
self.radar_manager = Radar2DManager()
self.data_fuser = CostmapFuser(grid_shape=self.grid_ref_shape, K=3, M=2, fuse_method="q0.7", block_thr=0.7, central_cols=None, y_range_m=(0.5,5.0), near_is_bottom=True, fov_h_rad=np.radians(self.camera.parametros["fov_h"]), robot_width=self.largura_robo_m)
self.operante = True
@ -88,12 +91,16 @@ class CameraManager:
self._ultima_analise_solo = {}
self._ultima_analise_radar = {}
self._ultima_analise_segmentacao = {}
self._ultima_analise_deteccao = {}
self._ultima_analise_matriz_confianca = {}
self._ultima_analise_matriz_custo = {}
self._ts_segmentacao_anterior = 0
self._ts_deteccao_anterior = 0
self._ultimo_rgb_frame = None
self._depth_frame_necessario = True
self._rgb_frame_necessario = True
self._nova_segmentacao_disponivel = False
self._nova_deteccao_disponivel = False
self._nova_grid_conf_disponivel = False
self._analisando_anomalias = False
@ -102,6 +109,7 @@ class CameraManager:
self._analisando_matriz_custo = False
self._analisando_matriz_confianca = False
self._analisando_segmentacao = False
self._analisando_deteccao = False
self._iniciar_loop_analise_continua(15.0)
self.iniciando = False
@ -178,7 +186,6 @@ class CameraManager:
try:
predictions, res = self.camera.requisitar_segmentacao()
if predictions is not None:
self._ultimo_predictions = predictions
return predictions, self.camera.timestamp_ultima_segmentacao, res
elif "X_LINK_ERROR" in res["erro"]:
self.reiniciar_status()
@ -189,6 +196,23 @@ class CameraManager:
return None, None, None
def get_detections(self):
if self.camera is None:
return None, None, None
try:
detections, res = self.camera.requisitar_deteccao()
if detections is not None:
return detections, self.camera.timestamp_ultima_deteccao, res
elif "X_LINK_ERROR" in res["erro"]:
self.reiniciar_status()
except Exception as e:
self.mostrar_log("Erro ao requisitar detections:", e)
if "X_LINK_ERROR" in str(e):
self.reiniciar_status()
return None, None, None
def get_select_frame(self, tipo: CameraFrameType):
f = None
t = None
@ -273,18 +297,18 @@ class CameraManager:
def _realizar_analises(self):
self._analise_segmentacao()
if self._depth_frame_necessario:
depth_frame_np, depth_timestamp, depth_res = self.get_depth_frame()
else:
depth_frame_np = self._ultimo_depth_frame
self._analise_segmentacao()
parametros_camera = self.camera.parametros
fov_h = parametros_camera["fov_h"]
distancia_max_m = parametros_camera["distancia_maxima"] / 1000.0
self._analise_matriz_confianca(depth_frame_np, distancia_max_m, fov_h)
#key, vis = self.debug_show_costmap(rgb_frame=self._ultimo_rgb_frame, grid_dict=self._ultima_analise_matriz_confianca, grid_shape=self.grid_ref_shape, window_name="viz MPC", wait=1, text_mode="mini")
#key, vis = self.debug_show_visualworker(frame_bgr=self._ultimo_rgb_frame, grid=self._ultima_analise_matriz_confianca, wait=1, text_mode="full", draw_grid=True, draw_cells=True, draw_legend=True)
self.segmentacao_manager.display_segmentation_debug(self._ultimo_rgb_frame, 150)
self._analise_deteccao()
def _realizar_analises_async(self):
executor = self._pool
@ -351,6 +375,12 @@ class CameraManager:
)
self._nova_segmentacao_disponivel = True
from visual_worker.config import load_seg_config
if load_seg_config().get("debug_visual", False):
#key, vis = self.debug_show_costmap(rgb_frame=self._ultimo_rgb_frame, grid_dict=self._ultima_analise_matriz_confianca, grid_shape=self.grid_ref_shape, window_name="viz MPC", wait=1, text_mode="mini")
#key, vis = self.debug_show_visualworker(frame_bgr=self._ultimo_rgb_frame, grid=self._ultima_analise_matriz_confianca, wait=1, text_mode="full", draw_grid=True, draw_cells=True, draw_legend=True)
self.segmentacao_manager.display_segmentation_debug(self._ultimo_rgb_frame, 150)
# Enviar comando para atualizar os dados de controle sempre que um novo dado de segmentacao seja processado e a operacao seja do tipo MapeamentoVisual
#op_modo = ContextoGlobalRedis.get_operacao().get("modo", ModoOperacao.NaoDefinido.value)
#movimento_automatico = ContextoGlobalRedis.get_controle().get("movimento_automatico", False)
@ -375,7 +405,7 @@ class CameraManager:
t0 = time.time()
#grid_conf = self._gerar_grid_confianca(depth_frame_np, segmentacao, dist_max)
grid_conf = self._construir_grid_confianca(depth_frame_np, segmentacao, self.grid_ref, self.grid_ref_shape, self.camera.classes)
grid_conf = self._construir_grid_confianca(depth_frame_np, segmentacao, self.grid_ref, self.grid_ref_shape, self.camera.modelo_ia_seg.get("classes"))
#self.mostrar_log(grid_conf)
t1 = time.time()
grid_conf["ultima_chamada"] = self._ultima_analise_matriz_confianca.get("ultima_chamada", t0)
@ -401,6 +431,38 @@ class CameraManager:
self._analisando_matriz_confianca = False
#self.mostrar_log("Matriz de confianca concluida")
def _analise_deteccao(self):
if self._analisando_deteccao or self.camera.modelo_ia_det is None: return
self._analisando_deteccao = True
try:
t0 = time.time()
dets, ts, meta = self.get_detections()
if ts == self._ts_deteccao_anterior: return
self._ts_deteccao_anterior = ts
if dets is not None:
t1 = time.time()
analise_deteccoes = {
"bboxes": dets
}
self._calcular_performance(t0, t1, analise_deteccoes)
self._ultima_analise_deteccao = analise_deteccoes
ContextoGlobalRedis.atualizar_ctx_dict(
CtxKey.DadosVisualWorker,
ts_analise=t1,
deteccao=converter_valores_numpy(dets)
)
self._nova_deteccao_disponivel = True
from visual_worker.config import load_det_config
if load_det_config().get("debug_visual", False):
self._overlay_deteccoes(self._ultimo_rgb_frame, dets)
except Exception as e:
self.mostrar_log(f"❌ Erro na deteccao de objetos: {e}")
finally:
self._analisando_deteccao = False
#self.mostrar_log(f"Deteccao concluida em {self._ultima_analise_deteccao['latencia']:.4f} s, a {fps:.4f} FPS")
def _analise_anomalias(self, grid_conf, limiar_delta, limiar_conf, dist_max, largura_min, altura_min):
if self._analisando_anomalias:
return
@ -1400,3 +1462,121 @@ class CameraManager:
cv2.waitKey(1)
return vis, metrics
def _overlay_deteccoes(
self,
rgb_frame,
dets,
conf_thr=0.5, # limiar de confiança pra desenhar
roi_frac=None, # (rx1,ry1,rx2,ry2) normalizado da ROI usada no detector (ex.: (0.0,y1,1.0,y2))
show=True, # se True, faz cv2.imshow
janela="det", # nome da janela
fps_state=None, # dict estado do FPS (persistido fora), ex.: {}
):
"""
dets: lista de dicts no formato:
{
"label_id": int,
"label": str|None,
"conf": float,
"bbox_norm": [x0,y0,x1,y1] # 0..1 relativo ao input do detector (na ROI)
# opcional: "bbox_full": [x0,y0,x1,y1] em px do frame completo
}
Retorna: (frame_com_overlay, fps_state, keep_loop_bool)
"""
img = cv2.resize(rgb_frame.copy(), (1280, 720))
H, W = img.shape[:2]
# paleta simples por classe
palette = [
(255, 56, 56), (255, 157, 151), (72, 249, 10), (0, 255, 0), (0, 0, 255),
(255, 0, 255), (0, 255, 255), (255, 191, 0), (52, 148, 230), (147, 112, 219)
]
def _map_bbox_norm_to_full(bn):
# bn é [x0n,y0n,x1n,y1n] relativo ao input da ROI (0..1)
x0n, y0n, x1n, y1n = bn
if roi_frac is not None:
rx1, ry1, rx2, ry2 = roi_frac
sx, sy = (rx2 - rx1), (ry2 - ry1)
x0 = int(round((rx1 + x0n * sx) * W))
y0 = int(round((ry1 + y0n * sy) * H))
x1 = int(round((rx1 + x1n * sx) * W))
y1 = int(round((ry1 + y1n * sy) * H))
else:
x0 = int(round(x0n * W))
y0 = int(round(y0n * H))
x1 = int(round(x1n * W))
y1 = int(round(y1n * H))
# clamp
x0 = max(0, min(W - 1, x0)); x1 = max(0, min(W - 1, x1))
y0 = max(0, min(H - 1, y0)); y1 = max(0, min(H - 1, y1))
return x0, y0, x1, y1
def _put_label(img, text, x, y, bg):
(tw, th), _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
cv2.rectangle(img, (x, max(0, y - th - 6)), (x + tw + 6, y), bg, -1)
cv2.putText(img, text, (x + 3, y - 4), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)
# desenhar ROI (opcional, ajuda debug)
if roi_frac is not None:
rx1, ry1, rx2, ry2 = roi_frac
x0r, y0r = int(rx1 * W), int(ry1 * H)
x1r, y1r = int(rx2 * W), int(ry2 * H)
cv2.rectangle(img, (x0r, y0r), (x1r, y1r), (60, 60, 60), 1)
# desenhar detecções
for d in dets:
if d.get("conf", 0.0) < conf_thr:
continue
# bbox em px do frame
if "bbox_full" in d and d["bbox_full"]:
x0, y0, x1, y1 = d["bbox_full"]
# clamp se necessário
x0 = max(0, min(W - 1, int(x0))); x1 = max(0, min(W - 1, int(x1)))
y0 = max(0, min(H - 1, int(y0))); y1 = max(0, min(H - 1, int(y1)))
else:
bn = d.get("bbox_norm", None)
if not bn:
continue
x0, y0, x1, y1 = _map_bbox_norm_to_full(bn)
if x1 <= x0 or y1 <= y0:
continue
lid = int(d.get("label_id", -1))
color = palette[lid % len(palette)] if lid >= 0 else (0, 255, 0)
cv2.rectangle(img, (x0, y0), (x1, y1), color, 2)
name = d.get("label", None)
txt = f"{name or f'id:{lid}'} {d.get('conf', 0.0):.2f}"
_put_label(img, txt, x0, y0, color)
# FPS (EMA)
now = time.monotonic()
if fps_state is None:
fps_state = {}
t_prev = fps_state.get("t_prev")
fps_ema = fps_state.get("fps_ema")
if t_prev is not None:
dt = now - t_prev
if dt > 0:
fps_inst = 1.0 / dt
alpha = 0.90
fps_ema = fps_inst if fps_ema is None else (alpha * fps_ema + (1 - alpha) * fps_inst)
fps_state["t_prev"] = now
fps_state["fps_ema"] = fps_ema
if fps_ema:
cv2.putText(img, f"FPS: {fps_ema:.1f}", (10, 22), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (50, 220, 50), 2, cv2.LINE_AA)
keep = True
if show:
cv2.imshow(janela, img)
k = cv2.waitKey(1) & 0xFF
keep = (k != 27) # ESC para sair
return img, fps_state, keep

View File

@ -37,7 +37,7 @@ _CONFIG_CACHE = None
_CONFIG_MTIME = None
_CONFIG_LOCK = threading.Lock()
def load_config(force_reload=False):
def load_seg_config(force_reload=False):
global _CONFIG_CACHE, _CONFIG_MTIME
with _CONFIG_LOCK:
#try:
@ -72,15 +72,36 @@ def load_config(force_reload=False):
# "kernel_morf": 3
# }
_CONFIG_CACHE = {
"debug_visual": True,
"debug_visual": False,
"ia_roi_begin": 0.0,
"ia_roi_size": 1.0,
"ia_resolution": [512,288]
"ia_resolution": [512,288],
"det_every_n": 1,
}
_CONFIG_CACHE["ia_model_path"] = ContextoGlobalRedis.get_equipamento().get("path_ia_model_ruas", "C:/AgroBaseModels/Ruas/model-1_1.blob")
_CONFIG_CACHE["ia_labelmap_path"] = ContextoGlobalRedis.get_equipamento().get("path_ia_labelmap_ruas", "C:/AgroBaseModels/Ruas/model-1_1.txt")
return _CONFIG_CACHE
def reload_config():
return load_config(force_reload=True)
def reload_seg_config():
return load_seg_config(force_reload=True)
def load_det_config():
_CONFIG_DET = {
"debug_visual": False,
"ia_roi_begin": 0.0,
"ia_roi_size": 1.0,
"ia_resolution": [300,300],
"det_every_n": 3,
"ia_conf": 0.5,
"ia_model_path": "C:\\AgroBaseModels\\Ruas\\det_3.blob",
"classes": [
"background",
"aeroplane","bicycle","bird","boat","bottle",
"bus","car","cat","chair","cow",
"diningtable","dog","horse","motorbike","person",
"pottedplant","sheep","sofa","train","tvmonitor",
]
}
return _CONFIG_DET

View File

@ -15,8 +15,8 @@ class ClassesSegmentacao(IntEnum):
class SegmentacaoManager:
def __init__(self, color_map, classes):
from visual_worker.config import load_config
config = load_config()
from visual_worker.config import load_seg_config
config = load_seg_config()
resolucao = config.get("ia_resolution")
self.color_map = color_map
self.classes = classes

View File

@ -42,8 +42,8 @@ class CameraManager:
self.mx_id = mx_id
from weed_worker.config import load_config
camera_config = load_config()
from weed_worker.config import load_seg_config
camera_config = load_seg_config()
try:
nova = CameraOak(self.mostrar_log, mx_id, modelo_ia_onboard=camera_config)
@ -62,7 +62,7 @@ class CameraManager:
self._ultimo_rgb_frame = None
self._ultimo_predictions = None
self.weed_detector = WeedDetector(self.camera.colormap_rgb, self.camera.classes)
self.weed_detector = WeedDetector(self.camera.modelo_ia_seg.get("colormap_rgb"), self.camera.modelo_ia_seg.get("classes"))
self._iniciar_loop_analise_continua(20.0)
self.iniciando = False

View File

@ -39,7 +39,7 @@ _CONFIG_CACHE = None
_CONFIG_MTIME = None
_CONFIG_LOCK = threading.Lock()
def load_config(force_reload=False):
def load_seg_config(force_reload=False):
global _CONFIG_CACHE, _CONFIG_MTIME
with _CONFIG_LOCK:
#try:
@ -104,5 +104,5 @@ def load_config(force_reload=False):
_CONFIG_CACHE["faixa_atuacao_bicos"] = dadosAtu.get("percent_vertical_deteccao", 0.3)
return _CONFIG_CACHE
def reload_config():
return load_config(force_reload=True)
def reload_seg_config():
return load_seg_config(force_reload=True)

View File

@ -12,8 +12,8 @@ class ClassesSegmentacao(IntEnum):
class WeedDetector:
def __init__(self, color_map, classes):
from weed_worker.config import load_config
config = load_config()
from weed_worker.config import load_seg_config
config = load_seg_config()
resolucao = config.get("ia_resolution")
self.color_map = color_map
self.classes = classes
@ -40,8 +40,8 @@ class WeedDetector:
self._seg_fps_ema = None # opcional: chame quando terminar a segmentação
def _reiniciar_deteccoes(self):
from weed_worker.config import load_config
config = load_config()
from weed_worker.config import load_seg_config
config = load_seg_config()
qtd_bicos = config.get("qtd_bicos")
self.ervas_ativas_radar = []
self.ervas_ativas_filtradas = []
@ -99,8 +99,8 @@ class WeedDetector:
print("[Erro] Máscara de classes não encontrada no resultado")
return None
from weed_worker.config import load_config
config = load_config()
from weed_worker.config import load_seg_config
config = load_seg_config()
# vel_norm pode vir do contexto (0..1 da sua Vmax). Se não tiver, manda 0.0
vel_norm = float(config.get("velocidade_robo", 0.0))

View File

@ -11,6 +11,7 @@ MODELO = config["camera"]
MODEL_NAME = config["model_name"]
RESOLUCAO = config["resolucao"]
MAIN_CLASS_NAME = config["main_class_name"]
N_SHAVES = config["shaves"]
use_main_class = config["use_main_class"]
model_path = os.path.join(MODELO, "backup", config["modelo"], MODEL_NAME)
labelmap_path = os.path.join(MODELO, "dataset", "labelmap.txt")
@ -55,7 +56,7 @@ blob_path = blobconverter.from_openvino(
xml=os.path.join(model_path, model_name + ".xml"),
bin=os.path.join(model_path, model_name + ".bin"),
data_type="FP16",
shaves=6,
shaves=N_SHAVES,
output_dir=model_path,
#compile_params=[
# "-ip U8", # entrada em bytes; compila a conversão interna p/ FP16

View File

@ -6,5 +6,6 @@
"use_main_class": false,
"resolucao": [512, 288],
"roi_inicio": 0.0,
"roi_tamanho": 1.0
"roi_tamanho": 1.0,
"shaves": 3
}