ajsutado salvamento para pós processamento
This commit is contained in:
parent
3b15a2473c
commit
405903d5da
|
|
@ -105,6 +105,11 @@ class CameraManager:
|
||||||
self.perf = VisualPerfMonitor(janela=180)
|
self.perf = VisualPerfMonitor(janela=180)
|
||||||
self.gpu_controller = None
|
self.gpu_controller = None
|
||||||
|
|
||||||
|
self._ultimo_posproc_save_ts = 0.0
|
||||||
|
self._posproc_save_lock = threading.Lock()
|
||||||
|
self._posproc_salvando = False
|
||||||
|
self.posproc_intervalo_min_s = 5.0
|
||||||
|
|
||||||
self._reset_runtime_state()
|
self._reset_runtime_state()
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
@ -197,6 +202,8 @@ class CameraManager:
|
||||||
self.seg_config = load_seg_config()
|
self.seg_config = load_seg_config()
|
||||||
self.det_config = load_det_config()
|
self.det_config = load_det_config()
|
||||||
|
|
||||||
|
self.posproc_intervalo_min_s = float(self.seg_config.get("posproc_intervalo_min_s", 5.0))
|
||||||
|
|
||||||
self.debug_visual = bool(self.seg_config.get("debug_visual", False))
|
self.debug_visual = bool(self.seg_config.get("debug_visual", False))
|
||||||
self.debug_perf = bool(self.seg_config.get("debug_perf", False))
|
self.debug_perf = bool(self.seg_config.get("debug_perf", False))
|
||||||
|
|
||||||
|
|
@ -1252,6 +1259,8 @@ class CameraManager:
|
||||||
if agora - self._ultimo_perf_publish >= 1.0:
|
if agora - self._ultimo_perf_publish >= 1.0:
|
||||||
self._ultimo_perf_publish = agora
|
self._ultimo_perf_publish = agora
|
||||||
|
|
||||||
|
self._atualizar_config_dinamica_visual(intervalo_s=1.0)
|
||||||
|
|
||||||
ctrl = self.gpu_controller
|
ctrl = self.gpu_controller
|
||||||
if ctrl is not None:
|
if ctrl is not None:
|
||||||
ctrl.update_from_redis()
|
ctrl.update_from_redis()
|
||||||
|
|
@ -1291,6 +1300,33 @@ class CameraManager:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.mostrar_log(f"[saude] erro: {e}")
|
self.mostrar_log(f"[saude] erro: {e}")
|
||||||
|
|
||||||
|
def _atualizar_config_dinamica_visual(self, intervalo_s=1.0):
|
||||||
|
agora = time.time()
|
||||||
|
|
||||||
|
if not hasattr(self, "_ultimo_config_update_ts"):
|
||||||
|
self._ultimo_config_update_ts = 0.0
|
||||||
|
|
||||||
|
if (agora - self._ultimo_config_update_ts) < intervalo_s:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
from visual_worker.config import load_seg_config
|
||||||
|
|
||||||
|
cfg = load_seg_config() or {}
|
||||||
|
self.seg_config = cfg
|
||||||
|
|
||||||
|
self.debug_visual = bool(cfg.get("debug_visual", self.debug_visual))
|
||||||
|
self.debug_perf = bool(cfg.get("debug_perf", self.debug_perf))
|
||||||
|
|
||||||
|
self.posproc_intervalo_min_s = float(
|
||||||
|
cfg.get("posproc_intervalo_min_s", self.posproc_intervalo_min_s)
|
||||||
|
)
|
||||||
|
|
||||||
|
self._ultimo_config_update_ts = agora
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.mostrar_log(f"[visual] erro ao atualizar config dinâmica: {e}")
|
||||||
|
|
||||||
def _verificar_desconexao_camera(self):
|
def _verificar_desconexao_camera(self):
|
||||||
if self.iniciando or self._em_warmup or time.time() < self._startup_grace_until:
|
if self.iniciando or self._em_warmup or time.time() < self._startup_grace_until:
|
||||||
return
|
return
|
||||||
|
|
@ -1441,7 +1477,6 @@ class CameraManager:
|
||||||
frame_name = nome.strip() if nome else datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3]
|
frame_name = nome.strip() if nome else datetime.datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3]
|
||||||
|
|
||||||
replay_jpeg_quality = 70
|
replay_jpeg_quality = 70
|
||||||
pos_jpeg_quality = 100
|
|
||||||
|
|
||||||
for frame_type in tipos:
|
for frame_type in tipos:
|
||||||
try:
|
try:
|
||||||
|
|
@ -1463,13 +1498,48 @@ class CameraManager:
|
||||||
# No Visual Worker, o dado científico é só a imagem limpa.
|
# No Visual Worker, o dado científico é só a imagem limpa.
|
||||||
# Salva com qualidade máxima.
|
# Salva com qualidade máxima.
|
||||||
if tipo_enum == TipoFrameCamera.PosProcessamento:
|
if tipo_enum == TipoFrameCamera.PosProcessamento:
|
||||||
caminho = os.path.join(pasta, f"{nome_base}.png")
|
pode_salvar, motivo = self._pode_salvar_posprocessamento()
|
||||||
|
|
||||||
ok = cv2.imwrite(caminho, frame)
|
if not pode_salvar:
|
||||||
|
self.mostrar_log(
|
||||||
|
f"[visual][SAVE_PP] pulado | motivo={motivo} "
|
||||||
|
f"intervalo_min={self.posproc_intervalo_min_s:.1f}s "
|
||||||
|
f"nome={nome_base}"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
if ok:
|
frame_pp = frame.copy()
|
||||||
frames_salvos.append(caminho)
|
|
||||||
|
|
||||||
|
def salvar_pp_async(nome_base_async, pasta_async, frame_async):
|
||||||
|
try:
|
||||||
|
t_pp0 = time.perf_counter()
|
||||||
|
|
||||||
|
caminho = os.path.join(pasta_async, f"{nome_base_async}.png")
|
||||||
|
|
||||||
|
ok = cv2.imwrite(caminho, frame_async)
|
||||||
|
|
||||||
|
t_pp1 = time.perf_counter()
|
||||||
|
|
||||||
|
self.mostrar_log(
|
||||||
|
f"[visual][SAVE_PP] salvo async | "
|
||||||
|
f"nome={nome_base_async} "
|
||||||
|
f"ok={ok} "
|
||||||
|
f"tempo_ms={(t_pp1 - t_pp0) * 1000.0:.1f}"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.mostrar_log(f"❌ Erro no visual SAVE_PP async: {e}")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self._finalizar_salvamento_posprocessamento()
|
||||||
|
|
||||||
|
threading.Thread(
|
||||||
|
target=salvar_pp_async,
|
||||||
|
args=(nome_base, pasta, frame_pp),
|
||||||
|
daemon=True
|
||||||
|
).start()
|
||||||
|
|
||||||
|
frames_salvos.append(f"ASYNC_STARTED:{nome_base}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# ====================================================
|
# ====================================================
|
||||||
|
|
@ -1493,6 +1563,26 @@ class CameraManager:
|
||||||
self.mostrar_log(f"❌ Erro ao salvar frames visual: {e}")
|
self.mostrar_log(f"❌ Erro ao salvar frames visual: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def _pode_salvar_posprocessamento(self):
|
||||||
|
agora = time.time()
|
||||||
|
|
||||||
|
with self._posproc_save_lock:
|
||||||
|
if self._posproc_salvando:
|
||||||
|
return False, "busy"
|
||||||
|
|
||||||
|
dt = agora - self._ultimo_posproc_save_ts
|
||||||
|
if dt < self.posproc_intervalo_min_s:
|
||||||
|
return False, f"cooldown_{dt:.2f}s"
|
||||||
|
|
||||||
|
self._posproc_salvando = True
|
||||||
|
self._ultimo_posproc_save_ts = agora
|
||||||
|
|
||||||
|
return True, "ok"
|
||||||
|
|
||||||
|
def _finalizar_salvamento_posprocessamento(self):
|
||||||
|
with self._posproc_save_lock:
|
||||||
|
self._posproc_salvando = False
|
||||||
|
|
||||||
def _visual_disponivel_para_frame(self) -> bool:
|
def _visual_disponivel_para_frame(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Indica se o Visual Worker tem o mínimo necessário para gerar/salvar frames.
|
Indica se o Visual Worker tem o mínimo necessário para gerar/salvar frames.
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ VISUAL_DEFAULT_CONFIG = {
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Mostra janelas OpenCV/debug visual. Não usar em runtime de campo.
|
# Mostra janelas OpenCV/debug visual. Não usar em runtime de campo.
|
||||||
"debug_visual": False,
|
"debug_visual": False,
|
||||||
|
"posproc_intervalo_min_s": 5.0,
|
||||||
|
|
||||||
# Publica logs de performance no console.
|
# Publica logs de performance no console.
|
||||||
"debug_perf": False,
|
"debug_perf": False,
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,11 @@ class CameraManager:
|
||||||
|
|
||||||
self.perf = VisualPerfMonitor(janela=180)
|
self.perf = VisualPerfMonitor(janela=180)
|
||||||
|
|
||||||
|
self._ultimo_posproc_save_ts = 0.0
|
||||||
|
self._posproc_save_lock = threading.Lock()
|
||||||
|
self._posproc_salvando = False
|
||||||
|
self.posproc_intervalo_min_s = 5.0
|
||||||
|
|
||||||
self._reset_runtime_state()
|
self._reset_runtime_state()
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
@ -188,6 +193,8 @@ class CameraManager:
|
||||||
from weed_worker.config import load_seg_config
|
from weed_worker.config import load_seg_config
|
||||||
self.seg_config = load_seg_config()
|
self.seg_config = load_seg_config()
|
||||||
|
|
||||||
|
self.posproc_intervalo_min_s = float(self.seg_config.get("posproc_intervalo_min_s", 5.0))
|
||||||
|
|
||||||
self._inicializar_camera(mx_id, self.seg_config)
|
self._inicializar_camera(mx_id, self.seg_config)
|
||||||
|
|
||||||
if self.camera is None:
|
if self.camera is None:
|
||||||
|
|
@ -526,6 +533,7 @@ class CameraManager:
|
||||||
cfg = load_seg_config()
|
cfg = load_seg_config()
|
||||||
self.seg_config = cfg
|
self.seg_config = cfg
|
||||||
self.qtd_bicos = int(cfg.get("qtd_bicos", self.qtd_bicos or 7) or 7)
|
self.qtd_bicos = int(cfg.get("qtd_bicos", self.qtd_bicos or 7) or 7)
|
||||||
|
self.posproc_intervalo_min_s = float(cfg.get("posproc_intervalo_min_s", self.posproc_intervalo_min_s))
|
||||||
|
|
||||||
if self.weed_detector is not None:
|
if self.weed_detector is not None:
|
||||||
self.weed_detector.atualizar_config(cfg)
|
self.weed_detector.atualizar_config(cfg)
|
||||||
|
|
@ -1533,17 +1541,49 @@ class CameraManager:
|
||||||
nome_frame = f"{frame_name}_{tipo_nome}"
|
nome_frame = f"{frame_name}_{tipo_nome}"
|
||||||
|
|
||||||
if tipo_enum == TipoFrameCamera.PosProcessamento:
|
if tipo_enum == TipoFrameCamera.PosProcessamento:
|
||||||
caminhos = self._salvar_bruto_multiespectral(
|
pode_salvar, motivo = self._pode_salvar_posprocessamento()
|
||||||
nome_base=nome_frame,
|
|
||||||
pasta=pasta
|
|
||||||
)
|
|
||||||
|
|
||||||
if caminhos:
|
if not pode_salvar:
|
||||||
if isinstance(caminhos, list):
|
self.mostrar_log(
|
||||||
frames_salvos.extend(caminhos)
|
f"[weed][SAVE_PP] pulado | motivo={motivo} "
|
||||||
else:
|
f"intervalo_min={self.posproc_intervalo_min_s:.1f}s "
|
||||||
frames_salvos.append(caminhos)
|
f"nome={nome_frame}"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
def salvar_pp_async(nome_frame_async, pasta_async):
|
||||||
|
try:
|
||||||
|
t_pp0 = time.perf_counter()
|
||||||
|
|
||||||
|
caminhos = self._salvar_bruto_multiespectral(
|
||||||
|
nome_base=nome_frame_async,
|
||||||
|
pasta=pasta_async
|
||||||
|
)
|
||||||
|
|
||||||
|
t_pp1 = time.perf_counter()
|
||||||
|
|
||||||
|
qtd = len(caminhos) if isinstance(caminhos, list) else 1 if caminhos else 0
|
||||||
|
|
||||||
|
self.mostrar_log(
|
||||||
|
f"[weed][SAVE_PP] salvo async | "
|
||||||
|
f"nome={nome_frame_async} "
|
||||||
|
f"arquivos={qtd} "
|
||||||
|
f"tempo_ms={(t_pp1 - t_pp0) * 1000.0:.1f}"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.mostrar_log(f"❌ Erro no SAVE_PP async: {e}")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self._finalizar_salvamento_posprocessamento()
|
||||||
|
|
||||||
|
threading.Thread(
|
||||||
|
target=salvar_pp_async,
|
||||||
|
args=(nome_frame, pasta),
|
||||||
|
daemon=True
|
||||||
|
).start()
|
||||||
|
|
||||||
|
frames_salvos.append(f"{nome_frame}_PosProcessamento_ASYNC_STARTED")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# ====================================================
|
# ====================================================
|
||||||
|
|
@ -1635,3 +1675,24 @@ class CameraManager:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.mostrar_log(f"❌ Erro ao salvar bruto multiespectral: {e}")
|
self.mostrar_log(f"❌ Erro ao salvar bruto multiespectral: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def _pode_salvar_posprocessamento(self):
|
||||||
|
agora = time.time()
|
||||||
|
|
||||||
|
with self._posproc_save_lock:
|
||||||
|
if self._posproc_salvando:
|
||||||
|
return False, "busy"
|
||||||
|
|
||||||
|
dt = agora - self._ultimo_posproc_save_ts
|
||||||
|
if dt < self.posproc_intervalo_min_s:
|
||||||
|
return False, f"cooldown_{dt:.2f}s"
|
||||||
|
|
||||||
|
self._posproc_salvando = True
|
||||||
|
self._ultimo_posproc_save_ts = agora
|
||||||
|
|
||||||
|
return True, "ok"
|
||||||
|
|
||||||
|
def _finalizar_salvamento_posprocessamento(self):
|
||||||
|
with self._posproc_save_lock:
|
||||||
|
self._posproc_salvando = False
|
||||||
|
|
||||||
|
|
@ -41,6 +41,7 @@ WEED_DEFAULT_CONFIG = {
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Mostra janela OpenCV/debug visual. Não usar em runtime de campo.
|
# Mostra janela OpenCV/debug visual. Não usar em runtime de campo.
|
||||||
"debug_visual": False,
|
"debug_visual": False,
|
||||||
|
"posproc_intervalo_min_s": 5.0,
|
||||||
|
|
||||||
# Publica logs de performance no console.
|
# Publica logs de performance no console.
|
||||||
"debug_perf": False,
|
"debug_perf": False,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue