ajustado core da camera multiespectral, criado ferramenta para revisar as mascaras, ajsutado ferramentas para calibragem do módulo multiespectral, ajustado scripts de separação de dataset, normalizacao, treinamento, teste, exportação e benchmark, para modelo agricola
This commit is contained in:
parent
c9ad8d2aff
commit
e8cdb27687
|
|
@ -0,0 +1 @@
|
|||
Coloque seu labelmap.txt real ao lado do EXE.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"group_root": "C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\dist\\MaskReviewer\\group",
|
||||
"labelmap": "C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\dist\\MaskReviewer\\labelmap.txt"
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# -*- mode: python ; coding: utf-8 -*-
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
|
||||
datas = []
|
||||
binaries = []
|
||||
hiddenimports = []
|
||||
tmp_ret = collect_all('cv2')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['MaskReviewer.py'],
|
||||
pathex=[],
|
||||
binaries=binaries,
|
||||
datas=datas,
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
[],
|
||||
exclude_binaries=True,
|
||||
name='MaskReviewer',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
coll = COLLECT(
|
||||
exe,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='MaskReviewer',
|
||||
)
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
MASKREVIEWER - PACOTE WINDOWS
|
||||
================================
|
||||
|
||||
OBJETIVO
|
||||
--------
|
||||
Revisar, comparar e eventualmente editar máscaras já separadas pelo auditor.
|
||||
Não carrega modelo, PyTorch, CUDA ou checkpoint.
|
||||
|
||||
PACOTE PARA O ANOTADOR
|
||||
----------------------
|
||||
A estrutura recomendada é:
|
||||
|
||||
MaskReviewer\
|
||||
MaskReviewer.exe
|
||||
_internal\
|
||||
labelmap.txt
|
||||
group\
|
||||
chao\
|
||||
previews\
|
||||
masks\
|
||||
predictions\
|
||||
final_masks\
|
||||
review_order.csv
|
||||
chao_cana\
|
||||
chao_cana_erva\
|
||||
chao_erva\
|
||||
...
|
||||
|
||||
Ao abrir MaskReviewer.exe:
|
||||
|
||||
1. Se "group" estiver ao lado do EXE, ele usa automaticamente.
|
||||
2. Se "labelmap.txt" estiver ao lado do EXE, ele usa automaticamente.
|
||||
3. Se algum deles não existir, abre o seletor do Windows.
|
||||
4. Os caminhos escolhidos ficam lembrados em MaskReviewer.settings.json.
|
||||
5. O estado do lote fica em group\review_choices.csv.
|
||||
6. As escolhas finais ficam em cada:
|
||||
group\<GRUPO>\final_masks\
|
||||
|
||||
NOVO LOTE
|
||||
---------
|
||||
Para mandar uma nova revisão à mesma pessoa:
|
||||
|
||||
1. Ela mantém:
|
||||
MaskReviewer.exe
|
||||
_internal\
|
||||
labelmap.txt
|
||||
|
||||
2. Substitui a pasta:
|
||||
group\
|
||||
|
||||
3. Abre o mesmo EXE.
|
||||
|
||||
Como review_choices.csv fica DENTRO de group\, a sessão nova começa limpa junto
|
||||
com a nova pasta group.
|
||||
|
||||
CONTROLES
|
||||
---------
|
||||
Painel 2x2:
|
||||
1 = máscara humana
|
||||
2 = máscara do modelo
|
||||
3 = REMAP
|
||||
E = editar
|
||||
A/D = anterior/próxima
|
||||
S = pular
|
||||
X = apagar decisão
|
||||
Q/ESC = sair
|
||||
|
||||
A barra "Overlay %" controla a opacidade dos dois overlays ao mesmo tempo.
|
||||
|
||||
Editor:
|
||||
E e depois:
|
||||
1 = humana como base
|
||||
2 = modelo como base
|
||||
3 = começar de chão
|
||||
|
||||
Mouse esquerdo = adiciona ponto
|
||||
Mouse direito = remove último ponto
|
||||
ENTER = preenche polígono
|
||||
C = próxima classe
|
||||
0..9 = ID de classe
|
||||
Z = desfazer
|
||||
R = restaurar base
|
||||
BACKSPACE/DEL = limpar pontos abertos
|
||||
S = salvar
|
||||
ESC/Q = cancelar edição
|
||||
|
||||
COMO GERAR O EXE
|
||||
----------------
|
||||
Execute com duplo clique:
|
||||
|
||||
build_windows.bat
|
||||
|
||||
Recomendado:
|
||||
Windows 10/11
|
||||
Python 3.11 ou 3.12 instalado SOMENTE na máquina de build
|
||||
|
||||
O script cria:
|
||||
dist\MaskReviewer\MaskReviewer.exe
|
||||
|
||||
Depois do build, a máquina do anotador NÃO precisa ter Python.
|
||||
|
||||
POR QUE --ONEDIR?
|
||||
-----------------
|
||||
O build usa PyInstaller --onedir porque OpenCV/Numpy ficam mais confiáveis,
|
||||
iniciam mais rápido e são mais fáceis de diagnosticar do que um EXE --onefile.
|
||||
|
||||
IMPORTANTE
|
||||
----------
|
||||
O MaskReviewer nunca altera o dataset bruto.
|
||||
Ele só escreve final_masks e review_choices.csv dentro do lote enviado.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,77 @@
|
|||
('C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\MaskReviewer.exe',
|
||||
False,
|
||||
False,
|
||||
True,
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-windowed.ico',
|
||||
None,
|
||||
False,
|
||||
False,
|
||||
b'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<assembly xmlns='
|
||||
b'"urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\n <trustInfo x'
|
||||
b'mlns="urn:schemas-microsoft-com:asm.v3">\n <security>\n <requested'
|
||||
b'Privileges>\n <requestedExecutionLevel level="asInvoker" uiAccess='
|
||||
b'"false"/>\n </requestedPrivileges>\n </security>\n </trustInfo>\n '
|
||||
b'<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">\n <'
|
||||
b'application>\n <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f'
|
||||
b'0}"/>\n <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>\n '
|
||||
b' <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>\n <s'
|
||||
b'upportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>\n <supporte'
|
||||
b'dOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>\n </application>\n <'
|
||||
b'/compatibility>\n <application xmlns="urn:schemas-microsoft-com:asm.v3">'
|
||||
b'\n <windowsSettings>\n <longPathAware xmlns="http://schemas.micros'
|
||||
b'oft.com/SMI/2016/WindowsSettings">true</longPathAware>\n </windowsSett'
|
||||
b'ings>\n </application>\n <dependency>\n <dependentAssembly>\n <ass'
|
||||
b'emblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version='
|
||||
b'"6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" langua'
|
||||
b'ge="*"/>\n </dependentAssembly>\n </dependency>\n</assembly>',
|
||||
True,
|
||||
False,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\MaskReviewer.pkg',
|
||||
[('pyi-contents-directory _internal', '', 'OPTION'),
|
||||
('PYZ-00.pyz',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\PYZ-00.pyz',
|
||||
'PYZ'),
|
||||
('struct',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\struct.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod01_archive',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod01_archive.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod02_importers',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod02_importers.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod03_ctypes',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod03_ctypes.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod04_pywin32',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod04_pywin32.pyc',
|
||||
'PYMODULE'),
|
||||
('pyiboot01_bootstrap',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth__tkinter',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth__tkinter.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_inspect',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgutil',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_multiprocessing',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
|
||||
'PYSOURCE'),
|
||||
('MaskReviewer',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\MaskReviewer.py',
|
||||
'PYSOURCE')],
|
||||
[],
|
||||
False,
|
||||
False,
|
||||
1787944409,
|
||||
[('runw.exe',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\bootloader\\Windows-64bit-intel\\runw.exe',
|
||||
'EXECUTABLE')],
|
||||
'C:\\Python312\\python312.dll')
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,55 @@
|
|||
('C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\MaskReviewer.pkg',
|
||||
{'BINARY': True,
|
||||
'DATA': True,
|
||||
'EXECUTABLE': True,
|
||||
'EXTENSION': True,
|
||||
'PYMODULE': True,
|
||||
'PYSOURCE': True,
|
||||
'PYZ': False,
|
||||
'SPLASH': True,
|
||||
'SYMLINK': False},
|
||||
[('pyi-contents-directory _internal', '', 'OPTION'),
|
||||
('PYZ-00.pyz',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\PYZ-00.pyz',
|
||||
'PYZ'),
|
||||
('struct',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\struct.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod01_archive',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod01_archive.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod02_importers',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod02_importers.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod03_ctypes',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod03_ctypes.pyc',
|
||||
'PYMODULE'),
|
||||
('pyimod04_pywin32',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\localpycs\\pyimod04_pywin32.pyc',
|
||||
'PYMODULE'),
|
||||
('pyiboot01_bootstrap',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth__tkinter',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth__tkinter.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_inspect',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_pkgutil',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
|
||||
'PYSOURCE'),
|
||||
('pyi_rth_multiprocessing',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
|
||||
'PYSOURCE'),
|
||||
('MaskReviewer',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\MaskReviewer.py',
|
||||
'PYSOURCE')],
|
||||
'python312.dll',
|
||||
True,
|
||||
False,
|
||||
False,
|
||||
[],
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
Binary file not shown.
|
|
@ -0,0 +1,815 @@
|
|||
('C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\build\\MaskReviewer\\PYZ-00.pyz',
|
||||
[('__future__', 'C:\\Python312\\Lib\\__future__.py', 'PYMODULE'),
|
||||
('_aix_support', 'C:\\Python312\\Lib\\_aix_support.py', 'PYMODULE'),
|
||||
('_compat_pickle', 'C:\\Python312\\Lib\\_compat_pickle.py', 'PYMODULE'),
|
||||
('_compression', 'C:\\Python312\\Lib\\_compression.py', 'PYMODULE'),
|
||||
('_py_abc', 'C:\\Python312\\Lib\\_py_abc.py', 'PYMODULE'),
|
||||
('_pydatetime', 'C:\\Python312\\Lib\\_pydatetime.py', 'PYMODULE'),
|
||||
('_pydecimal', 'C:\\Python312\\Lib\\_pydecimal.py', 'PYMODULE'),
|
||||
('_strptime', 'C:\\Python312\\Lib\\_strptime.py', 'PYMODULE'),
|
||||
('_threading_local', 'C:\\Python312\\Lib\\_threading_local.py', 'PYMODULE'),
|
||||
('argparse', 'C:\\Python312\\Lib\\argparse.py', 'PYMODULE'),
|
||||
('ast', 'C:\\Python312\\Lib\\ast.py', 'PYMODULE'),
|
||||
('asyncio', 'C:\\Python312\\Lib\\asyncio\\__init__.py', 'PYMODULE'),
|
||||
('asyncio.base_events',
|
||||
'C:\\Python312\\Lib\\asyncio\\base_events.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.base_futures',
|
||||
'C:\\Python312\\Lib\\asyncio\\base_futures.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.base_subprocess',
|
||||
'C:\\Python312\\Lib\\asyncio\\base_subprocess.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.base_tasks',
|
||||
'C:\\Python312\\Lib\\asyncio\\base_tasks.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.constants',
|
||||
'C:\\Python312\\Lib\\asyncio\\constants.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.coroutines',
|
||||
'C:\\Python312\\Lib\\asyncio\\coroutines.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.events', 'C:\\Python312\\Lib\\asyncio\\events.py', 'PYMODULE'),
|
||||
('asyncio.exceptions',
|
||||
'C:\\Python312\\Lib\\asyncio\\exceptions.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.format_helpers',
|
||||
'C:\\Python312\\Lib\\asyncio\\format_helpers.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.futures', 'C:\\Python312\\Lib\\asyncio\\futures.py', 'PYMODULE'),
|
||||
('asyncio.locks', 'C:\\Python312\\Lib\\asyncio\\locks.py', 'PYMODULE'),
|
||||
('asyncio.log', 'C:\\Python312\\Lib\\asyncio\\log.py', 'PYMODULE'),
|
||||
('asyncio.mixins', 'C:\\Python312\\Lib\\asyncio\\mixins.py', 'PYMODULE'),
|
||||
('asyncio.proactor_events',
|
||||
'C:\\Python312\\Lib\\asyncio\\proactor_events.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.protocols',
|
||||
'C:\\Python312\\Lib\\asyncio\\protocols.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.queues', 'C:\\Python312\\Lib\\asyncio\\queues.py', 'PYMODULE'),
|
||||
('asyncio.runners', 'C:\\Python312\\Lib\\asyncio\\runners.py', 'PYMODULE'),
|
||||
('asyncio.selector_events',
|
||||
'C:\\Python312\\Lib\\asyncio\\selector_events.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.sslproto', 'C:\\Python312\\Lib\\asyncio\\sslproto.py', 'PYMODULE'),
|
||||
('asyncio.staggered',
|
||||
'C:\\Python312\\Lib\\asyncio\\staggered.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.streams', 'C:\\Python312\\Lib\\asyncio\\streams.py', 'PYMODULE'),
|
||||
('asyncio.subprocess',
|
||||
'C:\\Python312\\Lib\\asyncio\\subprocess.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.taskgroups',
|
||||
'C:\\Python312\\Lib\\asyncio\\taskgroups.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.tasks', 'C:\\Python312\\Lib\\asyncio\\tasks.py', 'PYMODULE'),
|
||||
('asyncio.threads', 'C:\\Python312\\Lib\\asyncio\\threads.py', 'PYMODULE'),
|
||||
('asyncio.timeouts', 'C:\\Python312\\Lib\\asyncio\\timeouts.py', 'PYMODULE'),
|
||||
('asyncio.transports',
|
||||
'C:\\Python312\\Lib\\asyncio\\transports.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.trsock', 'C:\\Python312\\Lib\\asyncio\\trsock.py', 'PYMODULE'),
|
||||
('asyncio.unix_events',
|
||||
'C:\\Python312\\Lib\\asyncio\\unix_events.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.windows_events',
|
||||
'C:\\Python312\\Lib\\asyncio\\windows_events.py',
|
||||
'PYMODULE'),
|
||||
('asyncio.windows_utils',
|
||||
'C:\\Python312\\Lib\\asyncio\\windows_utils.py',
|
||||
'PYMODULE'),
|
||||
('base64', 'C:\\Python312\\Lib\\base64.py', 'PYMODULE'),
|
||||
('bdb', 'C:\\Python312\\Lib\\bdb.py', 'PYMODULE'),
|
||||
('bisect', 'C:\\Python312\\Lib\\bisect.py', 'PYMODULE'),
|
||||
('bz2', 'C:\\Python312\\Lib\\bz2.py', 'PYMODULE'),
|
||||
('calendar', 'C:\\Python312\\Lib\\calendar.py', 'PYMODULE'),
|
||||
('cmd', 'C:\\Python312\\Lib\\cmd.py', 'PYMODULE'),
|
||||
('code', 'C:\\Python312\\Lib\\code.py', 'PYMODULE'),
|
||||
('codeop', 'C:\\Python312\\Lib\\codeop.py', 'PYMODULE'),
|
||||
('concurrent', 'C:\\Python312\\Lib\\concurrent\\__init__.py', 'PYMODULE'),
|
||||
('concurrent.futures',
|
||||
'C:\\Python312\\Lib\\concurrent\\futures\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('concurrent.futures._base',
|
||||
'C:\\Python312\\Lib\\concurrent\\futures\\_base.py',
|
||||
'PYMODULE'),
|
||||
('concurrent.futures.process',
|
||||
'C:\\Python312\\Lib\\concurrent\\futures\\process.py',
|
||||
'PYMODULE'),
|
||||
('concurrent.futures.thread',
|
||||
'C:\\Python312\\Lib\\concurrent\\futures\\thread.py',
|
||||
'PYMODULE'),
|
||||
('contextlib', 'C:\\Python312\\Lib\\contextlib.py', 'PYMODULE'),
|
||||
('contextvars', 'C:\\Python312\\Lib\\contextvars.py', 'PYMODULE'),
|
||||
('copy', 'C:\\Python312\\Lib\\copy.py', 'PYMODULE'),
|
||||
('csv', 'C:\\Python312\\Lib\\csv.py', 'PYMODULE'),
|
||||
('ctypes', 'C:\\Python312\\Lib\\ctypes\\__init__.py', 'PYMODULE'),
|
||||
('ctypes._endian', 'C:\\Python312\\Lib\\ctypes\\_endian.py', 'PYMODULE'),
|
||||
('dataclasses', 'C:\\Python312\\Lib\\dataclasses.py', 'PYMODULE'),
|
||||
('datetime', 'C:\\Python312\\Lib\\datetime.py', 'PYMODULE'),
|
||||
('decimal', 'C:\\Python312\\Lib\\decimal.py', 'PYMODULE'),
|
||||
('difflib', 'C:\\Python312\\Lib\\difflib.py', 'PYMODULE'),
|
||||
('dis', 'C:\\Python312\\Lib\\dis.py', 'PYMODULE'),
|
||||
('doctest', 'C:\\Python312\\Lib\\doctest.py', 'PYMODULE'),
|
||||
('email', 'C:\\Python312\\Lib\\email\\__init__.py', 'PYMODULE'),
|
||||
('email._encoded_words',
|
||||
'C:\\Python312\\Lib\\email\\_encoded_words.py',
|
||||
'PYMODULE'),
|
||||
('email._header_value_parser',
|
||||
'C:\\Python312\\Lib\\email\\_header_value_parser.py',
|
||||
'PYMODULE'),
|
||||
('email._parseaddr', 'C:\\Python312\\Lib\\email\\_parseaddr.py', 'PYMODULE'),
|
||||
('email._policybase',
|
||||
'C:\\Python312\\Lib\\email\\_policybase.py',
|
||||
'PYMODULE'),
|
||||
('email.base64mime', 'C:\\Python312\\Lib\\email\\base64mime.py', 'PYMODULE'),
|
||||
('email.charset', 'C:\\Python312\\Lib\\email\\charset.py', 'PYMODULE'),
|
||||
('email.contentmanager',
|
||||
'C:\\Python312\\Lib\\email\\contentmanager.py',
|
||||
'PYMODULE'),
|
||||
('email.encoders', 'C:\\Python312\\Lib\\email\\encoders.py', 'PYMODULE'),
|
||||
('email.errors', 'C:\\Python312\\Lib\\email\\errors.py', 'PYMODULE'),
|
||||
('email.feedparser', 'C:\\Python312\\Lib\\email\\feedparser.py', 'PYMODULE'),
|
||||
('email.generator', 'C:\\Python312\\Lib\\email\\generator.py', 'PYMODULE'),
|
||||
('email.header', 'C:\\Python312\\Lib\\email\\header.py', 'PYMODULE'),
|
||||
('email.headerregistry',
|
||||
'C:\\Python312\\Lib\\email\\headerregistry.py',
|
||||
'PYMODULE'),
|
||||
('email.iterators', 'C:\\Python312\\Lib\\email\\iterators.py', 'PYMODULE'),
|
||||
('email.message', 'C:\\Python312\\Lib\\email\\message.py', 'PYMODULE'),
|
||||
('email.parser', 'C:\\Python312\\Lib\\email\\parser.py', 'PYMODULE'),
|
||||
('email.policy', 'C:\\Python312\\Lib\\email\\policy.py', 'PYMODULE'),
|
||||
('email.quoprimime', 'C:\\Python312\\Lib\\email\\quoprimime.py', 'PYMODULE'),
|
||||
('email.utils', 'C:\\Python312\\Lib\\email\\utils.py', 'PYMODULE'),
|
||||
('fileinput', 'C:\\Python312\\Lib\\fileinput.py', 'PYMODULE'),
|
||||
('fnmatch', 'C:\\Python312\\Lib\\fnmatch.py', 'PYMODULE'),
|
||||
('fractions', 'C:\\Python312\\Lib\\fractions.py', 'PYMODULE'),
|
||||
('ftplib', 'C:\\Python312\\Lib\\ftplib.py', 'PYMODULE'),
|
||||
('getopt', 'C:\\Python312\\Lib\\getopt.py', 'PYMODULE'),
|
||||
('getpass', 'C:\\Python312\\Lib\\getpass.py', 'PYMODULE'),
|
||||
('gettext', 'C:\\Python312\\Lib\\gettext.py', 'PYMODULE'),
|
||||
('glob', 'C:\\Python312\\Lib\\glob.py', 'PYMODULE'),
|
||||
('gzip', 'C:\\Python312\\Lib\\gzip.py', 'PYMODULE'),
|
||||
('hashlib', 'C:\\Python312\\Lib\\hashlib.py', 'PYMODULE'),
|
||||
('hmac', 'C:\\Python312\\Lib\\hmac.py', 'PYMODULE'),
|
||||
('html', 'C:\\Python312\\Lib\\html\\__init__.py', 'PYMODULE'),
|
||||
('html.entities', 'C:\\Python312\\Lib\\html\\entities.py', 'PYMODULE'),
|
||||
('http', 'C:\\Python312\\Lib\\http\\__init__.py', 'PYMODULE'),
|
||||
('http.client', 'C:\\Python312\\Lib\\http\\client.py', 'PYMODULE'),
|
||||
('http.cookiejar', 'C:\\Python312\\Lib\\http\\cookiejar.py', 'PYMODULE'),
|
||||
('http.server', 'C:\\Python312\\Lib\\http\\server.py', 'PYMODULE'),
|
||||
('importlib', 'C:\\Python312\\Lib\\importlib\\__init__.py', 'PYMODULE'),
|
||||
('importlib._abc', 'C:\\Python312\\Lib\\importlib\\_abc.py', 'PYMODULE'),
|
||||
('importlib._bootstrap',
|
||||
'C:\\Python312\\Lib\\importlib\\_bootstrap.py',
|
||||
'PYMODULE'),
|
||||
('importlib._bootstrap_external',
|
||||
'C:\\Python312\\Lib\\importlib\\_bootstrap_external.py',
|
||||
'PYMODULE'),
|
||||
('importlib.abc', 'C:\\Python312\\Lib\\importlib\\abc.py', 'PYMODULE'),
|
||||
('importlib.machinery',
|
||||
'C:\\Python312\\Lib\\importlib\\machinery.py',
|
||||
'PYMODULE'),
|
||||
('importlib.metadata',
|
||||
'C:\\Python312\\Lib\\importlib\\metadata\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('importlib.metadata._adapters',
|
||||
'C:\\Python312\\Lib\\importlib\\metadata\\_adapters.py',
|
||||
'PYMODULE'),
|
||||
('importlib.metadata._collections',
|
||||
'C:\\Python312\\Lib\\importlib\\metadata\\_collections.py',
|
||||
'PYMODULE'),
|
||||
('importlib.metadata._functools',
|
||||
'C:\\Python312\\Lib\\importlib\\metadata\\_functools.py',
|
||||
'PYMODULE'),
|
||||
('importlib.metadata._itertools',
|
||||
'C:\\Python312\\Lib\\importlib\\metadata\\_itertools.py',
|
||||
'PYMODULE'),
|
||||
('importlib.metadata._meta',
|
||||
'C:\\Python312\\Lib\\importlib\\metadata\\_meta.py',
|
||||
'PYMODULE'),
|
||||
('importlib.metadata._text',
|
||||
'C:\\Python312\\Lib\\importlib\\metadata\\_text.py',
|
||||
'PYMODULE'),
|
||||
('importlib.readers',
|
||||
'C:\\Python312\\Lib\\importlib\\readers.py',
|
||||
'PYMODULE'),
|
||||
('importlib.resources',
|
||||
'C:\\Python312\\Lib\\importlib\\resources\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('importlib.resources._adapters',
|
||||
'C:\\Python312\\Lib\\importlib\\resources\\_adapters.py',
|
||||
'PYMODULE'),
|
||||
('importlib.resources._common',
|
||||
'C:\\Python312\\Lib\\importlib\\resources\\_common.py',
|
||||
'PYMODULE'),
|
||||
('importlib.resources._itertools',
|
||||
'C:\\Python312\\Lib\\importlib\\resources\\_itertools.py',
|
||||
'PYMODULE'),
|
||||
('importlib.resources._legacy',
|
||||
'C:\\Python312\\Lib\\importlib\\resources\\_legacy.py',
|
||||
'PYMODULE'),
|
||||
('importlib.resources.abc',
|
||||
'C:\\Python312\\Lib\\importlib\\resources\\abc.py',
|
||||
'PYMODULE'),
|
||||
('importlib.resources.readers',
|
||||
'C:\\Python312\\Lib\\importlib\\resources\\readers.py',
|
||||
'PYMODULE'),
|
||||
('importlib.util', 'C:\\Python312\\Lib\\importlib\\util.py', 'PYMODULE'),
|
||||
('inspect', 'C:\\Python312\\Lib\\inspect.py', 'PYMODULE'),
|
||||
('ipaddress', 'C:\\Python312\\Lib\\ipaddress.py', 'PYMODULE'),
|
||||
('json', 'C:\\Python312\\Lib\\json\\__init__.py', 'PYMODULE'),
|
||||
('json.decoder', 'C:\\Python312\\Lib\\json\\decoder.py', 'PYMODULE'),
|
||||
('json.encoder', 'C:\\Python312\\Lib\\json\\encoder.py', 'PYMODULE'),
|
||||
('json.scanner', 'C:\\Python312\\Lib\\json\\scanner.py', 'PYMODULE'),
|
||||
('logging', 'C:\\Python312\\Lib\\logging\\__init__.py', 'PYMODULE'),
|
||||
('lzma', 'C:\\Python312\\Lib\\lzma.py', 'PYMODULE'),
|
||||
('mimetypes', 'C:\\Python312\\Lib\\mimetypes.py', 'PYMODULE'),
|
||||
('multiprocessing',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.connection',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\connection.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.context',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\context.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.dummy',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\dummy\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.dummy.connection',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\dummy\\connection.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.forkserver',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\forkserver.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.heap',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\heap.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.managers',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\managers.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.pool',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\pool.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.popen_fork',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\popen_fork.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.popen_forkserver',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\popen_forkserver.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.popen_spawn_posix',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\popen_spawn_posix.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.popen_spawn_win32',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\popen_spawn_win32.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.process',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\process.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.queues',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\queues.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.reduction',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\reduction.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.resource_sharer',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\resource_sharer.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.resource_tracker',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\resource_tracker.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.shared_memory',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\shared_memory.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.sharedctypes',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\sharedctypes.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.spawn',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\spawn.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.synchronize',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\synchronize.py',
|
||||
'PYMODULE'),
|
||||
('multiprocessing.util',
|
||||
'C:\\Python312\\Lib\\multiprocessing\\util.py',
|
||||
'PYMODULE'),
|
||||
('netrc', 'C:\\Python312\\Lib\\netrc.py', 'PYMODULE'),
|
||||
('nturl2path', 'C:\\Python312\\Lib\\nturl2path.py', 'PYMODULE'),
|
||||
('numbers', 'C:\\Python312\\Lib\\numbers.py', 'PYMODULE'),
|
||||
('numpy',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.__config__',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\__config__.py',
|
||||
'PYMODULE'),
|
||||
('numpy._array_api_info',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_array_api_info.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._add_newdocs',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_add_newdocs.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._add_newdocs_scalars',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_add_newdocs_scalars.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._asarray',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_asarray.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._dtype',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_dtype.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._dtype_ctypes',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_dtype_ctypes.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._exceptions',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_exceptions.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._internal',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_internal.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._methods',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_methods.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._string_helpers',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_string_helpers.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._type_aliases',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_type_aliases.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core._ufunc_config',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\_ufunc_config.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.arrayprint',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\arrayprint.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.defchararray',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\defchararray.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.einsumfunc',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\einsumfunc.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.fromnumeric',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\fromnumeric.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.function_base',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\function_base.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.getlimits',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\getlimits.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.memmap',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\memmap.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.multiarray',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\multiarray.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.numeric',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\numeric.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.numerictypes',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\numerictypes.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.overrides',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\overrides.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.printoptions',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\printoptions.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.records',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\records.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.shape_base',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\shape_base.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.strings',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\strings.py',
|
||||
'PYMODULE'),
|
||||
('numpy._core.umath',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_core\\umath.py',
|
||||
'PYMODULE'),
|
||||
('numpy._distributor_init',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_distributor_init.py',
|
||||
'PYMODULE'),
|
||||
('numpy._expired_attrs_2_0',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_expired_attrs_2_0.py',
|
||||
'PYMODULE'),
|
||||
('numpy._globals',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_globals.py',
|
||||
'PYMODULE'),
|
||||
('numpy._pytesttester',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_pytesttester.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._add_docstring',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_add_docstring.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._array_like',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_array_like.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._char_codes',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_char_codes.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._dtype_like',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_dtype_like.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._nbit',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_nbit.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._nbit_base',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_nbit_base.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._nested_sequence',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_nested_sequence.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._scalars',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_scalars.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._shape',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_shape.py',
|
||||
'PYMODULE'),
|
||||
('numpy._typing._ufunc',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_typing\\_ufunc.py',
|
||||
'PYMODULE'),
|
||||
('numpy._utils',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_utils\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy._utils._conversions',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_utils\\_conversions.py',
|
||||
'PYMODULE'),
|
||||
('numpy._utils._inspect',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\_utils\\_inspect.py',
|
||||
'PYMODULE'),
|
||||
('numpy.char',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\char\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.core',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\core\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.core._utils',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\core\\_utils.py',
|
||||
'PYMODULE'),
|
||||
('numpy.core.multiarray',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\core\\multiarray.py',
|
||||
'PYMODULE'),
|
||||
('numpy.ctypeslib',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\ctypeslib\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.ctypeslib._ctypeslib',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\ctypeslib\\_ctypeslib.py',
|
||||
'PYMODULE'),
|
||||
('numpy.dtypes',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\dtypes.py',
|
||||
'PYMODULE'),
|
||||
('numpy.exceptions',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\exceptions.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.__version__',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\__version__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py._backends',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\_backends\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py._backends._backend',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\_backends\\_backend.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py._backends._meson',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\_backends\\_meson.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py._isocbind',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\_isocbind.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.auxfuncs',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\auxfuncs.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.capi_maps',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\capi_maps.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.cb_rules',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\cb_rules.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.cfuncs',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\cfuncs.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.common_rules',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\common_rules.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.crackfortran',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\crackfortran.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.diagnose',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\diagnose.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.f2py2e',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\f2py2e.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.f90mod_rules',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\f90mod_rules.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.func2subr',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\func2subr.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.rules',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\rules.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.symbolic',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\symbolic.py',
|
||||
'PYMODULE'),
|
||||
('numpy.f2py.use_rules',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\f2py\\use_rules.py',
|
||||
'PYMODULE'),
|
||||
('numpy.fft',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\fft\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.fft._helper',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\fft\\_helper.py',
|
||||
'PYMODULE'),
|
||||
('numpy.fft._pocketfft',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\fft\\_pocketfft.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._array_utils_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_array_utils_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._arraypad_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_arraypad_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._arraysetops_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_arraysetops_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._arrayterator_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_arrayterator_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._datasource',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_datasource.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._format_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_format_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._function_base_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_function_base_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._histograms_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_histograms_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._index_tricks_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_index_tricks_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._iotools',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_iotools.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._nanfunctions_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_nanfunctions_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._npyio_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_npyio_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._polynomial_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_polynomial_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._scimath_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_scimath_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._shape_base_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_shape_base_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._stride_tricks_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_stride_tricks_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._twodim_base_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_twodim_base_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._type_check_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_type_check_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._ufunclike_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_ufunclike_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._utils_impl',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_utils_impl.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib._version',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\_version.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.array_utils',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\array_utils.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.format',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\format.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.introspect',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\introspect.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.mixins',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\mixins.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.npyio',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\npyio.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.recfunctions',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\recfunctions.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.scimath',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\scimath.py',
|
||||
'PYMODULE'),
|
||||
('numpy.lib.stride_tricks',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\lib\\stride_tricks.py',
|
||||
'PYMODULE'),
|
||||
('numpy.linalg',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\linalg\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.linalg._linalg',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\linalg\\_linalg.py',
|
||||
'PYMODULE'),
|
||||
('numpy.ma',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\ma\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.ma.core',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\ma\\core.py',
|
||||
'PYMODULE'),
|
||||
('numpy.ma.extras',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\ma\\extras.py',
|
||||
'PYMODULE'),
|
||||
('numpy.ma.mrecords',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\ma\\mrecords.py',
|
||||
'PYMODULE'),
|
||||
('numpy.matlib',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\matlib.py',
|
||||
'PYMODULE'),
|
||||
('numpy.matrixlib',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\matrixlib\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.matrixlib.defmatrix',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\matrixlib\\defmatrix.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial._polybase',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\_polybase.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial.chebyshev',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\chebyshev.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial.hermite',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\hermite.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial.hermite_e',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\hermite_e.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial.laguerre',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\laguerre.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial.legendre',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\legendre.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial.polynomial',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\polynomial.py',
|
||||
'PYMODULE'),
|
||||
('numpy.polynomial.polyutils',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\polynomial\\polyutils.py',
|
||||
'PYMODULE'),
|
||||
('numpy.random',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\random\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.random._pickle',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\random\\_pickle.py',
|
||||
'PYMODULE'),
|
||||
('numpy.rec',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\rec\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.strings',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\strings\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.testing',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\testing\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.testing._private',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\testing\\_private\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.testing._private.extbuild',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\testing\\_private\\extbuild.py',
|
||||
'PYMODULE'),
|
||||
('numpy.testing._private.utils',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\testing\\_private\\utils.py',
|
||||
'PYMODULE'),
|
||||
('numpy.testing.overrides',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\testing\\overrides.py',
|
||||
'PYMODULE'),
|
||||
('numpy.typing',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\typing\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('numpy.version',
|
||||
'C:\\ZendionInc\\agrobot_base\\Python\\OAK\\datasets\\oak-fcc-3\\MaskReviewer_package\\.build_venv\\Lib\\site-packages\\numpy\\version.py',
|
||||
'PYMODULE'),
|
||||
('opcode', 'C:\\Python312\\Lib\\opcode.py', 'PYMODULE'),
|
||||
('pathlib', 'C:\\Python312\\Lib\\pathlib.py', 'PYMODULE'),
|
||||
('pdb', 'C:\\Python312\\Lib\\pdb.py', 'PYMODULE'),
|
||||
('pickle', 'C:\\Python312\\Lib\\pickle.py', 'PYMODULE'),
|
||||
('pkgutil', 'C:\\Python312\\Lib\\pkgutil.py', 'PYMODULE'),
|
||||
('platform', 'C:\\Python312\\Lib\\platform.py', 'PYMODULE'),
|
||||
('pprint', 'C:\\Python312\\Lib\\pprint.py', 'PYMODULE'),
|
||||
('py_compile', 'C:\\Python312\\Lib\\py_compile.py', 'PYMODULE'),
|
||||
('pydoc', 'C:\\Python312\\Lib\\pydoc.py', 'PYMODULE'),
|
||||
('pydoc_data', 'C:\\Python312\\Lib\\pydoc_data\\__init__.py', 'PYMODULE'),
|
||||
('pydoc_data.topics',
|
||||
'C:\\Python312\\Lib\\pydoc_data\\topics.py',
|
||||
'PYMODULE'),
|
||||
('queue', 'C:\\Python312\\Lib\\queue.py', 'PYMODULE'),
|
||||
('quopri', 'C:\\Python312\\Lib\\quopri.py', 'PYMODULE'),
|
||||
('random', 'C:\\Python312\\Lib\\random.py', 'PYMODULE'),
|
||||
('runpy', 'C:\\Python312\\Lib\\runpy.py', 'PYMODULE'),
|
||||
('secrets', 'C:\\Python312\\Lib\\secrets.py', 'PYMODULE'),
|
||||
('selectors', 'C:\\Python312\\Lib\\selectors.py', 'PYMODULE'),
|
||||
('shlex', 'C:\\Python312\\Lib\\shlex.py', 'PYMODULE'),
|
||||
('shutil', 'C:\\Python312\\Lib\\shutil.py', 'PYMODULE'),
|
||||
('signal', 'C:\\Python312\\Lib\\signal.py', 'PYMODULE'),
|
||||
('socket', 'C:\\Python312\\Lib\\socket.py', 'PYMODULE'),
|
||||
('socketserver', 'C:\\Python312\\Lib\\socketserver.py', 'PYMODULE'),
|
||||
('ssl', 'C:\\Python312\\Lib\\ssl.py', 'PYMODULE'),
|
||||
('statistics', 'C:\\Python312\\Lib\\statistics.py', 'PYMODULE'),
|
||||
('string', 'C:\\Python312\\Lib\\string.py', 'PYMODULE'),
|
||||
('stringprep', 'C:\\Python312\\Lib\\stringprep.py', 'PYMODULE'),
|
||||
('subprocess', 'C:\\Python312\\Lib\\subprocess.py', 'PYMODULE'),
|
||||
('sysconfig', 'C:\\Python312\\Lib\\sysconfig.py', 'PYMODULE'),
|
||||
('tarfile', 'C:\\Python312\\Lib\\tarfile.py', 'PYMODULE'),
|
||||
('tempfile', 'C:\\Python312\\Lib\\tempfile.py', 'PYMODULE'),
|
||||
('textwrap', 'C:\\Python312\\Lib\\textwrap.py', 'PYMODULE'),
|
||||
('threading', 'C:\\Python312\\Lib\\threading.py', 'PYMODULE'),
|
||||
('tkinter', 'C:\\Python312\\Lib\\tkinter\\__init__.py', 'PYMODULE'),
|
||||
('tkinter.commondialog',
|
||||
'C:\\Python312\\Lib\\tkinter\\commondialog.py',
|
||||
'PYMODULE'),
|
||||
('tkinter.constants',
|
||||
'C:\\Python312\\Lib\\tkinter\\constants.py',
|
||||
'PYMODULE'),
|
||||
('tkinter.dialog', 'C:\\Python312\\Lib\\tkinter\\dialog.py', 'PYMODULE'),
|
||||
('tkinter.filedialog',
|
||||
'C:\\Python312\\Lib\\tkinter\\filedialog.py',
|
||||
'PYMODULE'),
|
||||
('tkinter.messagebox',
|
||||
'C:\\Python312\\Lib\\tkinter\\messagebox.py',
|
||||
'PYMODULE'),
|
||||
('tkinter.simpledialog',
|
||||
'C:\\Python312\\Lib\\tkinter\\simpledialog.py',
|
||||
'PYMODULE'),
|
||||
('token', 'C:\\Python312\\Lib\\token.py', 'PYMODULE'),
|
||||
('tokenize', 'C:\\Python312\\Lib\\tokenize.py', 'PYMODULE'),
|
||||
('tracemalloc', 'C:\\Python312\\Lib\\tracemalloc.py', 'PYMODULE'),
|
||||
('tty', 'C:\\Python312\\Lib\\tty.py', 'PYMODULE'),
|
||||
('typing', 'C:\\Python312\\Lib\\typing.py', 'PYMODULE'),
|
||||
('unittest', 'C:\\Python312\\Lib\\unittest\\__init__.py', 'PYMODULE'),
|
||||
('unittest._log', 'C:\\Python312\\Lib\\unittest\\_log.py', 'PYMODULE'),
|
||||
('unittest.async_case',
|
||||
'C:\\Python312\\Lib\\unittest\\async_case.py',
|
||||
'PYMODULE'),
|
||||
('unittest.case', 'C:\\Python312\\Lib\\unittest\\case.py', 'PYMODULE'),
|
||||
('unittest.loader', 'C:\\Python312\\Lib\\unittest\\loader.py', 'PYMODULE'),
|
||||
('unittest.main', 'C:\\Python312\\Lib\\unittest\\main.py', 'PYMODULE'),
|
||||
('unittest.result', 'C:\\Python312\\Lib\\unittest\\result.py', 'PYMODULE'),
|
||||
('unittest.runner', 'C:\\Python312\\Lib\\unittest\\runner.py', 'PYMODULE'),
|
||||
('unittest.signals', 'C:\\Python312\\Lib\\unittest\\signals.py', 'PYMODULE'),
|
||||
('unittest.suite', 'C:\\Python312\\Lib\\unittest\\suite.py', 'PYMODULE'),
|
||||
('unittest.util', 'C:\\Python312\\Lib\\unittest\\util.py', 'PYMODULE'),
|
||||
('urllib', 'C:\\Python312\\Lib\\urllib\\__init__.py', 'PYMODULE'),
|
||||
('urllib.error', 'C:\\Python312\\Lib\\urllib\\error.py', 'PYMODULE'),
|
||||
('urllib.parse', 'C:\\Python312\\Lib\\urllib\\parse.py', 'PYMODULE'),
|
||||
('urllib.request', 'C:\\Python312\\Lib\\urllib\\request.py', 'PYMODULE'),
|
||||
('urllib.response', 'C:\\Python312\\Lib\\urllib\\response.py', 'PYMODULE'),
|
||||
('webbrowser', 'C:\\Python312\\Lib\\webbrowser.py', 'PYMODULE'),
|
||||
('xml', 'C:\\Python312\\Lib\\xml\\__init__.py', 'PYMODULE'),
|
||||
('xml.parsers', 'C:\\Python312\\Lib\\xml\\parsers\\__init__.py', 'PYMODULE'),
|
||||
('xml.parsers.expat',
|
||||
'C:\\Python312\\Lib\\xml\\parsers\\expat.py',
|
||||
'PYMODULE'),
|
||||
('xml.sax', 'C:\\Python312\\Lib\\xml\\sax\\__init__.py', 'PYMODULE'),
|
||||
('xml.sax._exceptions',
|
||||
'C:\\Python312\\Lib\\xml\\sax\\_exceptions.py',
|
||||
'PYMODULE'),
|
||||
('xml.sax.expatreader',
|
||||
'C:\\Python312\\Lib\\xml\\sax\\expatreader.py',
|
||||
'PYMODULE'),
|
||||
('xml.sax.handler', 'C:\\Python312\\Lib\\xml\\sax\\handler.py', 'PYMODULE'),
|
||||
('xml.sax.saxutils', 'C:\\Python312\\Lib\\xml\\sax\\saxutils.py', 'PYMODULE'),
|
||||
('xml.sax.xmlreader',
|
||||
'C:\\Python312\\Lib\\xml\\sax\\xmlreader.py',
|
||||
'PYMODULE'),
|
||||
('xmlrpc', 'C:\\Python312\\Lib\\xmlrpc\\__init__.py', 'PYMODULE'),
|
||||
('xmlrpc.client', 'C:\\Python312\\Lib\\xmlrpc\\client.py', 'PYMODULE'),
|
||||
('zipfile', 'C:\\Python312\\Lib\\zipfile\\__init__.py', 'PYMODULE'),
|
||||
('zipfile._path',
|
||||
'C:\\Python312\\Lib\\zipfile\\_path\\__init__.py',
|
||||
'PYMODULE'),
|
||||
('zipfile._path.glob',
|
||||
'C:\\Python312\\Lib\\zipfile\\_path\\glob.py',
|
||||
'PYMODULE'),
|
||||
('zipimport', 'C:\\Python312\\Lib\\zipimport.py', 'PYMODULE')])
|
||||
Binary file not shown.
|
|
@ -0,0 +1,223 @@
|
|||
|
||||
This file lists modules PyInstaller was not able to find. This does not
|
||||
necessarily mean these modules are required for running your program. Both
|
||||
Python's standard library and 3rd-party Python packages often conditionally
|
||||
import optional modules, some of which may be available only on certain
|
||||
platforms.
|
||||
|
||||
Types of import:
|
||||
* top-level: imported at the top-level - look at these first
|
||||
* conditional: imported within an if-statement
|
||||
* delayed: imported within a function
|
||||
* optional: imported within a try-except-statement
|
||||
|
||||
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
|
||||
tracking down the missing module yourself. Thanks!
|
||||
|
||||
missing module named pwd - imported by posixpath (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional), http.server (delayed, optional), netrc (delayed, conditional), getpass (delayed)
|
||||
missing module named grp - imported by shutil (delayed, optional), tarfile (optional), pathlib (delayed, optional), subprocess (delayed, conditional, optional)
|
||||
missing module named _posixsubprocess - imported by subprocess (conditional), multiprocessing.util (delayed)
|
||||
missing module named fcntl - imported by subprocess (optional)
|
||||
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
|
||||
missing module named _scproxy - imported by urllib.request (conditional)
|
||||
missing module named termios - imported by tty (top-level), getpass (optional)
|
||||
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
|
||||
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
|
||||
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
|
||||
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
|
||||
missing module named posix - imported by os (conditional, optional), posixpath (optional), shutil (conditional), importlib._bootstrap_external (conditional)
|
||||
missing module named resource - imported by posix (top-level)
|
||||
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
|
||||
missing module named pyimod02_importers - imported by C:\ZendionInc\agrobot_base\Python\OAK\datasets\oak-fcc-3\MaskReviewer_package\.build_venv\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed)
|
||||
missing module named _dummy_thread - imported by numpy._core.arrayprint (optional)
|
||||
missing module named typing_extensions - imported by numpy._typing._nested_sequence (conditional), numpy.random.bit_generator (top-level)
|
||||
missing module named charset_normalizer - imported by numpy.f2py.crackfortran (optional)
|
||||
missing module named vms_lib - imported by platform (delayed, optional)
|
||||
missing module named 'java.lang' - imported by platform (delayed, optional)
|
||||
missing module named java - imported by platform (delayed)
|
||||
missing module named _winreg - imported by platform (delayed, optional)
|
||||
missing module named psutil - imported by numpy.testing._private.utils (delayed, optional)
|
||||
missing module named readline - imported by cmd (delayed, conditional, optional), code (delayed, conditional, optional), pdb (delayed, optional)
|
||||
missing module named win32pdh - imported by numpy.testing._private.utils (delayed, conditional)
|
||||
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
|
||||
missing module named _typeshed - imported by numpy.random._common (top-level), numpy.random.bit_generator (top-level)
|
||||
missing module named threadpoolctl - imported by numpy.lib._utils_impl (delayed, optional)
|
||||
missing module named numpy._core.zeros - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.void - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.vecmat - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.vecdot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.ushort - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.unsignedinteger - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.ulonglong - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.ulong - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.uintp - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.uintc - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.uint64 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.uint32 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.uint16 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.uint - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.ubyte - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.trunc - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.true_divide - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.transpose - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._function_base_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.trace - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.timedelta64 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.tensordot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.tanh - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.tan - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.swapaxes - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.sum - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.subtract - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.str_ - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.square - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.sqrt - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy._core.spacing - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.sort - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.sinh - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.single - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.signedinteger - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.signbit - imported by numpy._core (conditional), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.sign - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.short - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.rint - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.right_shift - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.remainder - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.reciprocal - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy._core.radians - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.rad2deg - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.prod - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.power - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.positive - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.pi - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.outer - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.ones - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.object_ - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.number - imported by numpy._core (conditional), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.not_equal - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.nextafter - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.newaxis - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.negative - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.ndarray - imported by numpy._core (top-level), numpy.lib._utils_impl (top-level), numpy (conditional), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy._core.multiply - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.moveaxis - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.modf - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.mod - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.minimum - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.maximum - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.matvec - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.matrix_transpose - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.matmul - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.longlong - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.longdouble - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.long - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.logical_xor - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.logical_or - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.logical_not - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.logical_and - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.logaddexp2 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.logaddexp - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.log10 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.log2 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.log1p - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.log - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.linspace - imported by numpy._core (top-level), numpy.lib._index_tricks_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.less_equal - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.less - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.left_shift - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.ldexp - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.lcm - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.isscalar - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.isnan - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.isfinite - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.intp - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy._array_api_info (top-level), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy._core.integer - imported by numpy._core (conditional), numpy (conditional), numpy.fft._helper (top-level)
|
||||
missing module named numpy._core.intc - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.int64 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.int32 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.int16 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.int8 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.inf - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.inexact - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.iinfo - imported by numpy._core (top-level), numpy.lib._twodim_base_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.hypot - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.hstack - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.heaviside - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.half - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.greater_equal - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.greater - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.gcd - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.frompyfunc - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.frexp - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.fmod - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.fmin - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.fmax - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.floor_divide - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.floor - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.floating - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.float_power - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.float32 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy._core.float16 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.finfo - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.fabs - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.expm1 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.exp2 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.exp - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.euler_gamma - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.errstate - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.equal - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.empty_like - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy._core.empty - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.fft._helper (top-level), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy._core.e - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.double - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.dot - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.divmod - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.divide - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.diagonal - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.degrees - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.deg2rad - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.datetime64 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.csingle - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.cross - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.count_nonzero - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.cosh - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.cos - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.copysign - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.conjugate - imported by numpy._core (conditional), numpy (conditional), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy._core.conj - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.complexfloating - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.complex64 - imported by numpy._core (conditional), numpy (conditional), numpy._array_api_info (top-level)
|
||||
missing module named numpy._core.clongdouble - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.character - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.ceil - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.cdouble - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.cbrt - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.bytes_ - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.byte - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.bool_ - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.bitwise_xor - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.bitwise_or - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.bitwise_count - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.bitwise_and - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.atleast_3d - imported by numpy._core (top-level), numpy.lib._shape_base_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.atleast_2d - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.atleast_1d - imported by numpy._core (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional)
|
||||
missing module named numpy._core.asarray - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._array_utils_impl (top-level), numpy (conditional), numpy.fft._helper (top-level), numpy.fft._pocketfft (top-level)
|
||||
missing module named numpy._core.asanyarray - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.array - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy.lib._polynomial_impl (top-level), numpy (conditional), numpy.testing._private.utils (top-level)
|
||||
missing module named numpy._core.argsort - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.arctanh - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.arctan2 - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.arctan - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.arcsinh - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.arcsin - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.arccosh - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.arccos - imported by numpy._core (conditional), numpy (conditional)
|
||||
missing module named numpy._core.amin - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.amax - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named numpy._core.all - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional), numpy.testing._private.utils (delayed)
|
||||
missing module named numpy._core.add - imported by numpy._core (top-level), numpy.linalg._linalg (top-level), numpy (conditional)
|
||||
missing module named yaml - imported by numpy.__config__ (delayed)
|
||||
missing module named numpy._distributor_init_local - imported by numpy (optional), numpy._distributor_init (optional)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,81 @@
|
|||
@echo off
|
||||
setlocal
|
||||
cd /d "%~dp0"
|
||||
|
||||
echo ============================================================
|
||||
echo BUILD MASKREVIEWER WINDOWS
|
||||
echo ============================================================
|
||||
echo.
|
||||
|
||||
where py >nul 2>nul
|
||||
if %errorlevel%==0 (
|
||||
set PY=py
|
||||
) else (
|
||||
set PY=python
|
||||
)
|
||||
|
||||
%PY% --version
|
||||
if errorlevel 1 (
|
||||
echo.
|
||||
echo [ERRO] Python nao encontrado.
|
||||
echo Instale Python 3.11 ou 3.12 para Windows e tente novamente.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist ".build_venv\Scripts\python.exe" (
|
||||
echo [1/4] Criando ambiente de build...
|
||||
%PY% -m venv .build_venv
|
||||
if errorlevel 1 goto :erro
|
||||
)
|
||||
|
||||
call ".build_venv\Scripts\activate.bat"
|
||||
|
||||
echo [2/4] Instalando dependencias de build...
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install pyinstaller numpy opencv-python
|
||||
if errorlevel 1 goto :erro
|
||||
|
||||
echo [3/4] Limpando builds antigos...
|
||||
if exist build rmdir /s /q build
|
||||
if exist dist rmdir /s /q dist
|
||||
if exist MaskReviewer.spec del /q MaskReviewer.spec
|
||||
|
||||
echo [4/4] Gerando EXE...
|
||||
python -m PyInstaller ^
|
||||
--noconfirm ^
|
||||
--clean ^
|
||||
--onedir ^
|
||||
--windowed ^
|
||||
--name MaskReviewer ^
|
||||
--collect-all cv2 ^
|
||||
MaskReviewer.py
|
||||
|
||||
if errorlevel 1 goto :erro
|
||||
|
||||
echo.
|
||||
echo ============================================================
|
||||
echo BUILD CONCLUIDO
|
||||
echo ============================================================
|
||||
echo Pasta gerada:
|
||||
echo %CD%\dist\MaskReviewer
|
||||
echo.
|
||||
echo Coloque ao lado do MaskReviewer.exe:
|
||||
echo labelmap.txt
|
||||
echo group\
|
||||
echo.
|
||||
echo Estrutura final recomendada:
|
||||
echo MaskReviewer\
|
||||
echo MaskReviewer.exe
|
||||
echo _internal\
|
||||
echo labelmap.txt
|
||||
echo group\
|
||||
echo.
|
||||
pause
|
||||
exit /b 0
|
||||
|
||||
:erro
|
||||
echo.
|
||||
echo [ERRO] Falha no build.
|
||||
pause
|
||||
exit /b 1
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
@echo off
|
||||
setlocal
|
||||
cd /d "%~dp0"
|
||||
|
||||
where py >nul 2>nul
|
||||
if %errorlevel%==0 (
|
||||
set PY=py
|
||||
) else (
|
||||
set PY=python
|
||||
)
|
||||
|
||||
%PY% -c "import cv2, numpy" >nul 2>nul
|
||||
if errorlevel 1 (
|
||||
echo Instalando numpy e opencv-python...
|
||||
%PY% -m pip install numpy opencv-python
|
||||
)
|
||||
|
||||
%PY% MaskReviewer.py
|
||||
if errorlevel 1 pause
|
||||
|
|
@ -8,7 +8,8 @@ Exporta o checkpoint PyTorch do SegFormer Multi-Head OAK-FCC-3 para ONNX.
|
|||
|
||||
Exemplo:
|
||||
|
||||
python _10_export_onnx.py --config config.json --checkpoint backup/segformer_b1/2026_08_17/stacked_raw5_ndvi_ndre/best_score.pt --out backup/segformer_b1/2026_08_17/stacked_raw5_ndvi_ndre/best_score.onnx --include-norm --postprocess argmax_fullres
|
||||
python .\_10_export_onnx.py --config config.json --checkpoint backup/segformer_b1/2026_08_17/stacked_raw5_ndvi_ndre/best_score.pt --out backup/segformer_b1/2026_08_17/stacked_raw5_ndvi_ndre/best_score.onnx --include-norm --postprocess argmax_fullres
|
||||
python .\_10_export_onnx.py --config .\config.json --train-script .\_8_train_multihead_v2.py --opset 17 --device cuda --include-norm --postprocess argmax_fullres
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ para o SegFormer OAK-FCC-3 Multi-Head.
|
|||
Exemplo:
|
||||
|
||||
python _11_validate_onnx.py --config config.json --max_samples 20 --device cuda --onnx_provider cuda --torch_no_amp
|
||||
python .\_11_validate_onnx.py --config .\config.json --train-script .\_8_train_multihead_v2.py --max_samples 50 --device cuda --onnx_provider cuda --torch_no_amp
|
||||
|
||||
Para validar o ONNX com saída já redimensionada:
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -25,10 +25,7 @@ Mostra:
|
|||
|
||||
Exemplo:
|
||||
|
||||
python .\\_9_test_infer_multihead.py ^
|
||||
--config config.json ^
|
||||
--split_folder val ^
|
||||
--ckpt backup\segformer_b1\test_multi\stacked_raw5_multihead\best_score.pt
|
||||
python .\\_9_test_multihead.py --config config.json --split_folder val --ckpt backup\segformer_b1\test_multi\stacked_raw5_multihead\best_score.pt
|
||||
|
||||
Controles:
|
||||
D / seta direita : próxima amostra
|
||||
|
|
@ -634,7 +631,20 @@ def collect_samples(root: Path, heads_config: Dict[str, dict], require_masks: bo
|
|||
missing = []
|
||||
|
||||
for head_name, hcfg in heads_config.items():
|
||||
mask_dir = group_dir / str(hcfg.get("mask_dir", "masks"))
|
||||
mask_dir_name = str(hcfg.get("mask_dir", "masks"))
|
||||
is_derived = (
|
||||
bool(hcfg.get("derived", False))
|
||||
or mask_dir_name == "__derived_target__"
|
||||
)
|
||||
|
||||
# Heads derivadas não possuem máscara física.
|
||||
# O GT target será construído posteriormente a partir de:
|
||||
# vegetation == 1 AND cana == 0.
|
||||
if is_derived:
|
||||
masks[head_name] = None
|
||||
continue
|
||||
|
||||
mask_dir = group_dir / mask_dir_name
|
||||
mask_path = mask_dir / f"{base}.npy"
|
||||
|
||||
if mask_path.exists():
|
||||
|
|
@ -2002,14 +2012,25 @@ def main():
|
|||
sample_metrics[head_name] = {"iou": iou, "miou": miou, "acc": acc}
|
||||
metric_lines.append(f"{head_name}: mIoU={miou:.3f} acc={acc:.3f}")
|
||||
|
||||
if gt_target is not None:
|
||||
cm_t = confusion_matrix_np(pred_target, gt_target, 2, ignore_id)
|
||||
if gt_target is not None and pred_target_op is not None:
|
||||
cm_t = confusion_matrix_np(pred_target_op, gt_target, 2, ignore_id)
|
||||
iou_t, miou_t, acc_t = metrics_from_cm(cm_t)
|
||||
sample_metrics["target_op"] = {"iou": iou_t, "miou": miou_t, "acc": acc_t}
|
||||
metric_lines.append(f"target_op: IoU_alvo={iou_t[1]:.3f} acc={acc_t:.3f}")
|
||||
|
||||
sample_metrics["target_op"] = {
|
||||
"iou": iou_t,
|
||||
"miou": miou_t,
|
||||
"acc": acc_t,
|
||||
}
|
||||
|
||||
metric_lines.append(
|
||||
f"target_op: IoU_alvo={iou_t[1]:.3f} acc={acc_t:.3f}"
|
||||
)
|
||||
|
||||
if "target" in sample_metrics:
|
||||
iou_head = sample_metrics["target"]["iou"]
|
||||
metric_lines.append(f"target_head: IoU_alvo={iou_head[1]:.3f}")
|
||||
metric_lines.append(
|
||||
f"target_head: IoU_alvo={iou_head[1]:.3f}"
|
||||
)
|
||||
|
||||
if idx not in visited:
|
||||
for head_name, pred in preds.items():
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,18 +1,18 @@
|
|||
{
|
||||
"camera": "oak-fcc-3",
|
||||
"modelo": "segformer_b1",
|
||||
"model_name": "2026_08_18",
|
||||
"model_name": "2026_08_28_linear_demosaic",
|
||||
"main_class_name": "erva",
|
||||
"es_classes": "",
|
||||
"model_to_use": "geral",
|
||||
"raw_size": [1280, 800],
|
||||
"resolucao": [640, 400],
|
||||
"resolucao": [960, 600],
|
||||
"roi_inicio": 0.0,
|
||||
"roi_tamanho": 1.0,
|
||||
"shaves": 3,
|
||||
"source_channels": ["R", "G", "B", "RE", "NIR"],
|
||||
"channels": 7,
|
||||
"input_channels": ["R", "G", "B", "RE", "NIR", "NDVI", "NDRE"],
|
||||
"channels": 5,
|
||||
"input_channels": ["R", "G", "B", "RE", "NIR"],
|
||||
"derived_channels": {
|
||||
"epsilon": 1e-6,
|
||||
"clip_min": -1.0,
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
},
|
||||
"backbone": "nvidia/mit-b1",
|
||||
"fusion_mode": "stacked",
|
||||
"stats_source_tag": "stacked_raw5_ndvi_ndre",
|
||||
"stats_source_tag": "stacked_raw5",
|
||||
"module_params_json": "calibration/module_params.json",
|
||||
"ckpt_test": "best_score",
|
||||
"multi_head": true,
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
"mask_dir": "masks_vegetation",
|
||||
"classes": {"background": 0, "vegetation": 1},
|
||||
"ignore_index": 255,
|
||||
"loss_weight": 0.20
|
||||
"loss_weight": 0.15
|
||||
},
|
||||
"cana": {
|
||||
"enabled": true,
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
"mask_dir": "masks_cana",
|
||||
"classes": {"not_cana": 0, "cana": 1},
|
||||
"ignore_index": 255,
|
||||
"loss_weight": 0.25
|
||||
"loss_weight": 0.35
|
||||
},
|
||||
"target": {
|
||||
"enabled": true,
|
||||
|
|
@ -59,23 +59,158 @@
|
|||
"mask_dir": "__derived_target__",
|
||||
"classes": {"background": 0, "target": 1},
|
||||
"ignore_index": 255,
|
||||
"loss_weight": 0.35,
|
||||
"loss_weight": 0.30,
|
||||
"derived": true
|
||||
}
|
||||
},
|
||||
"target_distillation": {
|
||||
"enabled": true,
|
||||
"hard_weight": 0.85,
|
||||
"distill_weight": 0.15,
|
||||
"rampup_enabled": true,
|
||||
"start_epoch": 8,
|
||||
"rampup_epochs": 12,
|
||||
"w_sem_erva": 0.45,
|
||||
"w_veg_not_cana": 0.35,
|
||||
"w_veg_suppressed": 0.20,
|
||||
"cana_suppression_power": 1.5,
|
||||
"teacher_min": 0.0,
|
||||
"teacher_max": 1.0,
|
||||
"detach_teacher": true
|
||||
"training_v2": {
|
||||
"model": {
|
||||
"decoder_mode": "shared_light",
|
||||
"spectral_input_init": "zero_extra"
|
||||
},
|
||||
"augmentation": {
|
||||
"enabled": true,
|
||||
"horizontal_flip_p": 0.5,
|
||||
"vertical_flip_p": 0.0,
|
||||
"affine_p": 0.7,
|
||||
"rotate_deg": 5.0,
|
||||
"scale_min": 0.9,
|
||||
"scale_max": 1.1,
|
||||
"translate_frac": 0.04,
|
||||
"crop_p": 0.45,
|
||||
"crop_scale_min": 0.7,
|
||||
"crop_scale_max": 1.0,
|
||||
"crop_focus_target_p": 0.55,
|
||||
"crop_focus_cana_p": 0.25,
|
||||
"global_gain_p": 0.35,
|
||||
"global_gain_min": 0.92,
|
||||
"global_gain_max": 1.08,
|
||||
"band_gain_p": 0.25,
|
||||
"band_gain_min": 0.96,
|
||||
"band_gain_max": 1.04,
|
||||
"rgb_gamma_p": 0.2,
|
||||
"rgb_gamma_min": 0.94,
|
||||
"rgb_gamma_max": 1.06,
|
||||
"noise_p": 0.2,
|
||||
"noise_sigma_min": 0.001,
|
||||
"noise_sigma_max": 0.008,
|
||||
"blur_p": 0.12,
|
||||
"blur_kernel": 3,
|
||||
"sensor_channel_dropout_p": 0.0,
|
||||
"clip_physical": true
|
||||
},
|
||||
"sampler": {
|
||||
"mode": "diverse",
|
||||
"samples_per_epoch": 0,
|
||||
"tiny_target_pct": 0.005,
|
||||
"small_target_pct": 0.02,
|
||||
"medium_target_pct": 0.1
|
||||
},
|
||||
"class_weighting": {
|
||||
"method": "log_inverse",
|
||||
"log_offset": 1.02,
|
||||
"power": 0.5,
|
||||
"min_weight": 0.25,
|
||||
"max_weight": 4.0
|
||||
},
|
||||
"loss": {
|
||||
"dice_reduction": "per_image",
|
||||
"dice_smooth": 1.0,
|
||||
"boundary_weight": 0.0,
|
||||
"ohem_ratio": 0.0,
|
||||
"safety": {
|
||||
"enabled": true,
|
||||
"weight": 0.08,
|
||||
"cana_weight": 1.0,
|
||||
"ground_weight": 0.2
|
||||
}
|
||||
},
|
||||
"optimizer": {
|
||||
"encoder_lr": null,
|
||||
"patch_lr_mult": 2.0,
|
||||
"heads_lr_mult": 5.0,
|
||||
"weight_decay": null,
|
||||
"no_decay_bias": true,
|
||||
"no_decay_norm": true,
|
||||
"betas": [
|
||||
0.9,
|
||||
0.999
|
||||
],
|
||||
"eps": 1e-08
|
||||
},
|
||||
"scheduler": {
|
||||
"mode": "poly",
|
||||
"warmup_ratio": 0.05,
|
||||
"warmup_start_factor": 0.1,
|
||||
"poly_power": 1.0,
|
||||
"min_lr_ratio": 0.02
|
||||
},
|
||||
"optimization": {
|
||||
"grad_clip_norm": 1.0,
|
||||
"matmul_precision": "high",
|
||||
"cudnn_benchmark": true,
|
||||
"persistent_workers": true,
|
||||
"prefetch_factor": 2
|
||||
},
|
||||
"target_distillation": {
|
||||
"enabled": false,
|
||||
"mode": "cross_head",
|
||||
"start_epoch": 8,
|
||||
"rampup_epochs": 12,
|
||||
"hard_weight": 0.75,
|
||||
"distill_weight": 0.25,
|
||||
"teacher_confidence_min": 0.6,
|
||||
"detach_teacher": true,
|
||||
"w_sem_erva": 0.45,
|
||||
"w_veg_not_cana": 0.35,
|
||||
"w_veg_suppressed": 0.2,
|
||||
"cana_suppression_power": 1.5
|
||||
},
|
||||
"metrics": {
|
||||
"target_thresholds": [
|
||||
0.3,
|
||||
0.4,
|
||||
0.5,
|
||||
0.6,
|
||||
0.7,
|
||||
0.8,
|
||||
0.9
|
||||
],
|
||||
"ece_bins": 15,
|
||||
"scenario_metrics": true,
|
||||
"group_metrics": true,
|
||||
"rich_train_metrics": false,
|
||||
"operational_threshold": {
|
||||
"max_cana_spray_rate": 0.02,
|
||||
"max_ground_spray_rate": 0.03,
|
||||
"max_weed_miss_rate": 0.2,
|
||||
"score_weights": {
|
||||
"target_iou": 0.35,
|
||||
"target_f1": 0.2,
|
||||
"cana_safety": 0.25,
|
||||
"ground_safety": 0.1,
|
||||
"weed_recall": 0.1
|
||||
}
|
||||
}
|
||||
},
|
||||
"selection_score": {
|
||||
"target_iou": 0.4,
|
||||
"cana_iou": 0.2,
|
||||
"target_f1": 0.1,
|
||||
"vegetation_miou": 0.1,
|
||||
"semantic_miou": 0.05,
|
||||
"cana_safety": 0.15
|
||||
},
|
||||
"checkpoint": {
|
||||
"early_stop_min_delta": 0.0005,
|
||||
"save_best_safety": true,
|
||||
"save_best_legacy": true,
|
||||
"save_best_operational": true
|
||||
},
|
||||
"data": {
|
||||
"validate_npy_content": true,
|
||||
"skip_corrupt_samples": true,
|
||||
"max_corrupt_fraction": 0.005
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,620 +0,0 @@
|
|||
import argparse
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
try:
|
||||
import torch
|
||||
except Exception:
|
||||
torch = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Ajuste de import local
|
||||
# ============================================================
|
||||
|
||||
THIS_FILE = Path(__file__).resolve()
|
||||
|
||||
# Esperado:
|
||||
# .../Python/Scripts/workers/camera_worker/oak_fcc3_core/benchmark_raw_bruto_scientific.py
|
||||
WORKERS_DIR = THIS_FILE.parents[2]
|
||||
|
||||
if str(WORKERS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(WORKERS_DIR))
|
||||
|
||||
from camera_worker.oak_fcc3_core.oak_fcc3_client import OakFcc3Client
|
||||
|
||||
try:
|
||||
from camera_worker.oak_fcc3_core.segformer_service import MultiSpecSegformerService
|
||||
except Exception:
|
||||
MultiSpecSegformerService = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Utils
|
||||
# ============================================================
|
||||
|
||||
def now_ms():
|
||||
return time.perf_counter() * 1000.0
|
||||
|
||||
|
||||
def mean(xs):
|
||||
return float(np.mean(xs)) if xs else 0.0
|
||||
|
||||
|
||||
def p95(xs):
|
||||
return float(np.percentile(xs, 95)) if xs else 0.0
|
||||
|
||||
|
||||
def maxv(xs):
|
||||
return float(np.max(xs)) if xs else 0.0
|
||||
|
||||
|
||||
def last_mean(xs, n=30):
|
||||
return float(np.mean(xs[-n:])) if xs else 0.0
|
||||
|
||||
|
||||
def last_max(xs, n=30):
|
||||
return float(np.max(xs[-n:])) if xs else 0.0
|
||||
|
||||
|
||||
def load_json_if_exists(path):
|
||||
if not path:
|
||||
return None
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def parse_float_list(s, expected=5, default=None):
|
||||
if s is None:
|
||||
return default
|
||||
|
||||
vals = [float(x.strip()) for x in str(s).split(",") if x.strip() != ""]
|
||||
|
||||
if len(vals) != expected:
|
||||
raise ValueError(f"Esperado {expected} valores, veio {len(vals)}: {s}")
|
||||
|
||||
return np.array(vals, dtype=np.float32)
|
||||
|
||||
|
||||
def extract_mean_std_from_model_config(cfg):
|
||||
if not isinstance(cfg, dict):
|
||||
return None, None
|
||||
|
||||
mean_cfg = cfg.get("mean") or cfg.get("channel_mean") or cfg.get("norm_mean")
|
||||
std_cfg = cfg.get("std") or cfg.get("channel_std") or cfg.get("norm_std")
|
||||
|
||||
norm = cfg.get("normalization") or cfg.get("norm") or {}
|
||||
|
||||
if mean_cfg is None and isinstance(norm, dict):
|
||||
mean_cfg = norm.get("mean") or norm.get("channel_mean")
|
||||
|
||||
if std_cfg is None and isinstance(norm, dict):
|
||||
std_cfg = norm.get("std") or norm.get("channel_std")
|
||||
|
||||
if mean_cfg is None or std_cfg is None:
|
||||
return None, None
|
||||
|
||||
mean_arr = np.array(mean_cfg, dtype=np.float32)
|
||||
std_arr = np.array(std_cfg, dtype=np.float32)
|
||||
|
||||
if mean_arr.size != 5 or std_arr.size != 5:
|
||||
return None, None
|
||||
|
||||
return mean_arr, std_arr
|
||||
|
||||
|
||||
def tensor_stats(tensor):
|
||||
names = ["R", "G", "B", "RE", "NIR"]
|
||||
out = {}
|
||||
|
||||
for i, name in enumerate(names):
|
||||
ch = tensor[i].astype(np.float32)
|
||||
out[name] = {
|
||||
"min": float(np.min(ch)),
|
||||
"p01": float(np.percentile(ch, 1)),
|
||||
"p50": float(np.percentile(ch, 50)),
|
||||
"p99": float(np.percentile(ch, 99)),
|
||||
"max": float(np.max(ch)),
|
||||
"mean": float(np.mean(ch)),
|
||||
"std": float(np.std(ch)),
|
||||
}
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def print_tensor_stats(label, tensor):
|
||||
print("============================================")
|
||||
print(f"[{label}] TENSOR")
|
||||
print(f"shape={tensor.shape} dtype={tensor.dtype}")
|
||||
|
||||
stats = tensor_stats(tensor)
|
||||
for ch, s in stats.items():
|
||||
print(
|
||||
f"{ch:>3} | "
|
||||
f"min={s['min']:.4f} "
|
||||
f"p01={s['p01']:.4f} "
|
||||
f"p50={s['p50']:.4f} "
|
||||
f"p99={s['p99']:.4f} "
|
||||
f"max={s['max']:.4f} "
|
||||
f"mean={s['mean']:.4f} "
|
||||
f"std={s['std']:.4f}"
|
||||
)
|
||||
|
||||
print("============================================")
|
||||
|
||||
|
||||
def to_u8_01(arr):
|
||||
arr = np.asarray(arr, dtype=np.float32)
|
||||
arr = np.nan_to_num(arr, nan=0.0, posinf=1.0, neginf=0.0)
|
||||
arr = np.clip(arr, 0.0, 1.0)
|
||||
return (arr * 255.0).astype(np.uint8)
|
||||
|
||||
|
||||
def make_panel(tensor):
|
||||
rgb = np.stack([tensor[0], tensor[1], tensor[2]], axis=2)
|
||||
rgb_bgr = cv2.cvtColor(to_u8_01(rgb), cv2.COLOR_RGB2BGR)
|
||||
|
||||
re_bgr = cv2.cvtColor(to_u8_01(tensor[3]), cv2.COLOR_GRAY2BGR)
|
||||
nir_bgr = cv2.cvtColor(to_u8_01(tensor[4]), cv2.COLOR_GRAY2BGR)
|
||||
|
||||
false_rgb = np.stack(
|
||||
[
|
||||
tensor[4], # visual R = NIR
|
||||
tensor[3], # visual G = RE
|
||||
tensor[0], # visual B = R real
|
||||
],
|
||||
axis=2,
|
||||
)
|
||||
false_bgr = cv2.cvtColor(to_u8_01(false_rgb), cv2.COLOR_RGB2BGR)
|
||||
|
||||
def title(img, text):
|
||||
h, w = img.shape[:2]
|
||||
bar_h = 34
|
||||
bar = np.zeros((bar_h, w, 3), dtype=np.uint8)
|
||||
cv2.putText(
|
||||
bar,
|
||||
text,
|
||||
(10, 24),
|
||||
cv2.FONT_HERSHEY_SIMPLEX,
|
||||
0.7,
|
||||
(255, 255, 255),
|
||||
2,
|
||||
cv2.LINE_AA,
|
||||
)
|
||||
return np.vstack([bar, img])
|
||||
|
||||
rgb_bgr = title(rgb_bgr, "RGB")
|
||||
re_bgr = title(re_bgr, "RE")
|
||||
nir_bgr = title(nir_bgr, "NIR")
|
||||
false_bgr = title(false_bgr, "Falso color NIR/RE/R")
|
||||
|
||||
top = np.hstack([rgb_bgr, re_bgr])
|
||||
bottom = np.hstack([nir_bgr, false_bgr])
|
||||
|
||||
return np.vstack([top, bottom])
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Benchmark processor
|
||||
# ============================================================
|
||||
|
||||
class ScientificBenchmark:
|
||||
def __init__(self, args):
|
||||
self.args = args
|
||||
self.target_size = (int(args.width), int(args.height))
|
||||
|
||||
self.model_cfg = load_json_if_exists(args.model_config_json)
|
||||
mean_cfg, std_cfg = extract_mean_std_from_model_config(self.model_cfg)
|
||||
|
||||
if args.model_mean is not None:
|
||||
self.mean = parse_float_list(args.model_mean, expected=5)
|
||||
elif mean_cfg is not None:
|
||||
self.mean = mean_cfg
|
||||
else:
|
||||
self.mean = np.array([0.5, 0.5, 0.5, 0.5, 0.5], dtype=np.float32)
|
||||
|
||||
if args.model_std is not None:
|
||||
self.std = parse_float_list(args.model_std, expected=5)
|
||||
elif std_cfg is not None:
|
||||
self.std = std_cfg
|
||||
else:
|
||||
self.std = np.array([0.25, 0.25, 0.25, 0.25, 0.25], dtype=np.float32)
|
||||
|
||||
self.mean_chw = self.mean[:, None, None].astype(np.float32)
|
||||
self.std_chw = self.std[:, None, None].astype(np.float32)
|
||||
|
||||
self.device = None
|
||||
if torch is not None and torch.cuda.is_available():
|
||||
self.device = torch.device("cuda")
|
||||
elif torch is not None:
|
||||
self.device = torch.device("cpu")
|
||||
|
||||
self.model_svc = None
|
||||
|
||||
if args.run_model:
|
||||
if MultiSpecSegformerService is None:
|
||||
raise RuntimeError("MultiSpecSegformerService não pôde ser importado.")
|
||||
|
||||
if not isinstance(self.model_cfg, dict):
|
||||
raise RuntimeError("--run_model requer --model_config_json válido.")
|
||||
|
||||
self.model_svc = MultiSpecSegformerService(
|
||||
model_config=self.model_cfg,
|
||||
mostrar_log=print,
|
||||
)
|
||||
|
||||
dummy = np.zeros((5, args.height, args.width), dtype=np.float32)
|
||||
|
||||
for _ in range(max(0, int(args.warmup_model))):
|
||||
self.model_svc.infer_tensor_fast(dummy, keep_probs=False)
|
||||
|
||||
print(f"[BENCH] Warmup modelo concluído: {args.warmup_model}x")
|
||||
|
||||
def process_once(self, client):
|
||||
"""
|
||||
Mede uma iteração completa do fluxo científico.
|
||||
"""
|
||||
times = {
|
||||
"capture_ms": 0.0,
|
||||
"decode_ms": 0.0,
|
||||
"controller_ms": 0.0,
|
||||
"fuse_total_ms": 0.0,
|
||||
"fuse_dark_ms": 0.0,
|
||||
"fuse_radnorm_ms": 0.0,
|
||||
"fuse_flat_ms": 0.0,
|
||||
"fuse_prepare_ms": 0.0,
|
||||
"fuse_warp_ms": 0.0,
|
||||
"fuse_crop_resize_ms": 0.0,
|
||||
"fuse_concat_ms": 0.0,
|
||||
"model_norm_ms": 0.0,
|
||||
"torch_ms": 0.0,
|
||||
"infer_ms": 0.0,
|
||||
"total_ms": 0.0,
|
||||
"sync_dt_ms": 0.0,
|
||||
}
|
||||
|
||||
t_total0 = now_ms()
|
||||
|
||||
# ========================================================
|
||||
# 1. Captura RAW_BRUTO
|
||||
# ========================================================
|
||||
t0 = now_ms()
|
||||
raw_frame, raw_meta = client.get_next_raw_frame(timeout=self.args.timeout)
|
||||
times["capture_ms"] = now_ms() - t0
|
||||
|
||||
#cp = raw_meta.get("capture_perf", {})
|
||||
#print(
|
||||
# "[CAP_ASYNC] "
|
||||
# f"get_wait={cp.get('async_get_wait_ms',0):.2f}ms "
|
||||
# f"age={cp.get('async_packet_age_ms',0):.2f}ms "
|
||||
# f"seq={cp.get('async_packet_seq')} "
|
||||
# f"thread_wait={cp.get('wait_total_ms',0):.2f}ms "
|
||||
# f"sleep={cp.get('sleep_ms',0):.2f}ms/{cp.get('sleep_count',0)} "
|
||||
# f"drain={cp.get('drain_total_ms',0):.2f}ms "
|
||||
# f"copy={cp.get('drain_frombuffer_copy_ms',0):.2f}ms "
|
||||
# f"status={cp.get('async_status',{})}"
|
||||
#)
|
||||
|
||||
times["sync_dt_ms"] = float(raw_meta.get("sync_dt_ms", 0.0) or 0.0)
|
||||
|
||||
# ========================================================
|
||||
# 2. Decode RAW10 packed -> float científico por câmera
|
||||
# ========================================================
|
||||
t0 = now_ms()
|
||||
decoded = client.decode_stream_cameras(raw_frame, raw_meta)
|
||||
times["decode_ms"] = now_ms() - t0
|
||||
|
||||
# ========================================================
|
||||
# 3. RadiometricController update, se ativo
|
||||
# Isso NÃO é a radiometric_normalization do tensor.
|
||||
# É o controlador de exposição/ganho.
|
||||
# ========================================================
|
||||
t0 = now_ms()
|
||||
client.update_radiometry(decoded, raw_meta)
|
||||
times["controller_ms"] = now_ms() - t0
|
||||
|
||||
# ========================================================
|
||||
# 4. Fusão científica no RawProcessorCore
|
||||
# dark + radnorm + flat + homografia + crop/resize + concat
|
||||
# ========================================================
|
||||
t0 = now_ms()
|
||||
tensor = client.build_infer_tensor_from_decoded(
|
||||
decoded=decoded,
|
||||
meta=raw_meta,
|
||||
channels_expected=5,
|
||||
target_size=self.target_size,
|
||||
)
|
||||
times["fuse_total_ms"] = now_ms() - t0
|
||||
|
||||
# Pega detalhamento interno do core
|
||||
try:
|
||||
perf = (client.core.last_fusion_result or {}).get("perf", {}) or {}
|
||||
times["fuse_dark_ms"] = float(perf.get("dark_ms", 0.0) or 0.0)
|
||||
times["fuse_radnorm_ms"] = float(perf.get("radnorm_ms", 0.0) or 0.0)
|
||||
times["fuse_flat_ms"] = float(perf.get("flat_ms", 0.0) or 0.0)
|
||||
times["fuse_prepare_ms"] = float(perf.get("prepare_ms", 0.0) or 0.0)
|
||||
times["fuse_warp_ms"] = float(perf.get("warp_total_ms", 0.0) or 0.0)
|
||||
times["fuse_crop_resize_ms"] = float(perf.get("crop_resize_ms", 0.0) or 0.0)
|
||||
times["fuse_concat_ms"] = float(perf.get("concat_ms", 0.0) or 0.0)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ========================================================
|
||||
# 5. Normalização do modelo, opcional
|
||||
# ========================================================
|
||||
if self.args.simulate_model_norm:
|
||||
t0 = now_ms()
|
||||
tensor = (tensor - self.mean_chw) / np.maximum(self.std_chw, 1e-6)
|
||||
tensor = np.ascontiguousarray(tensor, dtype=np.float32)
|
||||
times["model_norm_ms"] = now_ms() - t0
|
||||
|
||||
# ========================================================
|
||||
# 6. Transferência para torch/cuda, opcional
|
||||
# ========================================================
|
||||
if self.args.to_torch:
|
||||
if torch is None:
|
||||
raise RuntimeError("--to_torch requer torch instalado.")
|
||||
|
||||
t0 = now_ms()
|
||||
x = torch.from_numpy(tensor).unsqueeze(0).to(self.device, non_blocking=True)
|
||||
|
||||
if self.device is not None and self.device.type == "cuda":
|
||||
torch.cuda.synchronize()
|
||||
|
||||
times["torch_ms"] = now_ms() - t0
|
||||
|
||||
# ========================================================
|
||||
# 7. Inferência real, opcional
|
||||
# ========================================================
|
||||
pred = None
|
||||
if self.args.run_model:
|
||||
t0 = now_ms()
|
||||
pred = self.model_svc.infer_tensor_fast(tensor, keep_probs=False)
|
||||
times["infer_ms"] = now_ms() - t0
|
||||
|
||||
times["total_ms"] = now_ms() - t_total0
|
||||
|
||||
return tensor, pred, raw_frame, raw_meta, decoded, times
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Main
|
||||
# ============================================================
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(
|
||||
description="Benchmark científico OAK-FCC-3 RAW_BRUTO -> tensor multiespectral final."
|
||||
)
|
||||
|
||||
ap.add_argument(
|
||||
"--module_params",
|
||||
default=r"C:\ZendionInc\agrobot_base\Python\OAK\datasets\oak-fcc-3\calibration\module_params.json",
|
||||
help="Caminho do module_params.json.",
|
||||
)
|
||||
|
||||
ap.add_argument("--width", type=int, default=1024, help="Largura final do tensor.")
|
||||
ap.add_argument("--height", type=int, default=640, help="Altura final do tensor.")
|
||||
ap.add_argument("--fps", type=float, default=30.0)
|
||||
ap.add_argument("--seconds", type=float, default=20.0)
|
||||
ap.add_argument("--timeout", type=float, default=3.0)
|
||||
ap.add_argument("--warmup", type=int, default=5)
|
||||
ap.add_argument("--mx_id", default=None)
|
||||
ap.add_argument("--sync_tolerance_ms", type=float, default=25.0)
|
||||
ap.add_argument("--buffer_size", type=int, default=8)
|
||||
|
||||
ap.add_argument("--simulate_model_norm", action="store_true")
|
||||
ap.add_argument("--model_mean", default=None)
|
||||
ap.add_argument("--model_std", default=None)
|
||||
ap.add_argument("--to_torch", action="store_true")
|
||||
|
||||
ap.add_argument("--run_model", action="store_true")
|
||||
ap.add_argument("--model_config_json", default=None)
|
||||
ap.add_argument("--warmup_model", type=int, default=3)
|
||||
|
||||
ap.add_argument("--save_debug", action="store_true")
|
||||
ap.add_argument("--debug_dir", default="raw_bruto_scientific_benchmark")
|
||||
ap.add_argument("--show", action="store_true")
|
||||
ap.add_argument("--display_scale", type=float, default=0.65)
|
||||
|
||||
args = ap.parse_args()
|
||||
|
||||
bench = ScientificBenchmark(args)
|
||||
|
||||
client = OakFcc3Client(
|
||||
width=args.width,
|
||||
height=args.height,
|
||||
fps=args.fps,
|
||||
frame_type="RAW_BRUTO",
|
||||
output_dtype="uint8",
|
||||
capture_mode="TRIPLE",
|
||||
raw_policy="require_triple",
|
||||
module_calibration_json=args.module_params,
|
||||
sync_tolerance_ms=args.sync_tolerance_ms,
|
||||
buffer_size=args.buffer_size,
|
||||
mx_id=args.mx_id,
|
||||
)
|
||||
|
||||
client.core.warmup_numba_raw10_decode()
|
||||
|
||||
samples = {
|
||||
"capture_ms": [],
|
||||
"decode_ms": [],
|
||||
"controller_ms": [],
|
||||
"fuse_total_ms": [],
|
||||
"fuse_dark_ms": [],
|
||||
"fuse_radnorm_ms": [],
|
||||
"fuse_flat_ms": [],
|
||||
"fuse_prepare_ms": [],
|
||||
"fuse_warp_ms": [],
|
||||
"fuse_crop_resize_ms": [],
|
||||
"fuse_concat_ms": [],
|
||||
"model_norm_ms": [],
|
||||
"torch_ms": [],
|
||||
"infer_ms": [],
|
||||
"total_ms": [],
|
||||
"sync_dt_ms": [],
|
||||
}
|
||||
|
||||
n_frames = 0
|
||||
t_start = time.perf_counter()
|
||||
t_last_log = t_start
|
||||
|
||||
last_tensor = None
|
||||
last_meta = None
|
||||
|
||||
try:
|
||||
client.start(print_debug=True)
|
||||
|
||||
# Warmup de câmera/controlador/filas
|
||||
print(f"[BENCH] Warmup frames: {args.warmup}")
|
||||
for _ in range(max(0, int(args.warmup))):
|
||||
try:
|
||||
bench.process_once(client)
|
||||
except Exception as e:
|
||||
print(f"[WARN] warmup falhou: {type(e).__name__}: {e}")
|
||||
time.sleep(0.02)
|
||||
|
||||
print("============================================")
|
||||
print("[BENCH] Iniciando benchmark científico RAW_BRUTO")
|
||||
print(f"target tensor : (5,{args.height},{args.width})")
|
||||
print(f"duration : {args.seconds}s")
|
||||
print("============================================")
|
||||
|
||||
while True:
|
||||
now = time.perf_counter()
|
||||
elapsed = now - t_start
|
||||
|
||||
if elapsed >= args.seconds:
|
||||
break
|
||||
|
||||
try:
|
||||
tensor, pred, raw_frame, raw_meta, decoded, times = bench.process_once(client)
|
||||
except TimeoutError as e:
|
||||
print(f"[TIMEOUT] {e}")
|
||||
continue
|
||||
|
||||
n_frames += 1
|
||||
last_tensor = tensor
|
||||
last_meta = raw_meta
|
||||
|
||||
for k in samples:
|
||||
samples[k].append(float(times.get(k, 0.0) or 0.0))
|
||||
|
||||
if now - t_last_log >= 1.0:
|
||||
elapsed = now - t_start
|
||||
fps = n_frames / max(elapsed, 1e-6)
|
||||
|
||||
print(
|
||||
"[RAW_SCI_PERF] "
|
||||
f"elapsed={elapsed:.1f}s "
|
||||
f"frames={n_frames} "
|
||||
f"fps={fps:.2f} "
|
||||
f"sync={last_mean(samples['sync_dt_ms']):.2f}ms "
|
||||
f"capture={last_mean(samples['capture_ms']):.2f}ms "
|
||||
f"decode={last_mean(samples['decode_ms']):.2f}ms "
|
||||
f"controller={last_mean(samples['controller_ms']):.2f}ms "
|
||||
f"fuse={last_mean(samples['fuse_total_ms']):.2f}ms "
|
||||
f"radnorm={last_mean(samples['fuse_radnorm_ms']):.2f}ms "
|
||||
f"flat={last_mean(samples['fuse_flat_ms']):.2f}ms "
|
||||
f"warp={last_mean(samples['fuse_warp_ms']):.2f}ms "
|
||||
f"crop_resize={last_mean(samples['fuse_crop_resize_ms']):.2f}ms "
|
||||
f"concat={last_mean(samples['fuse_concat_ms']):.2f}ms "
|
||||
f"model_norm={last_mean(samples['model_norm_ms']):.2f}ms "
|
||||
f"torch={last_mean(samples['torch_ms']):.2f}ms "
|
||||
f"infer={last_mean(samples['infer_ms']):.2f}ms "
|
||||
f"total={last_mean(samples['total_ms']):.2f}ms "
|
||||
f"tensor_shape={tuple(tensor.shape)}"
|
||||
)
|
||||
|
||||
t_last_log = now
|
||||
|
||||
elapsed_total = time.perf_counter() - t_start
|
||||
fps_total = n_frames / max(elapsed_total, 1e-6)
|
||||
|
||||
print("============================================")
|
||||
print("RESULTADO FINAL RAW_BRUTO CIENTÍFICO")
|
||||
print(f"elapsed : {elapsed_total:.2f}s")
|
||||
print(f"frames : {n_frames}")
|
||||
print(f"fps : {fps_total:.2f}")
|
||||
print("--------------------------------------------")
|
||||
|
||||
def print_metric(name):
|
||||
xs = samples[name]
|
||||
print(
|
||||
f"{name:18s} "
|
||||
f"mean={mean(xs):8.2f}ms "
|
||||
f"p95={p95(xs):8.2f}ms "
|
||||
f"max={maxv(xs):8.2f}ms"
|
||||
)
|
||||
|
||||
for name in [
|
||||
"sync_dt_ms",
|
||||
"capture_ms",
|
||||
"decode_ms",
|
||||
"controller_ms",
|
||||
"fuse_total_ms",
|
||||
"fuse_dark_ms",
|
||||
"fuse_radnorm_ms",
|
||||
"fuse_flat_ms",
|
||||
"fuse_prepare_ms",
|
||||
"fuse_warp_ms",
|
||||
"fuse_crop_resize_ms",
|
||||
"fuse_concat_ms",
|
||||
"model_norm_ms",
|
||||
"torch_ms",
|
||||
"infer_ms",
|
||||
"total_ms",
|
||||
]:
|
||||
print_metric(name)
|
||||
|
||||
print("============================================")
|
||||
|
||||
if last_tensor is not None:
|
||||
print_tensor_stats("LAST RAW_BRUTO SCI", last_tensor)
|
||||
|
||||
if args.save_debug:
|
||||
debug_dir = Path(args.debug_dir)
|
||||
debug_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
np.save(str(debug_dir / "last_tensor.npy"), last_tensor)
|
||||
|
||||
stats_path = debug_dir / "last_tensor_stats.json"
|
||||
with open(stats_path, "w", encoding="utf-8") as f:
|
||||
json.dump(tensor_stats(last_tensor), f, indent=2, ensure_ascii=False)
|
||||
|
||||
panel = make_panel(last_tensor)
|
||||
cv2.imwrite(str(debug_dir / "last_tensor_panel.png"), panel)
|
||||
|
||||
if last_meta is not None:
|
||||
with open(debug_dir / "last_meta.json", "w", encoding="utf-8") as f:
|
||||
json.dump(last_meta, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"[SAVE] Debug salvo em: {debug_dir}")
|
||||
|
||||
if args.show:
|
||||
panel = make_panel(last_tensor)
|
||||
|
||||
if args.display_scale and abs(args.display_scale - 1.0) > 1e-6:
|
||||
new_w = max(1, int(panel.shape[1] * args.display_scale))
|
||||
new_h = max(1, int(panel.shape[0] * args.display_scale))
|
||||
panel = cv2.resize(panel, (new_w, new_h), interpolation=cv2.INTER_AREA)
|
||||
|
||||
cv2.imshow("RAW_BRUTO scientific tensor", panel)
|
||||
print("[INFO] Pressione qualquer tecla para fechar.")
|
||||
cv2.waitKey(0)
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
finally:
|
||||
try:
|
||||
client.stop()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,645 +0,0 @@
|
|||
import argparse
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
from pathlib import Path
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
# ============================================================
|
||||
# Ajuste de import local
|
||||
# ============================================================
|
||||
THIS_FILE = Path(__file__).resolve()
|
||||
WORKERS_DIR = THIS_FILE.parents[2]
|
||||
if str(WORKERS_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(WORKERS_DIR))
|
||||
|
||||
from camera_worker.oak_fcc3_core.oak_fcc3_client import OakFcc3Client
|
||||
|
||||
try:
|
||||
from camera_worker.oak_fcc3_core.segformer_service import MultiSpecSegformerService
|
||||
except Exception:
|
||||
MultiSpecSegformerService = None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# FPS / utilidades
|
||||
# ============================================================
|
||||
class FpsMeter:
|
||||
def __init__(self, alpha=0.15):
|
||||
self.alpha = float(alpha)
|
||||
self.last_ts = None
|
||||
self.fps = 0.0
|
||||
|
||||
def tick(self):
|
||||
now = time.perf_counter()
|
||||
if self.last_ts is not None:
|
||||
dt = now - self.last_ts
|
||||
if dt > 1e-9:
|
||||
inst = 1.0 / dt
|
||||
self.fps = inst if self.fps <= 0 else (1.0 - self.alpha) * self.fps + self.alpha * inst
|
||||
self.last_ts = now
|
||||
return self.fps
|
||||
|
||||
|
||||
def load_json_if_exists(path):
|
||||
if not path:
|
||||
return None
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def init_model_service(args):
|
||||
"""
|
||||
Mesmo contrato do benchmark científico:
|
||||
--run_model exige --model_config_json
|
||||
MultiSpecSegformerService(model_config=cfg).infer_tensor_fast(tensor, keep_probs=False)
|
||||
"""
|
||||
if not args.run_model:
|
||||
return None
|
||||
|
||||
if MultiSpecSegformerService is None:
|
||||
raise RuntimeError("MultiSpecSegformerService não pôde ser importado.")
|
||||
|
||||
model_cfg = load_json_if_exists(args.model_config_json)
|
||||
if not isinstance(model_cfg, dict):
|
||||
raise RuntimeError("--run_model requer --model_config_json válido.")
|
||||
|
||||
svc = MultiSpecSegformerService(
|
||||
model_config=model_cfg,
|
||||
mostrar_log=print,
|
||||
)
|
||||
|
||||
dummy = np.zeros((5, int(args.height), int(args.width)), dtype=np.float32)
|
||||
for _ in range(max(0, int(args.warmup_model))):
|
||||
svc.infer_tensor_fast(dummy, keep_probs=False)
|
||||
|
||||
print(f"[MODEL] Warmup concluído: {args.warmup_model}x")
|
||||
return svc
|
||||
|
||||
|
||||
def to_u8_01(arr, auto_level=False):
|
||||
arr = np.asarray(arr, dtype=np.float32)
|
||||
arr = np.nan_to_num(arr, nan=0.0, posinf=1.0, neginf=0.0)
|
||||
|
||||
if auto_level:
|
||||
p1 = float(np.percentile(arr, 1))
|
||||
p99 = float(np.percentile(arr, 99))
|
||||
den = max(p99 - p1, 1e-6)
|
||||
arr = (arr - p1) / den
|
||||
|
||||
arr = np.clip(arr, 0.0, 1.0)
|
||||
return (arr * 255.0).astype(np.uint8)
|
||||
|
||||
|
||||
def ensure_bgr(img, auto_level=False):
|
||||
img = np.asarray(img)
|
||||
|
||||
if img.ndim == 2:
|
||||
g = to_u8_01(img, auto_level=auto_level)
|
||||
return cv2.cvtColor(g, cv2.COLOR_GRAY2BGR)
|
||||
|
||||
if img.ndim == 3 and img.shape[2] == 3:
|
||||
u8 = to_u8_01(img, auto_level=auto_level)
|
||||
# decoded/tensor RGB vem em RGB; OpenCV mostra BGR
|
||||
return cv2.cvtColor(u8, cv2.COLOR_RGB2BGR)
|
||||
|
||||
raise RuntimeError(f"Imagem inválida para visualização: shape={img.shape}")
|
||||
|
||||
|
||||
def tensor_rgb_to_bgr(tensor, auto_level=False):
|
||||
rgb = np.stack([tensor[0], tensor[1], tensor[2]], axis=2)
|
||||
return ensure_bgr(rgb, auto_level=auto_level)
|
||||
|
||||
|
||||
def tensor_channel_to_bgr(tensor, idx, auto_level=False):
|
||||
return ensure_bgr(tensor[idx], auto_level=auto_level)
|
||||
|
||||
|
||||
def add_title(img, title, color=(255, 255, 255)):
|
||||
out = img.copy()
|
||||
h, w = out.shape[:2]
|
||||
bar_h = 34
|
||||
bar = np.zeros((bar_h, w, 3), dtype=np.uint8)
|
||||
cv2.putText(bar, str(title), (10, 23), cv2.FONT_HERSHEY_SIMPLEX, 0.62, color, 2, cv2.LINE_AA)
|
||||
return np.vstack([bar, out])
|
||||
|
||||
|
||||
def add_hud(panel, lines):
|
||||
out = panel.copy()
|
||||
x, y = 12, 45
|
||||
for line in lines:
|
||||
cv2.putText(out, line, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.62, (0, 255, 255), 2, cv2.LINE_AA)
|
||||
y += 24
|
||||
return out
|
||||
|
||||
|
||||
def resize_tile(img, tile_w, tile_h):
|
||||
return cv2.resize(img, (int(tile_w), int(tile_h)), interpolation=cv2.INTER_AREA)
|
||||
|
||||
|
||||
def get_cam_by_role(decoded, role):
|
||||
role = str(role).lower()
|
||||
for cam_id, item in decoded.items():
|
||||
r = str(item.get("role") or item.get("meta", {}).get("role") or "").lower()
|
||||
if r == role:
|
||||
return cam_id
|
||||
return None
|
||||
|
||||
|
||||
def decoded_raw_tiles(decoded, tile_w, tile_h, auto_level=False):
|
||||
"""
|
||||
Retorna tiles RAW/decoded para RGB, RE, NIR antes da fusão final.
|
||||
Aqui 'RAW_BRUTO' significa o conteúdo decodificado vindo das câmeras, ainda no espaço nativo.
|
||||
"""
|
||||
tiles = {}
|
||||
|
||||
rgb_id = get_cam_by_role(decoded, "rgb")
|
||||
re_id = get_cam_by_role(decoded, "re")
|
||||
nir_id = get_cam_by_role(decoded, "nir")
|
||||
|
||||
if rgb_id is not None:
|
||||
img = decoded[rgb_id]["image"]
|
||||
tiles["rgb"] = resize_tile(ensure_bgr(img, auto_level=auto_level), tile_w, tile_h)
|
||||
else:
|
||||
tiles["rgb"] = np.zeros((tile_h, tile_w, 3), dtype=np.uint8)
|
||||
|
||||
if re_id is not None:
|
||||
img = decoded[re_id]["image"]
|
||||
tiles["re"] = resize_tile(ensure_bgr(img, auto_level=auto_level), tile_w, tile_h)
|
||||
else:
|
||||
tiles["re"] = np.zeros((tile_h, tile_w, 3), dtype=np.uint8)
|
||||
|
||||
if nir_id is not None:
|
||||
img = decoded[nir_id]["image"]
|
||||
tiles["nir"] = resize_tile(ensure_bgr(img, auto_level=auto_level), tile_w, tile_h)
|
||||
else:
|
||||
tiles["nir"] = np.zeros((tile_h, tile_w, 3), dtype=np.uint8)
|
||||
|
||||
return tiles
|
||||
|
||||
|
||||
def tensor_tiles(tensor, tile_w, tile_h, auto_level=False):
|
||||
return {
|
||||
"rgb": resize_tile(tensor_rgb_to_bgr(tensor, auto_level=auto_level), tile_w, tile_h),
|
||||
"re": resize_tile(tensor_channel_to_bgr(tensor, 3, auto_level=auto_level), tile_w, tile_h),
|
||||
"nir": resize_tile(tensor_channel_to_bgr(tensor, 4, auto_level=auto_level), tile_w, tile_h),
|
||||
}
|
||||
|
||||
|
||||
def colorize_label_map(label_map, num_classes=None):
|
||||
label = np.asarray(label_map)
|
||||
if label.ndim == 3:
|
||||
label = np.argmax(label, axis=0)
|
||||
label = label.astype(np.int32)
|
||||
|
||||
if num_classes is None:
|
||||
num_classes = int(max(1, label.max() + 1))
|
||||
|
||||
# Paleta simples e estável. BGR.
|
||||
palette = np.array([
|
||||
[40, 40, 40],
|
||||
[60, 180, 60],
|
||||
[60, 60, 220],
|
||||
[220, 180, 60],
|
||||
[180, 60, 180],
|
||||
[180, 180, 60],
|
||||
[60, 180, 180],
|
||||
[220, 220, 220],
|
||||
], dtype=np.uint8)
|
||||
|
||||
out = palette[label % len(palette)]
|
||||
return out
|
||||
|
||||
|
||||
def try_extract_prediction_tiles(pred, target_w, target_h):
|
||||
"""
|
||||
Tentativa genérica. Adapte aqui se o benchmark tiver nomes específicos das cabeças.
|
||||
Retorna até 3 tiles BGR: semântica/head0/head1.
|
||||
"""
|
||||
if pred is None:
|
||||
blank = np.zeros((target_h, target_w, 3), dtype=np.uint8)
|
||||
return [blank, blank.copy(), blank.copy()], ["Pred vazio", "Head 1", "Head 2"]
|
||||
|
||||
candidates = []
|
||||
names = []
|
||||
|
||||
if isinstance(pred, dict):
|
||||
# nomes comuns
|
||||
for key in ("mask", "pred_mask", "class_map", "semantic", "semantic_mask", "segmentation"):
|
||||
if key in pred:
|
||||
candidates.append(pred[key])
|
||||
names.append(key)
|
||||
|
||||
heads = pred.get("heads") or pred.get("head_outputs") or pred.get("predictions")
|
||||
if isinstance(heads, dict):
|
||||
for k, v in heads.items():
|
||||
candidates.append(v)
|
||||
names.append(str(k))
|
||||
elif isinstance(heads, (list, tuple)):
|
||||
for i, v in enumerate(heads):
|
||||
candidates.append(v)
|
||||
names.append(f"head_{i}")
|
||||
else:
|
||||
candidates.append(pred)
|
||||
names.append("prediction")
|
||||
|
||||
tiles = []
|
||||
out_names = []
|
||||
|
||||
for name, arr in zip(names, candidates):
|
||||
arr = np.asarray(arr)
|
||||
|
||||
# remove batch se existir
|
||||
if arr.ndim == 4 and arr.shape[0] == 1:
|
||||
arr = arr[0]
|
||||
|
||||
if arr.ndim == 3:
|
||||
# CHW logits/probs ou HWC RGB/probs
|
||||
if arr.shape[0] <= 32:
|
||||
vis = colorize_label_map(np.argmax(arr, axis=0), num_classes=arr.shape[0])
|
||||
elif arr.shape[2] in (1, 3):
|
||||
vis = ensure_bgr(arr[:, :, 0] if arr.shape[2] == 1 else arr, auto_level=True)
|
||||
else:
|
||||
vis = ensure_bgr(np.max(arr, axis=2), auto_level=True)
|
||||
elif arr.ndim == 2:
|
||||
# se parecer label map, colore; se parecer float, cinza auto-level
|
||||
if np.issubdtype(arr.dtype, np.integer) and int(np.max(arr)) <= 64:
|
||||
vis = colorize_label_map(arr)
|
||||
else:
|
||||
vis = ensure_bgr(arr, auto_level=True)
|
||||
elif arr.ndim == 1:
|
||||
# vetor de classe/score: desenha texto
|
||||
vis = np.zeros((target_h, target_w, 3), dtype=np.uint8)
|
||||
txt = np.array2string(arr[:8], precision=2, separator=", ")
|
||||
cv2.putText(vis, txt[:80], (10, target_h // 2), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)
|
||||
else:
|
||||
continue
|
||||
|
||||
vis = resize_tile(vis, target_w, target_h)
|
||||
tiles.append(vis)
|
||||
out_names.append(name)
|
||||
|
||||
if len(tiles) >= 3:
|
||||
break
|
||||
|
||||
while len(tiles) < 3:
|
||||
tiles.append(np.zeros((target_h, target_w, 3), dtype=np.uint8))
|
||||
out_names.append(f"pred_{len(tiles)}")
|
||||
|
||||
return tiles[:3], out_names[:3]
|
||||
|
||||
|
||||
def try_run_model(model_svc, tensor):
|
||||
"""
|
||||
Inferência real, igual ao benchmark científico.
|
||||
Mantém esta função isolada para adaptar fácil caso o retorno do modelo mude.
|
||||
"""
|
||||
if model_svc is None:
|
||||
return None, "model_svc_none"
|
||||
|
||||
if hasattr(model_svc, "infer_tensor_fast"):
|
||||
return model_svc.infer_tensor_fast(tensor, keep_probs=False), None
|
||||
|
||||
if hasattr(model_svc, "infer"):
|
||||
return model_svc.infer(tensor), None
|
||||
|
||||
return None, "model_svc_sem_infer"
|
||||
|
||||
|
||||
def build_grid(raw_tiles, final_tiles, pred_tiles=None, pred_names=None, tile_w=420, tile_h=260):
|
||||
rows = []
|
||||
row_defs = [
|
||||
("RGB", "rgb"),
|
||||
("RE", "re"),
|
||||
("NIR", "nir"),
|
||||
]
|
||||
|
||||
for i, (label, key) in enumerate(row_defs):
|
||||
left = add_title(raw_tiles[key], f"RAW_BRUTO decoded {label}")
|
||||
mid = add_title(final_tiles[key], f"Tensor final {label}")
|
||||
|
||||
cells = [left, mid]
|
||||
|
||||
if pred_tiles is not None:
|
||||
name = pred_names[i] if pred_names and i < len(pred_names) else f"Pred {i}"
|
||||
cells.append(add_title(pred_tiles[i], name))
|
||||
|
||||
# iguala altura após título
|
||||
h_min = min(c.shape[0] for c in cells)
|
||||
norm = [cv2.resize(c, (tile_w, h_min), interpolation=cv2.INTER_AREA) if c.shape[1] != tile_w or c.shape[0] != h_min else c for c in cells]
|
||||
rows.append(np.hstack(norm))
|
||||
|
||||
return np.vstack(rows)
|
||||
|
||||
|
||||
def get_core_perf(client):
|
||||
for attr in ("raw_processor", "processor", "core", "raw_processor_core"):
|
||||
obj = getattr(client, attr, None)
|
||||
if obj is not None and getattr(obj, "last_fusion_result", None) is not None:
|
||||
return obj.last_fusion_result.get("perf", {}) or {}
|
||||
return {}
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Estado compartilhado / workers assíncronos
|
||||
# ============================================================
|
||||
class SharedState:
|
||||
def __init__(self):
|
||||
self.lock = threading.Lock()
|
||||
self.running = True
|
||||
self.latest_decoded = None
|
||||
self.latest_meta = None
|
||||
self.latest_tensor = None
|
||||
self.latest_perf = {}
|
||||
self.latest_pred = None
|
||||
self.latest_model_warn = None
|
||||
self.latest_model_ms = 0.0
|
||||
self.latest_error = None
|
||||
self.tensor_fps = FpsMeter()
|
||||
self.model_fps = FpsMeter()
|
||||
self.preview_fps = FpsMeter()
|
||||
self.tensor_seq = 0
|
||||
self.model_seq = 0
|
||||
|
||||
def stop(self):
|
||||
with self.lock:
|
||||
self.running = False
|
||||
|
||||
def is_running(self):
|
||||
with self.lock:
|
||||
return bool(self.running)
|
||||
|
||||
|
||||
def tensor_worker(client, state, args):
|
||||
"""
|
||||
Roda no talo: captura RAW_BRUTO, monta tensor final e atualiza cache.
|
||||
Não depende do FPS da janela.
|
||||
"""
|
||||
while state.is_running():
|
||||
try:
|
||||
frame, meta, decoded = client.get_next_decoded(timeout=args.timeout)
|
||||
if not isinstance(frame, dict):
|
||||
raise RuntimeError(f"RAW_BRUTO esperado como dict. Veio {type(frame)}")
|
||||
|
||||
tensor = client.build_infer_tensor_from_decoded(
|
||||
decoded=decoded,
|
||||
meta=meta,
|
||||
channels_expected=5,
|
||||
target_size=(args.width, args.height),
|
||||
)
|
||||
tensor = np.ascontiguousarray(tensor.astype(np.float32, copy=False))
|
||||
perf = get_core_perf(client)
|
||||
fps = state.tensor_fps.tick()
|
||||
|
||||
with state.lock:
|
||||
state.latest_decoded = decoded
|
||||
state.latest_meta = meta
|
||||
state.latest_tensor = tensor
|
||||
state.latest_perf = dict(perf or {})
|
||||
state.tensor_seq += 1
|
||||
state.latest_error = None
|
||||
|
||||
except Exception as e:
|
||||
with state.lock:
|
||||
state.latest_error = f"tensor_worker: {type(e).__name__}: {e}"
|
||||
time.sleep(0.02)
|
||||
|
||||
|
||||
def model_worker(model_svc, state, args):
|
||||
"""
|
||||
Opcional: roda inferência no último tensor disponível.
|
||||
Não bloqueia o worker de tensor nem a janela.
|
||||
"""
|
||||
last_seq = -1
|
||||
|
||||
while state.is_running():
|
||||
with state.lock:
|
||||
tensor = None if state.latest_tensor is None else state.latest_tensor.copy()
|
||||
seq = state.tensor_seq
|
||||
|
||||
if tensor is None or seq == last_seq:
|
||||
time.sleep(0.005)
|
||||
continue
|
||||
|
||||
last_seq = seq
|
||||
|
||||
try:
|
||||
t0_model = time.perf_counter()
|
||||
pred, warn = try_run_model(model_svc, tensor)
|
||||
model_ms = (time.perf_counter() - t0_model) * 1000.0
|
||||
if warn is None:
|
||||
state.model_fps.tick()
|
||||
|
||||
with state.lock:
|
||||
state.latest_pred = pred
|
||||
state.latest_model_warn = warn
|
||||
state.latest_model_ms = float(model_ms)
|
||||
state.model_seq += 1
|
||||
|
||||
except Exception as e:
|
||||
with state.lock:
|
||||
state.latest_model_warn = f"model_worker: {type(e).__name__}: {e}"
|
||||
time.sleep(0.02)
|
||||
|
||||
|
||||
def snapshot_state(state):
|
||||
"""
|
||||
Copia referências do cache para desenhar. A janela só roda na cadência do preview.
|
||||
"""
|
||||
with state.lock:
|
||||
return {
|
||||
"decoded": state.latest_decoded,
|
||||
"meta": state.latest_meta,
|
||||
"tensor": state.latest_tensor,
|
||||
"perf": dict(state.latest_perf or {}),
|
||||
"pred": state.latest_pred,
|
||||
"model_warn": state.latest_model_warn,
|
||||
"model_ms": state.latest_model_ms,
|
||||
"error": state.latest_error,
|
||||
"tensor_fps": state.tensor_fps.fps,
|
||||
"model_fps": state.model_fps.fps,
|
||||
"tensor_seq": state.tensor_seq,
|
||||
"model_seq": state.model_seq,
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Main loop assíncrono
|
||||
# ============================================================
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Preview assíncrono RAW_BRUTO decoded vs tensor final multispectral.")
|
||||
ap.add_argument("--module_params", default=r"C:\ZendionInc\agrobot_base\Python\OAK\datasets\oak-fcc-3\calibration\module_params.json")
|
||||
ap.add_argument("--width", type=int, default=1024, help="Largura final do tensor.")
|
||||
ap.add_argument("--height", type=int, default=640, help="Altura final do tensor.")
|
||||
ap.add_argument("--fps", type=float, default=40.0, help="FPS alvo da câmera.")
|
||||
ap.add_argument("--preview_fps", type=float, default=5.0, help="FPS da janela OpenCV apenas.")
|
||||
ap.add_argument("--timeout", type=float, default=2.0)
|
||||
ap.add_argument("--warmup", type=int, default=5)
|
||||
ap.add_argument("--mx_id", default=None)
|
||||
ap.add_argument("--display_scale", type=float, default=0.75)
|
||||
ap.add_argument("--tile_w", type=int, default=420)
|
||||
ap.add_argument("--tile_h", type=int, default=260)
|
||||
ap.add_argument("--auto_level_raw", action="store_true")
|
||||
ap.add_argument("--auto_level_tensor", action="store_true")
|
||||
ap.add_argument("--run_model", action="store_true", help="Roda inferência em thread separada usando o último tensor cacheado.")
|
||||
ap.add_argument("--model_config_json", default=None, help="JSON de configuração do modelo SegFormer, igual ao benchmark.")
|
||||
ap.add_argument("--warmup_model", type=int, default=3, help="Número de inferências dummy para aquecer o modelo.")
|
||||
ap.add_argument("--save_last", default=None)
|
||||
args = ap.parse_args()
|
||||
|
||||
client = OakFcc3Client(
|
||||
width=args.width,
|
||||
height=args.height,
|
||||
fps=args.fps,
|
||||
frame_type="RAW_BRUTO",
|
||||
capture_mode="TRIPLE",
|
||||
raw_policy="require_triple",
|
||||
module_calibration_json=args.module_params,
|
||||
mx_id=args.mx_id,
|
||||
)
|
||||
|
||||
model_svc = init_model_service(args) if args.run_model else None
|
||||
|
||||
state = SharedState()
|
||||
last_panel = None
|
||||
last_warn_ts = 0.0
|
||||
last_seq_drawn = -1
|
||||
|
||||
try:
|
||||
client.start(print_debug=True)
|
||||
|
||||
for _ in range(max(0, int(args.warmup))):
|
||||
try:
|
||||
client.get_next_decoded(timeout=args.timeout)
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(0.03)
|
||||
|
||||
tw = threading.Thread(target=tensor_worker, args=(client, state, args), daemon=True)
|
||||
tw.start()
|
||||
|
||||
mw = None
|
||||
if args.run_model:
|
||||
mw = threading.Thread(target=model_worker, args=(model_svc, state, args), daemon=True)
|
||||
mw.start()
|
||||
|
||||
min_period = 1.0 / max(float(args.preview_fps), 0.1)
|
||||
next_draw_ts = 0.0
|
||||
|
||||
print("[INFO] Preview assíncrono iniciado. Pressione Q ou ESC para sair.")
|
||||
print("[INFO] Tensor FPS = geração real do tensor. Preview FPS = janela. Model FPS = inferência, se habilitada.")
|
||||
|
||||
while True:
|
||||
now = time.perf_counter()
|
||||
if now < next_draw_ts:
|
||||
time.sleep(min(0.005, next_draw_ts - now))
|
||||
key = cv2.waitKey(1) & 0xFF
|
||||
if key in (27, ord('q'), ord('Q')):
|
||||
break
|
||||
continue
|
||||
|
||||
next_draw_ts = now + min_period
|
||||
snap = snapshot_state(state)
|
||||
|
||||
if snap["tensor"] is None or snap["decoded"] is None:
|
||||
blank = np.zeros((360, 900, 3), dtype=np.uint8)
|
||||
cv2.putText(blank, "Aguardando primeiro tensor...", (30, 180), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (255,255,255), 2, cv2.LINE_AA)
|
||||
cv2.imshow("OAK RAW_BRUTO vs Tensor Final", blank)
|
||||
key = cv2.waitKey(1) & 0xFF
|
||||
if key in (27, ord('q'), ord('Q')):
|
||||
break
|
||||
continue
|
||||
|
||||
# Desenha só usando o cache. Não captura nem monta tensor aqui.
|
||||
t_draw0 = time.perf_counter()
|
||||
raw_tiles = decoded_raw_tiles(
|
||||
snap["decoded"],
|
||||
tile_w=args.tile_w,
|
||||
tile_h=args.tile_h,
|
||||
auto_level=args.auto_level_raw,
|
||||
)
|
||||
final_tiles = tensor_tiles(
|
||||
snap["tensor"],
|
||||
tile_w=args.tile_w,
|
||||
tile_h=args.tile_h,
|
||||
auto_level=args.auto_level_tensor,
|
||||
)
|
||||
|
||||
pred_tiles = None
|
||||
pred_names = None
|
||||
if args.run_model:
|
||||
pred_tiles, pred_names = try_extract_prediction_tiles(
|
||||
snap["pred"],
|
||||
target_w=args.tile_w,
|
||||
target_h=args.tile_h,
|
||||
)
|
||||
if snap["model_warn"]:
|
||||
tnow = time.time()
|
||||
if tnow - last_warn_ts > 2.0:
|
||||
print(f"[WARN][MODEL] {snap['model_warn']}")
|
||||
last_warn_ts = tnow
|
||||
|
||||
panel = build_grid(
|
||||
raw_tiles=raw_tiles,
|
||||
final_tiles=final_tiles,
|
||||
pred_tiles=pred_tiles,
|
||||
pred_names=pred_names,
|
||||
tile_w=args.tile_w,
|
||||
tile_h=args.tile_h,
|
||||
)
|
||||
|
||||
preview_fps = state.preview_fps.tick()
|
||||
draw_ms = (time.perf_counter() - t_draw0) * 1000.0
|
||||
perf = snap["perf"]
|
||||
meta = snap["meta"] or {}
|
||||
tensor_seq = int(snap["tensor_seq"])
|
||||
dropped_for_preview = max(0, tensor_seq - last_seq_drawn - 1) if last_seq_drawn >= 0 else 0
|
||||
last_seq_drawn = tensor_seq
|
||||
|
||||
hud = [
|
||||
f"Preview FPS: {preview_fps:.1f} | Tensor FPS: {snap['tensor_fps']:.1f} | Model FPS: {snap['model_fps']:.1f} | infer={snap.get('model_ms', 0.0):.1f}ms",
|
||||
f"draw={draw_ms:.1f}ms flat={perf.get('flat_ms', 0):.1f} warp={perf.get('warp_total_ms', 0):.1f} crop={perf.get('crop_resize_ms', 0):.1f} fuse={perf.get('total_ms', 0):.1f}",
|
||||
f"seq={tensor_seq} skipped_preview={dropped_for_preview} frame_type={meta.get('frame_type')} run_model={args.run_model}",
|
||||
]
|
||||
if snap["error"]:
|
||||
hud.append(str(snap["error"])[:120])
|
||||
|
||||
panel = add_hud(panel, hud)
|
||||
last_panel = panel
|
||||
|
||||
disp = panel
|
||||
if args.display_scale and abs(args.display_scale - 1.0) > 1e-6:
|
||||
disp = cv2.resize(
|
||||
disp,
|
||||
(max(1, int(disp.shape[1] * args.display_scale)), max(1, int(disp.shape[0] * args.display_scale))),
|
||||
interpolation=cv2.INTER_AREA,
|
||||
)
|
||||
|
||||
cv2.imshow("OAK RAW_BRUTO vs Tensor Final", disp)
|
||||
key = cv2.waitKey(1) & 0xFF
|
||||
if key in (27, ord('q'), ord('Q')):
|
||||
break
|
||||
|
||||
finally:
|
||||
state.stop()
|
||||
time.sleep(0.05)
|
||||
|
||||
if args.save_last and last_panel is not None:
|
||||
out_path = Path(args.save_last)
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
cv2.imwrite(str(out_path), last_panel)
|
||||
print(f"[SAVE] {out_path}")
|
||||
|
||||
try:
|
||||
client.stop()
|
||||
except Exception:
|
||||
pass
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -46,6 +46,7 @@ class OakFcc3Client:
|
|||
mx_id=None,
|
||||
imu_modo="rotation_vector",
|
||||
imu_freq_hz=200,
|
||||
evaluate_quality=True,
|
||||
**kwargs,
|
||||
):
|
||||
self.width = width
|
||||
|
|
@ -63,6 +64,16 @@ class OakFcc3Client:
|
|||
self.imu_modo = str(imu_modo).strip().lower()
|
||||
self.imu_freq_hz = int(imu_freq_hz)
|
||||
|
||||
# Auditoria radiométrica completa do Raw5.
|
||||
#
|
||||
# True mantém o comportamento histórico e é útil para captura científica,
|
||||
# normalize/auditoria e ferramentas offline.
|
||||
#
|
||||
# No runtime em tempo real deve ficar False: evaluate_frame_quality()
|
||||
# calcula estatísticas/percentis pesados e não faz parte da montagem
|
||||
# necessária para a inferência.
|
||||
self.evaluate_quality = bool(evaluate_quality)
|
||||
|
||||
self.mx_id = str(mx_id) if mx_id else None
|
||||
|
||||
self.svc = OakFcc3Service(
|
||||
|
|
@ -327,8 +338,33 @@ class OakFcc3Client:
|
|||
target_size=target_size,
|
||||
)
|
||||
|
||||
def build_infer_tensor_from_decoded(self, decoded, meta, channels_expected, target_size=None):
|
||||
def build_infer_tensor_from_decoded(
|
||||
self,
|
||||
decoded,
|
||||
meta,
|
||||
channels_expected,
|
||||
target_size=None,
|
||||
evaluate_quality=None,
|
||||
):
|
||||
"""
|
||||
Monta o Raw5 físico a partir das câmeras já decodificadas.
|
||||
|
||||
evaluate_quality:
|
||||
- None -> usa self.evaluate_quality
|
||||
- True -> executa evaluate_frame_quality() e atualiza
|
||||
core.last_frame_quality_result
|
||||
- False -> não executa a auditoria pesada e limpa
|
||||
core.last_frame_quality_result
|
||||
|
||||
A flag altera somente a auditoria de qualidade. Não altera decode,
|
||||
radiometria, flat-field, homografia, crop/resize ou patch normalization.
|
||||
"""
|
||||
channels_expected = self._validate_physical_channel_count(channels_expected)
|
||||
|
||||
if evaluate_quality is None:
|
||||
evaluate_quality = self.evaluate_quality
|
||||
evaluate_quality = bool(evaluate_quality)
|
||||
|
||||
tensor = self.core.fuse_multispec_cameras(decoded, meta, channels_expected)
|
||||
tensor = self.core.resize_tensor_chw(tensor, target_size=target_size)
|
||||
|
||||
|
|
@ -338,7 +374,12 @@ class OakFcc3Client:
|
|||
if bool(patch_cfg.get("enabled", False)):
|
||||
tensor = self.core.apply_patch_normalization_to_tensor(tensor)
|
||||
|
||||
self.core.last_frame_quality_result = self.core.evaluate_frame_quality(tensor)
|
||||
if evaluate_quality:
|
||||
self.core.last_frame_quality_result = self.core.evaluate_frame_quality(tensor)
|
||||
else:
|
||||
# Evita deixar um resultado antigo parecer referente ao frame atual.
|
||||
self.core.last_frame_quality_result = None
|
||||
|
||||
return tensor
|
||||
|
||||
def decode_stream_cameras(self, frame, meta):
|
||||
|
|
@ -382,12 +423,19 @@ class OakFcc3Client:
|
|||
tensor = np.transpose(rgb01.astype(np.float32), (2, 0, 1))
|
||||
return np.ascontiguousarray(tensor.astype(np.float32, copy=False))
|
||||
|
||||
def build_multispec_tensor(self, decoded, meta=None, target_size=None):
|
||||
def build_multispec_tensor(
|
||||
self,
|
||||
decoded,
|
||||
meta=None,
|
||||
target_size=None,
|
||||
evaluate_quality=None,
|
||||
):
|
||||
tensor = self.build_infer_tensor_from_decoded(
|
||||
decoded=decoded,
|
||||
meta=meta,
|
||||
channels_expected=5,
|
||||
target_size=target_size,
|
||||
evaluate_quality=evaluate_quality,
|
||||
)
|
||||
return np.ascontiguousarray(tensor.astype(np.float32, copy=False))
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import cv2
|
|||
import depthai as dai
|
||||
import numpy as np
|
||||
|
||||
from itertools import product
|
||||
|
||||
|
||||
class OakFcc3Manager:
|
||||
"""
|
||||
|
|
@ -43,6 +45,8 @@ class OakFcc3Manager:
|
|||
raw_policy="allow_single",
|
||||
roles=None,
|
||||
sync_mode="best",
|
||||
hardware_sync_enabled=True,
|
||||
frame_sync_master="CAM_A",
|
||||
sync_tolerance_ms=12.0,
|
||||
buffer_size=8,
|
||||
only_camera=None,
|
||||
|
|
@ -52,6 +56,9 @@ class OakFcc3Manager:
|
|||
imu_modo="rotation_vector",
|
||||
imu_freq_hz=200,
|
||||
):
|
||||
self.hardware_sync_enabled = hardware_sync_enabled
|
||||
self.frame_sync_master = frame_sync_master
|
||||
|
||||
self.fps = fps
|
||||
|
||||
# Para compatibilidade, mantemos width/height.
|
||||
|
|
@ -432,6 +439,49 @@ class OakFcc3Manager:
|
|||
# Pipeline creation, MULTISPEC aligned on OAK
|
||||
# ============================================================
|
||||
|
||||
def _aplicar_frame_sync(self, cam, cam_id):
|
||||
cam_id_normalizado = str(cam_id).strip().upper()
|
||||
master = str(self.frame_sync_master).strip().upper()
|
||||
|
||||
if not self.hardware_sync_enabled:
|
||||
print(
|
||||
f"[OAK FSYNC] cam={cam_id_normalizado} "
|
||||
f"habilitado=False modo=DISABLED"
|
||||
)
|
||||
return
|
||||
|
||||
cameras_validas = {"CAM_A", "CAM_B", "CAM_C"}
|
||||
|
||||
if master not in cameras_validas:
|
||||
raise ValueError(
|
||||
f"frame_sync_master inválido: {self.frame_sync_master}. "
|
||||
f"Esperado: CAM_A, CAM_B ou CAM_C."
|
||||
)
|
||||
|
||||
if cam_id_normalizado not in cameras_validas:
|
||||
print(
|
||||
f"[OAK FSYNC] Câmera ignorada: "
|
||||
f"cam_id={cam_id_normalizado}"
|
||||
)
|
||||
return
|
||||
|
||||
if cam_id_normalizado == master:
|
||||
modo = dai.CameraControl.FrameSyncMode.OUTPUT
|
||||
nome_modo = "OUTPUT"
|
||||
else:
|
||||
modo = dai.CameraControl.FrameSyncMode.INPUT
|
||||
nome_modo = "INPUT"
|
||||
|
||||
cam.initialControl.setFrameSyncMode(modo)
|
||||
|
||||
print(
|
||||
f"[OAK FSYNC] "
|
||||
f"cam={cam_id_normalizado} "
|
||||
f"master={master} "
|
||||
f"habilitado=True "
|
||||
f"modo={nome_modo}"
|
||||
)
|
||||
|
||||
def _create_color_camera_multispec(self, socket):
|
||||
cam = self.pipeline.create(dai.node.ColorCamera)
|
||||
cam.setBoardSocket(socket)
|
||||
|
|
@ -591,6 +641,7 @@ class OakFcc3Manager:
|
|||
raise RuntimeError(f"Role não suportada no MULTISPEC: cam_id={cam_id}, role={role}")
|
||||
|
||||
self.apply_initial_camera_controls_to_node(cam, cam_id)
|
||||
self._aplicar_frame_sync(cam, cam_id)
|
||||
|
||||
xin_ctrl = self.pipeline.create(dai.node.XLinkIn)
|
||||
xin_ctrl.setStreamName(f"{cam_id}_ctrl")
|
||||
|
|
@ -871,6 +922,7 @@ class OakFcc3Manager:
|
|||
)
|
||||
|
||||
self.apply_initial_camera_controls_to_node(cam, socket_name)
|
||||
self._aplicar_frame_sync(cam, socket_name)
|
||||
|
||||
xin_ctrl = self.pipeline.create(dai.node.XLinkIn)
|
||||
xin_ctrl.setStreamName(f"{socket_name}_ctrl")
|
||||
|
|
@ -1241,6 +1293,41 @@ class OakFcc3Manager:
|
|||
f"Tolerância atual={self.sync_tolerance_ms} ms."
|
||||
)
|
||||
|
||||
def _encontrar_melhor_tripleta(self, required_cam_ids):
|
||||
listas = [
|
||||
list(self.buffers[cam_id])
|
||||
for cam_id in required_cam_ids
|
||||
]
|
||||
|
||||
melhor_selecao = None
|
||||
melhor_score = None
|
||||
|
||||
for combinacao in product(*listas):
|
||||
timestamps = [
|
||||
item["timestamp"]
|
||||
for item in combinacao
|
||||
]
|
||||
|
||||
menor_ts = min(timestamps)
|
||||
maior_ts = max(timestamps)
|
||||
spread_ms = (maior_ts - menor_ts) * 1000.0
|
||||
|
||||
# Primeiro prioriza menor dispersão.
|
||||
# Em empate, prefere o pacote mais recente.
|
||||
score = (
|
||||
spread_ms,
|
||||
-menor_ts,
|
||||
)
|
||||
|
||||
if melhor_score is None or score < melhor_score:
|
||||
melhor_score = score
|
||||
melhor_selecao = {
|
||||
cam_id: item
|
||||
for cam_id, item in zip(required_cam_ids, combinacao)
|
||||
}
|
||||
|
||||
return melhor_selecao
|
||||
|
||||
|
||||
def _extract_frame_controls(self, msg):
|
||||
controls = {
|
||||
|
|
@ -1330,9 +1417,19 @@ class OakFcc3Manager:
|
|||
|
||||
t0_ts = self._cap_now_ms()
|
||||
try:
|
||||
ts = msg.getTimestamp().total_seconds()
|
||||
ts_start = msg.getTimestampDevice(
|
||||
dai.CameraExposureOffset.START
|
||||
).total_seconds()
|
||||
|
||||
ts_end = msg.getTimestampDevice(
|
||||
dai.CameraExposureOffset.END
|
||||
).total_seconds()
|
||||
|
||||
except Exception:
|
||||
ts = time.time()
|
||||
ts_start = msg.getTimestamp().total_seconds()
|
||||
ts_end = ts_start
|
||||
|
||||
ts = ts_start
|
||||
if perf is not None:
|
||||
perf["drain_get_timestamp_ms"] += self._cap_now_ms() - t0_ts
|
||||
|
||||
|
|
@ -1395,7 +1492,9 @@ class OakFcc3Manager:
|
|||
|
||||
self.buffers[cam_id].append({
|
||||
"frame": frame,
|
||||
"timestamp": ts,
|
||||
"timestamp": ts_start,
|
||||
"timestamp_start": ts_start,
|
||||
"timestamp_end": ts_end,
|
||||
"controls": frame_controls,
|
||||
})
|
||||
|
||||
|
|
@ -1420,34 +1519,25 @@ class OakFcc3Manager:
|
|||
def _try_get_synced_packet(self, perf=None):
|
||||
required_cam_ids = self._get_required_cam_ids()
|
||||
|
||||
if not required_cam_ids:
|
||||
if perf is not None:
|
||||
perf["wait_reason"] = "no_required_cameras"
|
||||
return None
|
||||
|
||||
# Todas as câmeras precisam ter pelo menos um frame disponível.
|
||||
for cam_id in required_cam_ids:
|
||||
if cam_id not in self.buffers or len(self.buffers[cam_id]) == 0:
|
||||
if perf is not None:
|
||||
perf["wait_reason"] = f"empty_buffer:{cam_id}"
|
||||
return None
|
||||
|
||||
ref_cam_id = min(required_cam_ids, key=lambda cid: len(self.buffers[cid]))
|
||||
ref_item = self.buffers[ref_cam_id][0]
|
||||
ref_ts = ref_item["timestamp"]
|
||||
# Procura a melhor combinação entre todos os frames disponíveis.
|
||||
selected = self._encontrar_melhor_tripleta(required_cam_ids)
|
||||
|
||||
selected = {}
|
||||
|
||||
for cam_id in required_cam_ids:
|
||||
best_item = None
|
||||
best_dt = None
|
||||
|
||||
for item in self.buffers[cam_id]:
|
||||
dt = abs(item["timestamp"] - ref_ts)
|
||||
if best_dt is None or dt < best_dt:
|
||||
best_dt = dt
|
||||
best_item = item
|
||||
|
||||
if best_item is None:
|
||||
if perf is not None:
|
||||
perf["wait_reason"] = f"no_best_item:{cam_id}"
|
||||
return None
|
||||
|
||||
selected[cam_id] = best_item
|
||||
if not selected or len(selected) != len(required_cam_ids):
|
||||
if perf is not None:
|
||||
perf["wait_reason"] = "no_valid_selection"
|
||||
return None
|
||||
|
||||
timestamps = {
|
||||
cam_id: item["timestamp"]
|
||||
|
|
@ -1459,44 +1549,80 @@ class OakFcc3Manager:
|
|||
for cam_id, item in selected.items()
|
||||
}
|
||||
|
||||
ts_values = list(timestamps.values())
|
||||
|
||||
sync_dt_ms = (
|
||||
(max(ts_values) - min(ts_values)) * 1000.0
|
||||
if len(ts_values) >= 2
|
||||
else 0.0
|
||||
)
|
||||
|
||||
sync_ok = sync_dt_ms <= self.sync_tolerance_ms
|
||||
|
||||
if perf is not None:
|
||||
perf["selected_ts_by_cam"] = {cam_id: float(ts) for cam_id, ts in timestamps.items()}
|
||||
perf["selected_ts_by_cam"] = {
|
||||
cam_id: float(ts)
|
||||
for cam_id, ts in timestamps.items()
|
||||
}
|
||||
|
||||
perf["selected_seq_by_cam"] = {
|
||||
cam_id: item.get("controls", {}).get("sequence_num")
|
||||
for cam_id, item in selected.items()
|
||||
}
|
||||
|
||||
ts_values = list(timestamps.values())
|
||||
sync_dt_ms = (max(ts_values) - min(ts_values)) * 1000.0 if len(ts_values) >= 2 else 0.0
|
||||
sync_ok = sync_dt_ms <= self.sync_tolerance_ms
|
||||
perf["sync_dt_ms"] = float(sync_dt_ms)
|
||||
perf["sync_ok"] = bool(sync_ok)
|
||||
|
||||
modo_sync = str(self.sync_mode).strip().lower()
|
||||
|
||||
# No modo estrito, nunca entrega uma tripleta fora da tolerância.
|
||||
if not sync_ok and modo_sync == "strict":
|
||||
#Remove o frame globalmente mais antigo entre as cabeças
|
||||
#dos buffers. Frames futuros somente estarão mais distantes
|
||||
#desse frame, então ele não conseguirá formar uma combinação
|
||||
#melhor posteriormente.
|
||||
oldest_cam_id = min(
|
||||
required_cam_ids,
|
||||
key=lambda cam_id: self.buffers[cam_id][0]["timestamp"]
|
||||
)
|
||||
|
||||
dropped_item = self.buffers[oldest_cam_id].popleft()
|
||||
|
||||
if not sync_ok and self.sync_mode == "strict":
|
||||
oldest_cam_id = min(timestamps, key=timestamps.get)
|
||||
if len(self.buffers[oldest_cam_id]) > 0:
|
||||
self.buffers[oldest_cam_id].popleft()
|
||||
if perf is not None:
|
||||
perf["wait_reason"] = f"strict_drop_oldest:{oldest_cam_id}"
|
||||
perf["sync_dt_ms"] = float(sync_dt_ms)
|
||||
perf["sync_ok"] = False
|
||||
perf["dropped_timestamp"] = float(dropped_item["timestamp"])
|
||||
|
||||
return None
|
||||
|
||||
# Em best/best_effort, entrega a melhor combinação disponível,
|
||||
# mesmo quando estiver fora da tolerância.
|
||||
frames = {
|
||||
cam_id: item["frame"]
|
||||
for cam_id, item in selected.items()
|
||||
}
|
||||
|
||||
# Consome todos os frames anteriores e o próprio frame selecionado.
|
||||
for cam_id, used_item in selected.items():
|
||||
while len(self.buffers[cam_id]) > 0:
|
||||
while self.buffers[cam_id]:
|
||||
item = self.buffers[cam_id].popleft()
|
||||
|
||||
if item is used_item:
|
||||
break
|
||||
|
||||
if perf is not None:
|
||||
perf["wait_reason"] = "synced_selected"
|
||||
perf["sync_dt_ms"] = float(sync_dt_ms)
|
||||
perf["sync_ok"] = bool(sync_ok)
|
||||
perf["wait_reason"] = (
|
||||
"synced_selected"
|
||||
if sync_ok
|
||||
else "best_effort_selected_outside_tolerance"
|
||||
)
|
||||
|
||||
return frames, timestamps, sync_dt_ms, sync_ok, frame_controls
|
||||
return (
|
||||
frames,
|
||||
timestamps,
|
||||
sync_dt_ms,
|
||||
sync_ok,
|
||||
frame_controls,
|
||||
)
|
||||
|
||||
def _get_available_cam_ids_ordered(self):
|
||||
role_order = ["rgb", "re", "nir"]
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,761 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
camera_startup_profile_production.py
|
||||
====================================
|
||||
|
||||
Gerador/auditor FINAL de produção para o bloco `camera_settings`
|
||||
do módulo multiespectral.
|
||||
|
||||
IMPORTANTE
|
||||
----------
|
||||
Isto NÃO é uma calibração óptica/radiométrica nova.
|
||||
|
||||
O script antigo "Sensor Calibration Tool" misturava:
|
||||
- camera_settings;
|
||||
- ajustes manuais AE/AWB/exposure/gain;
|
||||
- ROIs de cana/erva/solo;
|
||||
- guidance heurístico;
|
||||
- rgb_calibration manual;
|
||||
- snapshots/offline samples.
|
||||
|
||||
Na arquitetura final de produto essas responsabilidades já foram separadas.
|
||||
|
||||
Esta ferramenta preserva SOMENTE o que ainda é necessário ao runtime:
|
||||
camera_settings
|
||||
|
||||
e força explicitamente:
|
||||
rgb_calibration.enabled = false
|
||||
gains = 1,1,1
|
||||
|
||||
para impedir que ganhos RGB históricos/experimentais vazem para o tensor.
|
||||
|
||||
Dependência
|
||||
-----------
|
||||
A ferramenta lê o artefato homologado da etapa radiométrica:
|
||||
|
||||
calibration/radiometry_calibration_v5.json
|
||||
|
||||
e reaproveita:
|
||||
radiometric_normalization.reference_controls
|
||||
|
||||
como valores de fallback do startup.
|
||||
|
||||
Política normal de produto
|
||||
--------------------------
|
||||
RGB:
|
||||
AE = ON
|
||||
AWB = ON
|
||||
exposure_time_us = referência radiométrica (fallback)
|
||||
analogue_gain = ISO_ref / 100
|
||||
colour_gains = [1.0, 1.0]
|
||||
|
||||
RE:
|
||||
AE = ON
|
||||
AWB = OFF
|
||||
exposure_time_us = referência radiométrica (fallback)
|
||||
analogue_gain = ISO_ref / 100
|
||||
|
||||
NIR:
|
||||
AE = ON
|
||||
AWB = OFF
|
||||
exposure_time_us = referência radiométrica (fallback)
|
||||
analogue_gain = ISO_ref / 100
|
||||
|
||||
Por que manter os valores manuais se AE está ON?
|
||||
-------------------------------------------------
|
||||
No manager atual, com AE ligado, exposure/gain do JSON não são forçados
|
||||
fisicamente. Eles ficam armazenados como estado/fallback para uma eventual
|
||||
transição futura para manual.
|
||||
|
||||
Assim:
|
||||
- o campo continua adaptando exposição automaticamente;
|
||||
- a normalização radiométrica usa os controles reais de cada frame;
|
||||
- se AE for desabilitado em algum fluxo futuro, o fallback já é coerente
|
||||
com a calibração radiométrica do módulo.
|
||||
|
||||
Saída
|
||||
-----
|
||||
calibration/camera_startup_profile_v3.json
|
||||
|
||||
Contém:
|
||||
module_params_fragment.camera_settings
|
||||
module_params_fragment.rgb_calibration
|
||||
|
||||
O assembler final do module_params continua sendo a autoridade de merge.
|
||||
|
||||
Fail-closed
|
||||
-----------
|
||||
- exige CAM_A = OV9782 ou AR0234;
|
||||
- exige CAM_B/C = OV9282;
|
||||
- exige artefato radiométrico promovido;
|
||||
- exige hardware_signature compatível;
|
||||
- exige reference_controls válidos para rgb/re/nir;
|
||||
- não aceita ISO inválido;
|
||||
- não ativa rgb_calibration;
|
||||
- preserva backup do ativo anterior.
|
||||
|
||||
Uso
|
||||
---
|
||||
python camera_startup_profile_production.py
|
||||
|
||||
Com rastreabilidade:
|
||||
python camera_startup_profile_production.py ^
|
||||
--module-id MOD_MS_001 ^
|
||||
--operator Diego
|
||||
|
||||
Somente auditoria, sem salvar:
|
||||
python camera_startup_profile_production.py --check-only
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
from dataclasses import dataclass, asdict
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, List
|
||||
|
||||
import depthai as dai
|
||||
|
||||
|
||||
SCHEMA = "multispec_camera_startup_profile_v3"
|
||||
ISO_BASE = 100.0
|
||||
|
||||
ROLES = ("rgb", "re", "nir")
|
||||
|
||||
PRODUCT_TOPOLOGY = {
|
||||
"rgb": {
|
||||
"socket": "CAM_A",
|
||||
"allowed_sensors": ("OV9782", "AR0234"),
|
||||
},
|
||||
"re": {
|
||||
"socket": "CAM_B",
|
||||
"allowed_sensors": ("OV9282",),
|
||||
},
|
||||
"nir": {
|
||||
"socket": "CAM_C",
|
||||
"allowed_sensors": ("OV9282",),
|
||||
},
|
||||
}
|
||||
|
||||
SENSOR_NATIVE_SIZE = {
|
||||
"OV9782": (1280, 800),
|
||||
"AR0234": (1920, 1200),
|
||||
"OV9282": (1280, 800),
|
||||
}
|
||||
|
||||
|
||||
def now_str() -> str:
|
||||
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def stamp() -> str:
|
||||
return datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
||||
|
||||
|
||||
def ensure_dir(path: str | Path):
|
||||
Path(path).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def load_json(path: str | Path) -> dict:
|
||||
p = Path(path)
|
||||
if not p.is_file():
|
||||
raise FileNotFoundError(f"Arquivo não encontrado: {p}")
|
||||
|
||||
with p.open("r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def save_json_atomic(path: str | Path, data: dict):
|
||||
p = Path(path)
|
||||
ensure_dir(p.parent)
|
||||
|
||||
tmp = p.with_suffix(p.suffix + ".tmp")
|
||||
|
||||
with tmp.open("w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
|
||||
os.replace(tmp, p)
|
||||
|
||||
|
||||
def socket_name(socket) -> str:
|
||||
name = getattr(socket, "name", None)
|
||||
if name:
|
||||
return str(name)
|
||||
|
||||
text = str(socket)
|
||||
for candidate in ("CAM_A", "CAM_B", "CAM_C", "CAM_D"):
|
||||
if candidate in text:
|
||||
return candidate
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def supported_types(feature) -> List[str]:
|
||||
return [
|
||||
str(v).upper()
|
||||
for v in (getattr(feature, "supportedTypes", []) or [])
|
||||
]
|
||||
|
||||
|
||||
def feature_is_color(feature) -> bool:
|
||||
types = supported_types(feature)
|
||||
sensor = str(getattr(feature, "sensorName", "") or "").upper()
|
||||
|
||||
if any("COLOR" in x for x in types):
|
||||
return True
|
||||
if any("MONO" in x for x in types):
|
||||
return False
|
||||
|
||||
return sensor in {"OV9782", "AR0234"}
|
||||
|
||||
|
||||
def feature_is_mono(feature) -> bool:
|
||||
types = supported_types(feature)
|
||||
|
||||
if any("MONO" in x for x in types):
|
||||
return True
|
||||
if any("COLOR" in x for x in types):
|
||||
return False
|
||||
|
||||
return not feature_is_color(feature)
|
||||
|
||||
|
||||
@dataclass
|
||||
class CameraInfo:
|
||||
role: str
|
||||
socket: str
|
||||
sensor: str
|
||||
width: int
|
||||
height: int
|
||||
is_color: bool
|
||||
is_mono: bool
|
||||
|
||||
|
||||
def discover_hardware(mx_id: Optional[str]):
|
||||
info = dai.DeviceInfo(mx_id) if mx_id else None
|
||||
ctx = dai.Device(info) if info is not None else dai.Device()
|
||||
|
||||
with ctx as device:
|
||||
actual_mx = None
|
||||
|
||||
for method_name in ("getMxId", "getDeviceId"):
|
||||
fn = getattr(device, method_name, None)
|
||||
if callable(fn):
|
||||
try:
|
||||
value = fn()
|
||||
if value:
|
||||
actual_mx = str(value)
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
usb_speed = None
|
||||
try:
|
||||
usb_speed = str(device.getUsbSpeed())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
rows = []
|
||||
|
||||
for f in device.getConnectedCameraFeatures():
|
||||
rows.append({
|
||||
"socket": socket_name(f.socket),
|
||||
"sensor": str(getattr(f, "sensorName", "") or "").upper(),
|
||||
"width": int(getattr(f, "width", 0) or 0),
|
||||
"height": int(getattr(f, "height", 0) or 0),
|
||||
"is_color": feature_is_color(f),
|
||||
"is_mono": feature_is_mono(f),
|
||||
"supported_types": supported_types(f),
|
||||
})
|
||||
|
||||
return rows, actual_mx, usb_speed
|
||||
|
||||
|
||||
def validate_and_resolve_hardware(rows: list[dict]) -> Dict[str, CameraInfo]:
|
||||
by_socket = {row["socket"]: row for row in rows}
|
||||
resolved = {}
|
||||
errors = []
|
||||
|
||||
for role in ROLES:
|
||||
contract = PRODUCT_TOPOLOGY[role]
|
||||
sock = contract["socket"]
|
||||
|
||||
row = by_socket.get(sock)
|
||||
if row is None:
|
||||
errors.append(f"{role.upper()}: {sock} ausente")
|
||||
continue
|
||||
|
||||
sensor = row["sensor"]
|
||||
|
||||
if sensor not in contract["allowed_sensors"]:
|
||||
errors.append(
|
||||
f"{role.upper()}: {sock} sensor={sensor}, "
|
||||
f"permitidos={contract['allowed_sensors']}"
|
||||
)
|
||||
continue
|
||||
|
||||
expected_w, expected_h = SENSOR_NATIVE_SIZE[sensor]
|
||||
|
||||
if row["width"] and row["height"]:
|
||||
if (row["width"], row["height"]) != (expected_w, expected_h):
|
||||
errors.append(
|
||||
f"{role.upper()}: {sensor} anunciou "
|
||||
f"{row['width']}x{row['height']}, esperado "
|
||||
f"{expected_w}x{expected_h}"
|
||||
)
|
||||
|
||||
if role == "rgb" and not row["is_color"]:
|
||||
errors.append(f"RGB: {sock}/{sensor} não anunciado COLOR")
|
||||
|
||||
if role in ("re", "nir") and not row["is_mono"]:
|
||||
errors.append(f"{role.upper()}: {sock}/{sensor} não anunciado MONO")
|
||||
|
||||
resolved[role] = CameraInfo(
|
||||
role=role,
|
||||
socket=sock,
|
||||
sensor=sensor,
|
||||
width=expected_w,
|
||||
height=expected_h,
|
||||
is_color=bool(row["is_color"]),
|
||||
is_mono=bool(row["is_mono"]),
|
||||
)
|
||||
|
||||
if errors:
|
||||
raise RuntimeError(
|
||||
"Topologia de produto inválida:\n - "
|
||||
+ "\n - ".join(errors)
|
||||
)
|
||||
|
||||
return resolved
|
||||
|
||||
|
||||
def hardware_signature_from_resolved(resolved: Dict[str, CameraInfo]) -> dict:
|
||||
return {
|
||||
role: {
|
||||
"socket": resolved[role].socket,
|
||||
"sensor": resolved[role].sensor,
|
||||
"size": [resolved[role].width, resolved[role].height],
|
||||
}
|
||||
for role in ROLES
|
||||
}
|
||||
|
||||
|
||||
def normalize_signature(sig: dict) -> dict:
|
||||
"""
|
||||
Aceita assinatura no formato dos calibradores de produção.
|
||||
Retorna apenas role/socket/sensor/size para comparação robusta.
|
||||
"""
|
||||
out = {}
|
||||
|
||||
for role in ROLES:
|
||||
item = (sig or {}).get(role, {}) or {}
|
||||
|
||||
socket = (
|
||||
item.get("socket")
|
||||
or item.get("socket_name")
|
||||
)
|
||||
|
||||
sensor = (
|
||||
item.get("sensor")
|
||||
or item.get("sensor_name")
|
||||
)
|
||||
|
||||
size = item.get("size")
|
||||
|
||||
if size is None:
|
||||
width = item.get("width")
|
||||
height = item.get("height")
|
||||
if width is not None and height is not None:
|
||||
size = [int(width), int(height)]
|
||||
|
||||
if socket is None or sensor is None or size is None:
|
||||
raise RuntimeError(
|
||||
f"hardware_signature incompleta para {role}: {item}"
|
||||
)
|
||||
|
||||
out[role] = {
|
||||
"socket": str(socket),
|
||||
"sensor": str(sensor).upper(),
|
||||
"size": [int(size[0]), int(size[1])],
|
||||
}
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def extract_radiometric_fragment(data: dict) -> dict:
|
||||
"""
|
||||
O artefato radiométrico de produção guarda:
|
||||
module_params_fragment.radiometric_normalization
|
||||
"""
|
||||
fragment = data.get("module_params_fragment", {}) or {}
|
||||
rn = fragment.get("radiometric_normalization")
|
||||
|
||||
if not isinstance(rn, dict):
|
||||
raise RuntimeError(
|
||||
"Artefato radiométrico sem "
|
||||
"module_params_fragment.radiometric_normalization"
|
||||
)
|
||||
|
||||
if not rn.get("enabled", False):
|
||||
raise RuntimeError(
|
||||
"radiometric_normalization do artefato não está enabled=true"
|
||||
)
|
||||
|
||||
return rn
|
||||
|
||||
|
||||
def validate_radiometry_artifact(
|
||||
data: dict,
|
||||
current_signature: dict,
|
||||
):
|
||||
schema = str(data.get("schema", ""))
|
||||
|
||||
if schema != "multispec_radiometric_calibration_v5":
|
||||
raise RuntimeError(
|
||||
f"Schema radiométrico inesperado: {schema!r}. "
|
||||
"Esperado 'multispec_radiometric_calibration_v5'."
|
||||
)
|
||||
|
||||
status = str(data.get("status", "")).lower()
|
||||
|
||||
if status not in ("good", "warning"):
|
||||
raise RuntimeError(
|
||||
f"Radiometria não homologada para consumo: status={status!r}"
|
||||
)
|
||||
|
||||
if not bool(data.get("promoted", False)):
|
||||
raise RuntimeError(
|
||||
"Artefato radiométrico não foi promovido."
|
||||
)
|
||||
|
||||
artifact_sig = normalize_signature(
|
||||
data.get("hardware_signature", {})
|
||||
)
|
||||
|
||||
if artifact_sig != current_signature:
|
||||
raise RuntimeError(
|
||||
"Hardware conectado não corresponde ao hardware da radiometria.\n"
|
||||
f"Atual : {current_signature}\n"
|
||||
f"Rad : {artifact_sig}"
|
||||
)
|
||||
|
||||
rn = extract_radiometric_fragment(data)
|
||||
|
||||
refs = rn.get("reference_controls", {}) or {}
|
||||
|
||||
for role in ROLES:
|
||||
ref = refs.get(role)
|
||||
|
||||
if not isinstance(ref, dict):
|
||||
raise RuntimeError(
|
||||
f"reference_controls ausente para {role}"
|
||||
)
|
||||
|
||||
exp = ref.get("exposure_time_us")
|
||||
iso = ref.get("sensitivity_iso")
|
||||
|
||||
if exp is None or float(exp) <= 0:
|
||||
raise RuntimeError(
|
||||
f"reference exposure inválida para {role}: {exp}"
|
||||
)
|
||||
|
||||
if iso is None or float(iso) < 50:
|
||||
raise RuntimeError(
|
||||
f"reference ISO inválido para {role}: {iso}"
|
||||
)
|
||||
|
||||
return rn
|
||||
|
||||
|
||||
def iso_to_analogue_gain(iso: float) -> float:
|
||||
"""
|
||||
O manager atual representa analogue_gain aproximadamente como ISO/100.
|
||||
"""
|
||||
gain = float(iso) / ISO_BASE
|
||||
return max(1.0, gain)
|
||||
|
||||
|
||||
def build_camera_settings(reference_controls: dict) -> dict:
|
||||
settings = {}
|
||||
|
||||
for role in ROLES:
|
||||
ref = reference_controls[role]
|
||||
|
||||
exp = int(round(float(ref["exposure_time_us"])))
|
||||
iso = float(ref["sensitivity_iso"])
|
||||
gain = iso_to_analogue_gain(iso)
|
||||
|
||||
if role == "rgb":
|
||||
settings[role] = {
|
||||
"ae_enable": True,
|
||||
"awb_enable": True,
|
||||
"exposure_time_us": exp,
|
||||
"analogue_gain": gain,
|
||||
"colour_gains": [1.0, 1.0],
|
||||
}
|
||||
else:
|
||||
settings[role] = {
|
||||
"ae_enable": True,
|
||||
"awb_enable": False,
|
||||
"exposure_time_us": exp,
|
||||
"analogue_gain": gain,
|
||||
"colour_gains": None,
|
||||
}
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def build_rgb_calibration_policy() -> dict:
|
||||
"""
|
||||
Produto final mantém correção multiplicativa RGB desligada.
|
||||
Se um dia ela for homologada, deve existir um calibrador separado e
|
||||
dataset/runtime precisam usar o mesmo contrato.
|
||||
"""
|
||||
return {
|
||||
"enabled": False,
|
||||
"gains": {
|
||||
"R": 1.0,
|
||||
"G": 1.0,
|
||||
"B": 1.0,
|
||||
},
|
||||
"policy": "disabled_product_default",
|
||||
"reason": (
|
||||
"No validated RGB tensor-gain calibration is currently active. "
|
||||
"Historical manual gains are intentionally discarded."
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def compare_existing_module_params(
|
||||
module_params_path: Optional[str],
|
||||
generated_fragment: dict,
|
||||
) -> dict:
|
||||
if not module_params_path:
|
||||
return {
|
||||
"available": False,
|
||||
"path": None,
|
||||
}
|
||||
|
||||
p = Path(module_params_path)
|
||||
|
||||
if not p.is_file():
|
||||
return {
|
||||
"available": False,
|
||||
"path": str(p),
|
||||
}
|
||||
|
||||
current = load_json(p)
|
||||
|
||||
current_camera = current.get("camera_settings")
|
||||
current_rgb = current.get("rgb_calibration")
|
||||
|
||||
generated_camera = generated_fragment["camera_settings"]
|
||||
generated_rgb = generated_fragment["rgb_calibration"]
|
||||
|
||||
return {
|
||||
"available": True,
|
||||
"path": str(p),
|
||||
"schema": current.get("schema"),
|
||||
"camera_settings_equal": current_camera == generated_camera,
|
||||
"rgb_calibration_equal": current_rgb == generated_rgb,
|
||||
"current_camera_settings": current_camera,
|
||||
"generated_camera_settings": generated_camera,
|
||||
"current_rgb_calibration": current_rgb,
|
||||
"generated_rgb_calibration": generated_rgb,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Gerador/auditor de produção para camera_settings e "
|
||||
"política rgb_calibration do módulo multiespectral."
|
||||
),
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--mx-id",
|
||||
default=None,
|
||||
help="MX ID da OAK. Vazio usa o primeiro dispositivo disponível.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--radiometry-json",
|
||||
default="calibration/radiometry_calibration_v5.json",
|
||||
help="Artefato radiométrico homologado.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--out-json",
|
||||
default="calibration/camera_startup_profile_v3.json",
|
||||
help="Artefato ativo desta etapa.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--compare-module-params",
|
||||
default="calibration/module_params.json",
|
||||
help="Opcional: audita diferenças contra module_params existente.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--module-id",
|
||||
default="",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--operator",
|
||||
default="",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--notes",
|
||||
default="",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--check-only",
|
||||
action="store_true",
|
||||
help="Valida e imprime o fragmento, mas não salva.",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
rows, actual_mx, usb_speed = discover_hardware(args.mx_id)
|
||||
resolved = validate_and_resolve_hardware(rows)
|
||||
|
||||
current_signature = hardware_signature_from_resolved(resolved)
|
||||
|
||||
radiometry = load_json(args.radiometry_json)
|
||||
|
||||
rn = validate_radiometry_artifact(
|
||||
radiometry,
|
||||
current_signature,
|
||||
)
|
||||
|
||||
reference_controls = rn["reference_controls"]
|
||||
|
||||
camera_settings = build_camera_settings(reference_controls)
|
||||
rgb_calibration = build_rgb_calibration_policy()
|
||||
|
||||
module_params_fragment = {
|
||||
"camera_settings": camera_settings,
|
||||
"rgb_calibration": {
|
||||
"enabled": False,
|
||||
"gains": {
|
||||
"R": 1.0,
|
||||
"G": 1.0,
|
||||
"B": 1.0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
audit = compare_existing_module_params(
|
||||
args.compare_module_params,
|
||||
module_params_fragment,
|
||||
)
|
||||
|
||||
payload = {
|
||||
"schema": SCHEMA,
|
||||
"created_at": now_str(),
|
||||
"status": "good",
|
||||
"promoted": not args.check_only,
|
||||
"runtime_effect": (
|
||||
"startup_camera_policy_and_explicit_rgb_gain_disable"
|
||||
),
|
||||
"device_mx_id": actual_mx,
|
||||
"usb_speed": usb_speed,
|
||||
"hardware_inventory": rows,
|
||||
"hardware_signature": current_signature,
|
||||
"source_radiometry": {
|
||||
"path": str(args.radiometry_json),
|
||||
"schema": radiometry.get("schema"),
|
||||
"session_id": radiometry.get("session_id"),
|
||||
"status": radiometry.get("status"),
|
||||
"promoted": radiometry.get("promoted"),
|
||||
"reference_controls": reference_controls,
|
||||
},
|
||||
"startup_policy": {
|
||||
"mode": "ae_with_calibrated_manual_fallback",
|
||||
"rgb_awb": "auto_for_isp_preview_only",
|
||||
"spectral_awb": "off_not_applicable",
|
||||
"manual_fallback_source": (
|
||||
"radiometric_normalization.reference_controls"
|
||||
),
|
||||
"note": (
|
||||
"With AE enabled, manager stores exposure/gain as fallback "
|
||||
"and does not force them manually at startup."
|
||||
),
|
||||
},
|
||||
"rgb_calibration_policy": rgb_calibration,
|
||||
"module_params_fragment": module_params_fragment,
|
||||
"existing_module_params_audit": audit,
|
||||
"traceability": {
|
||||
"module_id": args.module_id or None,
|
||||
"operator": args.operator or None,
|
||||
},
|
||||
"notes": args.notes or "",
|
||||
}
|
||||
|
||||
print("=" * 82)
|
||||
print("CAMERA STARTUP PROFILE - PRODUCTION")
|
||||
print(f"MX ID : {actual_mx}")
|
||||
print(f"USB : {usb_speed}")
|
||||
print("-" * 82)
|
||||
|
||||
for role in ROLES:
|
||||
c = resolved[role]
|
||||
s = camera_settings[role]
|
||||
|
||||
print(
|
||||
f"{c.socket} -> {role.upper():3s} | "
|
||||
f"{c.sensor:8s} | {c.width}x{c.height} | "
|
||||
f"AE={s['ae_enable']} AWB={s['awb_enable']} | "
|
||||
f"fallback={s['exposure_time_us']}us gain={s['analogue_gain']:.3f}"
|
||||
)
|
||||
|
||||
print("-" * 82)
|
||||
print("rgb_calibration: DISABLED | gains = 1.0 / 1.0 / 1.0")
|
||||
|
||||
if audit.get("available"):
|
||||
print(
|
||||
"module_params audit: "
|
||||
f"camera_settings_equal={audit['camera_settings_equal']} | "
|
||||
f"rgb_calibration_equal={audit['rgb_calibration_equal']}"
|
||||
)
|
||||
else:
|
||||
print("module_params audit: arquivo não disponível")
|
||||
|
||||
if args.check_only:
|
||||
print("[CHECK-ONLY] Nenhum arquivo alterado.")
|
||||
print("=" * 82)
|
||||
return
|
||||
|
||||
out = Path(args.out_json)
|
||||
ensure_dir(out.parent)
|
||||
|
||||
if out.exists():
|
||||
backup = out.with_name(
|
||||
out.stem
|
||||
+ f".backup_{stamp()}"
|
||||
+ out.suffix
|
||||
)
|
||||
shutil.copy2(out, backup)
|
||||
|
||||
save_json_atomic(out, payload)
|
||||
|
||||
print(f"[PASS] Artefato salvo: {out}")
|
||||
print("[ASSEMBLER] Consumir module_params_fragment deste JSON.")
|
||||
print("=" * 82)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,654 +0,0 @@
|
|||
import json
|
||||
import argparse
|
||||
import os
|
||||
from copy import deepcopy
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Helpers
|
||||
# ============================================================
|
||||
|
||||
|
||||
def now_str():
|
||||
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def load_json(path, required=True):
|
||||
if not path or not os.path.isfile(path):
|
||||
if required:
|
||||
raise FileNotFoundError(f"Arquivo não encontrado: {path}")
|
||||
return {}
|
||||
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def save_json(path, data):
|
||||
out_dir = os.path.dirname(os.path.abspath(path))
|
||||
if out_dir:
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
f.write("\n")
|
||||
|
||||
|
||||
def rel_or_abs(path):
|
||||
"""
|
||||
Mantém o caminho como veio, mas normaliza separadores.
|
||||
Isso evita quebrar projetos Windows/Linux e deixa o module_params legível.
|
||||
"""
|
||||
if path is None:
|
||||
return None
|
||||
return str(path).replace("\\", "/")
|
||||
|
||||
|
||||
def deep_merge(base, update, *, skip_none=True):
|
||||
"""
|
||||
Merge recursivo seguro.
|
||||
|
||||
- dict + dict: combina recursivamente.
|
||||
- listas/escalares: valor novo substitui o antigo.
|
||||
- None: por padrão NÃO apaga valor antigo, para evitar perder calibração quando
|
||||
um arquivo fonte não conhece determinada chave.
|
||||
"""
|
||||
if not isinstance(base, dict):
|
||||
base = {}
|
||||
out = deepcopy(base)
|
||||
|
||||
if not isinstance(update, dict):
|
||||
return out
|
||||
|
||||
for key, value in update.items():
|
||||
if value is None and skip_none:
|
||||
continue
|
||||
|
||||
if isinstance(value, dict) and isinstance(out.get(key), dict):
|
||||
out[key] = deep_merge(out[key], value, skip_none=skip_none)
|
||||
else:
|
||||
out[key] = deepcopy(value)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def first_dict(*values):
|
||||
for value in values:
|
||||
if isinstance(value, dict):
|
||||
return value
|
||||
return None
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Defaults coerentes com RawProcessorCore + module_params atual
|
||||
# ============================================================
|
||||
|
||||
|
||||
DEFAULT_RGB_PROCESSING = {
|
||||
"mode": "bayer_planes",
|
||||
}
|
||||
|
||||
|
||||
DEFAULT_PATCH_NORMALIZATION = {
|
||||
"enabled": True,
|
||||
"apply_when_metering_mode": "reference_patches",
|
||||
"apply_stage": "after_fusion",
|
||||
"method": "gray_scale_with_white_guard",
|
||||
"space": "multispec_tensor",
|
||||
"targets_by_patch_channel": {
|
||||
"black": {
|
||||
"R": 0.06,
|
||||
"G": 0.06,
|
||||
"B": 0.06,
|
||||
"RE": 0.06,
|
||||
"NIR": 0.06,
|
||||
},
|
||||
"gray": {
|
||||
"R": 0.34,
|
||||
"G": 0.34,
|
||||
"B": 0.34,
|
||||
"RE": 0.24,
|
||||
"NIR": 0.30,
|
||||
},
|
||||
"white": {
|
||||
"R": 0.78,
|
||||
"G": 0.78,
|
||||
"B": 0.78,
|
||||
"RE": 0.78,
|
||||
"NIR": 0.78,
|
||||
},
|
||||
},
|
||||
"white_guard_max": 0.92,
|
||||
"white_guard_max_by_channel": {
|
||||
"R": 0.92,
|
||||
"G": 0.92,
|
||||
"B": 0.92,
|
||||
"RE": 0.88,
|
||||
"NIR": 0.88,
|
||||
},
|
||||
"scale_min": 0.35,
|
||||
"scale_max": 2.5,
|
||||
"clip_output": True,
|
||||
"require_valid_gray": True,
|
||||
"use_black_for_offset": False,
|
||||
"save_patch_stats": True,
|
||||
"rgb_saturation_guard_enabled": True,
|
||||
"rgb_saturation_guard_mode": "fade_strength",
|
||||
"rgb_saturation_soft_start": 0.88,
|
||||
"rgb_saturation_hard": 0.97,
|
||||
"rgb_saturation_threshold": 0.97,
|
||||
}
|
||||
|
||||
|
||||
DEFAULT_FLATFIELD_RUNTIME = {
|
||||
"strength": 0.35,
|
||||
"strength_by_channel": {
|
||||
"R": 0.9,
|
||||
"G": 0.9,
|
||||
"B": 0.9,
|
||||
"RE": 0.25,
|
||||
"NIR": 0.25,
|
||||
},
|
||||
"gain_min_runtime": 0.75,
|
||||
"gain_max_runtime": 1.35,
|
||||
"runtime_smooth_ksize": 81,
|
||||
"saturation_guard_enabled": True,
|
||||
"saturation_guard_mode": "fade_strength",
|
||||
"saturation_guard_threshold": 0.97,
|
||||
"saturation_guard_soft_start": 0.88,
|
||||
"saturation_guard_hard": 0.97,
|
||||
}
|
||||
|
||||
|
||||
DEFAULT_RADIOMETRIC_NORMALIZATION = {
|
||||
"enabled": False,
|
||||
"method": "exposure_gain_reference",
|
||||
"apply_stage": "after_dark_before_flat_gain",
|
||||
"reference_controls": {
|
||||
"rgb": {"exposure_time_us": 3000, "analogue_gain": 1.0},
|
||||
"re": {"exposure_time_us": 7000, "analogue_gain": 1.0},
|
||||
"nir": {"exposure_time_us": 7000, "analogue_gain": 1.0},
|
||||
},
|
||||
"clip_output": True,
|
||||
}
|
||||
|
||||
|
||||
DEFAULT_RADIOMETRIC_CONFIG = {
|
||||
"enabled": True,
|
||||
"interval_s": 0.25,
|
||||
"verbose": True,
|
||||
"metering_mode": "reference_patches",
|
||||
"spectral_control_mode": "shared",
|
||||
"control_metric": "p50",
|
||||
"target_value": 0.5,
|
||||
"deadband": 0.055,
|
||||
"p95_limit": 0.975,
|
||||
"saturation_limit_pct": 5.0,
|
||||
"alpha": 0.18,
|
||||
"exp_step_gain": 0.55,
|
||||
"prefer_exposure": True,
|
||||
"exp_min_us": 100,
|
||||
"exp_max_us": 80000,
|
||||
"gain_min": 1.0,
|
||||
"gain_max": 4.0,
|
||||
"exp_apply_threshold_us": 15,
|
||||
"gain_apply_threshold": 0.05,
|
||||
"apply_same_spectral_to_both": True,
|
||||
"spectral_roles": ["re", "nir"],
|
||||
"dark_limit_pct": 35.0,
|
||||
"control_strategy": "ratio",
|
||||
"ratio_alpha": 0.42,
|
||||
"ratio_min": 0.72,
|
||||
"ratio_max": 1.38,
|
||||
"reduce_fast_factor": 0.8,
|
||||
"factor_min": 0.62,
|
||||
"factor_max": 1.42,
|
||||
"gain_return_enabled": True,
|
||||
"gain_reduce_on_saturation": True,
|
||||
"gain_increase_required_cycles": 3,
|
||||
"gain_decrease_required_cycles": 1,
|
||||
"gain_step_up": 0.3,
|
||||
"gain_step_down": 0.5,
|
||||
"gain_hard_reset_on_saturation": False,
|
||||
"exp_high_ratio_for_gain": 0.95,
|
||||
"exp_low_ratio_for_gain_return": 0.75,
|
||||
"role_limits": {
|
||||
"rgb": {"exp_min_us": 100, "exp_max_us": 80000, "gain_min": 1.0, "gain_max": 2.0},
|
||||
"re": {"exp_min_us": 100, "exp_max_us": 3500, "gain_min": 1.0, "gain_max": 2.0},
|
||||
"nir": {"exp_min_us": 100, "exp_max_us": 3500, "gain_min": 1.0, "gain_max": 2.0},
|
||||
},
|
||||
"ready_required_cycles": 3,
|
||||
"patch_control_mode": "gray_primary",
|
||||
"patch_require_order": True,
|
||||
"patch_min_separation": 0.08,
|
||||
"patch_white_sat_limit_pct": 5.0,
|
||||
"patch_white_p95_limit": 0.985,
|
||||
"patch_black_dark_limit_pct": 80.0,
|
||||
"patch_black_max_p50": 0.2,
|
||||
"patch_gray_min_p50": 0.08,
|
||||
"patch_gray_max_p50": 0.85,
|
||||
"patch_roi_contract": "multi_roi_by_role_v1",
|
||||
"patch_roi_reduce_method": "median_valid_rois",
|
||||
"patch_roi_outlier_reject": True,
|
||||
"patch_roi_max_p50_delta": 0.12,
|
||||
"global_saturation_guard_enabled": True,
|
||||
"global_guard_roi_pct": {"x0": 0.05, "y0": 0.05, "x1": 0.95, "y1": 0.76},
|
||||
"global_guard_sat_threshold": 0.985,
|
||||
"global_guard_near_sat_threshold": 0.94,
|
||||
"global_guard_sat_pct_soft": 0.50,
|
||||
"global_guard_sat_pct_hard": 1.5,
|
||||
"global_guard_sat_pct_extreme": 5.0,
|
||||
"global_guard_blob_pct_soft": 0.20,
|
||||
"global_guard_blob_pct_hard": 0.80,
|
||||
"global_guard_blob_pct_extreme": 2.2,
|
||||
"global_guard_min_blob_px": 48,
|
||||
"global_guard_downsample_max_side": 320,
|
||||
"global_guard_reduce_factor_soft": 0.96,
|
||||
"global_guard_reduce_factor_hard": 0.82,
|
||||
"global_guard_reduce_factor_extreme": 0.62,
|
||||
"sun_guard_enabled": True,
|
||||
"sun_guard_p99_threshold": 0.96,
|
||||
"sun_guard_near_sat_pct_threshold": 2.0,
|
||||
"sun_guard_freeze_increase_cycles": 1,
|
||||
"sun_guard_allow_decrease": True,
|
||||
"guard_force_apply_enabled": True,
|
||||
"guard_force_apply_soft": False,
|
||||
"guard_force_apply_hard": True,
|
||||
"guard_force_apply_extreme": True,
|
||||
"guard_force_apply_on_patch_saturation": True,
|
||||
"guard_freeze_cycles_soft": 1,
|
||||
"guard_freeze_cycles_hard": 2,
|
||||
"guard_freeze_cycles_extreme": 3,
|
||||
"guard_reapply_min_exp_on_emergency": True,
|
||||
"guard_min_exp_margin_us": 80,
|
||||
"patch_two_roi_soften_risk": True,
|
||||
"patch_two_roi_white_risk_percentile": 75,
|
||||
"patch_two_roi_other_risk_percentile": 50,
|
||||
"patch_white_single_roi_saturation_reject": True,
|
||||
"patch_white_roi_reject_sat_pct": 5.0,
|
||||
"patch_white_roi_reject_p95": 0.995,
|
||||
}
|
||||
|
||||
|
||||
def default_module_template():
|
||||
return {
|
||||
"schema": "multispec_module_params_v3",
|
||||
"saved_at": now_str(),
|
||||
"frame_type": "RAW_BRUTO",
|
||||
"capture_mode_requested": "AUTO",
|
||||
"capture_mode_effective": "AUTO",
|
||||
"raw_policy": "allow_single",
|
||||
"sensor_width": 1280,
|
||||
"sensor_height": 800,
|
||||
"bayer_pattern": "BGGR",
|
||||
"rgb_processing": deepcopy(DEFAULT_RGB_PROCESSING),
|
||||
"camera_settings": {},
|
||||
"fusion_config": {
|
||||
"alignment_mode": "manual_affine",
|
||||
"baseline_mm": 75.0,
|
||||
"reference_camera": "rgb",
|
||||
"manual_offsets": {
|
||||
"re": {"dx": 0, "dy": 0, "theta_deg": 0.0},
|
||||
"nir": {"dx": 0, "dy": 0, "theta_deg": 0.0},
|
||||
},
|
||||
"homographies": {
|
||||
"re_to_rgb": None,
|
||||
"nir_to_rgb": None,
|
||||
},
|
||||
"crop_valid_common": True,
|
||||
"resize_after_crop": True,
|
||||
"target_size": None,
|
||||
},
|
||||
"radiometric_config": deepcopy(DEFAULT_RADIOMETRIC_CONFIG),
|
||||
"radiometric_normalization": deepcopy(DEFAULT_RADIOMETRIC_NORMALIZATION),
|
||||
"patch_normalization": deepcopy(DEFAULT_PATCH_NORMALIZATION),
|
||||
"rgb_calibration": {
|
||||
"enabled": False,
|
||||
"gains": {"R": 1.0, "G": 1.0, "B": 1.0},
|
||||
},
|
||||
"flatfield_config": deep_merge(
|
||||
{
|
||||
"enabled": False,
|
||||
"reason": "flatfield não informado ou arquivo inexistente",
|
||||
"subtract_dark": True,
|
||||
"apply_before_fusion": True,
|
||||
"apply_after_decode": True,
|
||||
"apply_space": "native_camera_space",
|
||||
"map_type": "gain",
|
||||
"channels": ["R", "G", "B", "RE", "NIR"],
|
||||
"channel_maps": {},
|
||||
"clip_output": True,
|
||||
},
|
||||
DEFAULT_FLATFIELD_RUNTIME,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Builders / normalizers
|
||||
# ============================================================
|
||||
|
||||
|
||||
def build_flatfield_config(flatfield_json_path, flatfield_data, previous_flatfield_config=None):
|
||||
"""
|
||||
Espera o JSON gerado pelo flatfield_calibration_tool_v2.py.
|
||||
|
||||
Importante: usa previous_flatfield_config como base para preservar knobs runtime
|
||||
que não existem no arquivo de calibração do flat-field, como strength,
|
||||
gain_min_runtime, runtime_smooth_ksize e saturation_guard_*.
|
||||
"""
|
||||
base = deep_merge(
|
||||
deep_merge({}, previous_flatfield_config or {}),
|
||||
DEFAULT_FLATFIELD_RUNTIME,
|
||||
)
|
||||
|
||||
if not isinstance(flatfield_data, dict):
|
||||
return deep_merge(base, {
|
||||
"enabled": False,
|
||||
"reason": "flatfield_json ausente ou inválido",
|
||||
})
|
||||
|
||||
outputs = flatfield_data.get("outputs", {}) or {}
|
||||
maps = flatfield_data.get("maps", {}) or {}
|
||||
|
||||
npz_path = outputs.get("npz")
|
||||
if not npz_path:
|
||||
base_name, _ = os.path.splitext(flatfield_json_path)
|
||||
npz_path = base_name + ".npz"
|
||||
|
||||
channels = flatfield_data.get("channels") or base.get("channels") or ["R", "G", "B", "RE", "NIR"]
|
||||
|
||||
channel_maps = {}
|
||||
previous_channel_maps = base.get("channel_maps", {}) or {}
|
||||
for ch in channels:
|
||||
m = maps.get(ch, {}) or {}
|
||||
prev = previous_channel_maps.get(ch, {}) or {}
|
||||
channel_maps[ch] = deep_merge(prev, {
|
||||
"gain_key": m.get("gain_key", f"gain_{ch}"),
|
||||
"flat_norm_key": m.get("flat_norm_key", f"flat_norm_{ch}"),
|
||||
"white_median_key": m.get("white_median_key", f"white_median_{ch}"),
|
||||
"dark_median_key": m.get("dark_median_key", f"dark_median_{ch}"),
|
||||
"shape": m.get("shape"),
|
||||
"gain_min": m.get("gain_min"),
|
||||
"gain_max": m.get("gain_max"),
|
||||
"gain_mean": m.get("gain_mean"),
|
||||
"gain_std": m.get("gain_std"),
|
||||
})
|
||||
|
||||
generated = {
|
||||
"enabled": True,
|
||||
"subtract_dark": True,
|
||||
"schema": flatfield_data.get("schema", "multispec_flatfield_v1"),
|
||||
"created_at": flatfield_data.get("created_at"),
|
||||
"json_file": rel_or_abs(flatfield_json_path),
|
||||
"npz_file": rel_or_abs(npz_path),
|
||||
"apply_before_fusion": True,
|
||||
"apply_after_decode": True,
|
||||
"apply_space": "native_camera_space",
|
||||
"map_type": "gain",
|
||||
"formula": "channel_corrected = max(channel_linear - dark, 0) * gain_map",
|
||||
"channels": channels,
|
||||
"channel_maps": channel_maps,
|
||||
"exp_gain_correct_during_flat_capture": bool(flatfield_data.get("exp_gain_correct", False)),
|
||||
"smooth_ksize": flatfield_data.get("smooth_ksize"),
|
||||
"min_gain": flatfield_data.get("min_gain"),
|
||||
"max_gain": flatfield_data.get("max_gain"),
|
||||
"notes": flatfield_data.get("notes", ""),
|
||||
}
|
||||
|
||||
return deep_merge(base, generated)
|
||||
|
||||
|
||||
def pick_radiometric_config(radiometric_data: dict, selected_profile: str | None = None):
|
||||
if not isinstance(radiometric_data, dict):
|
||||
return None
|
||||
|
||||
root_cfg = radiometric_data.get("radiometric_config")
|
||||
if isinstance(root_cfg, dict):
|
||||
return root_cfg
|
||||
|
||||
active_profile = radiometric_data.get("active_profile")
|
||||
if active_profile in ("global_scene_mode", "three_reference_patches_mode"):
|
||||
cfg = radiometric_data.get(active_profile, {}).get("radiometric_config")
|
||||
if isinstance(cfg, dict):
|
||||
return cfg
|
||||
|
||||
if selected_profile:
|
||||
cfg = radiometric_data.get(selected_profile, {}).get("radiometric_config")
|
||||
if isinstance(cfg, dict):
|
||||
return cfg
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def normalize_patch_normalization_contract(base_patch_config, incoming_patch_config=None):
|
||||
"""
|
||||
Garante o contrato atual do RawProcessorCore.
|
||||
|
||||
- Sempre tem targets_by_patch_channel.
|
||||
- Preserva white_guard_max_by_channel.
|
||||
- Preserva rgb_saturation_guard_*.
|
||||
- Remove a chave legada targets, porque ela não é usada pelo core atual.
|
||||
"""
|
||||
cfg = deep_merge(DEFAULT_PATCH_NORMALIZATION, base_patch_config or {})
|
||||
cfg = deep_merge(cfg, incoming_patch_config or {})
|
||||
|
||||
legacy_targets = cfg.pop("targets", None)
|
||||
if isinstance(legacy_targets, dict) and "targets_by_patch_channel" not in cfg:
|
||||
# Fallback conservador. Na prática, com DEFAULT_PATCH_NORMALIZATION acima,
|
||||
# normalmente não entra aqui. Mantido só para arquivos muito antigos.
|
||||
t = deepcopy(DEFAULT_PATCH_NORMALIZATION["targets_by_patch_channel"])
|
||||
for patch_type in ("black", "gray", "white"):
|
||||
if patch_type in legacy_targets:
|
||||
scalar = legacy_targets.get(patch_type)
|
||||
try:
|
||||
scalar = float(scalar)
|
||||
for ch in ("R", "G", "B", "RE", "NIR"):
|
||||
t[patch_type][ch] = scalar
|
||||
except Exception:
|
||||
pass
|
||||
cfg["targets_by_patch_channel"] = t
|
||||
|
||||
cfg = deep_merge(DEFAULT_PATCH_NORMALIZATION, cfg)
|
||||
return cfg
|
||||
|
||||
|
||||
def normalize_radiometric_config(base_rad_config, incoming_rad_config=None):
|
||||
cfg = deep_merge(DEFAULT_RADIOMETRIC_CONFIG, base_rad_config or {})
|
||||
cfg = deep_merge(cfg, incoming_rad_config or {})
|
||||
return cfg
|
||||
|
||||
|
||||
def normalize_radiometric_normalization(base_config, incoming_config=None):
|
||||
cfg = deep_merge(DEFAULT_RADIOMETRIC_NORMALIZATION, base_config or {})
|
||||
cfg = deep_merge(cfg, incoming_config or {})
|
||||
cfg["enabled"] = bool(cfg.get("enabled", False))
|
||||
return cfg
|
||||
|
||||
|
||||
def build_fusion_config(fusion_data, previous_fusion_config=None):
|
||||
base = previous_fusion_config or {}
|
||||
generated = {
|
||||
"alignment_mode": fusion_data.get("alignment_mode"),
|
||||
"baseline_mm": fusion_data.get("baseline_mm"),
|
||||
"reference_camera": fusion_data.get("reference_camera"),
|
||||
"manual_offsets": fusion_data.get("manual_offsets"),
|
||||
"homographies": fusion_data.get("homographies"),
|
||||
"crop_valid_common": fusion_data.get("crop_valid_common"),
|
||||
"resize_after_crop": fusion_data.get("resize_after_crop"),
|
||||
"target_size": fusion_data.get("target_size"),
|
||||
}
|
||||
cfg = deep_merge(default_module_template()["fusion_config"], base)
|
||||
cfg = deep_merge(cfg, generated)
|
||||
return cfg
|
||||
|
||||
|
||||
def load_base_module(args):
|
||||
"""
|
||||
Carrega defaults do module_params atual.
|
||||
|
||||
Prioridade:
|
||||
1. --base_module_json, se informado.
|
||||
2. --out, se já existir.
|
||||
3. template interno coerente com o contrato atual.
|
||||
"""
|
||||
candidates = []
|
||||
if args.base_module_json:
|
||||
candidates.append(args.base_module_json)
|
||||
if args.out:
|
||||
candidates.append(args.out)
|
||||
|
||||
for path in candidates:
|
||||
if path and os.path.isfile(path):
|
||||
print(f"[INFO] Usando module_params base: {path}")
|
||||
return deep_merge(default_module_template(), load_json(path, required=True))
|
||||
|
||||
print("[WARN] Nenhum module_params base encontrado. Usando defaults internos.")
|
||||
return default_module_template()
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Main
|
||||
# ============================================================
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Monta o module_params.json preservando o contrato atual do RawProcessorCore.",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
parser.add_argument("--camera_json", default="calibration/sensor_calibration.json")
|
||||
parser.add_argument("--fusion_json", default="calibration/manual_offsets.json")
|
||||
parser.add_argument("--radiometric_json", default="calibration/radiometric_config.json")
|
||||
parser.add_argument(
|
||||
"--radiometric_profile",
|
||||
default="global_scene_mode",
|
||||
choices=["global_scene_mode", "three_reference_patches_mode"],
|
||||
)
|
||||
parser.add_argument("--flatfield_json", default="calibration/flatfield_maps_v1.json")
|
||||
parser.add_argument("--disable_flatfield", action="store_true")
|
||||
parser.add_argument("--base_module_json", default=None, help="module_params atual usado como defaults antes de sobrescrever")
|
||||
parser.add_argument("--out", default="calibration/module_params.json")
|
||||
args = parser.parse_args()
|
||||
|
||||
module_base = load_base_module(args)
|
||||
|
||||
cam_data = load_json(args.camera_json, required=True)
|
||||
fusion_data = load_json(args.fusion_json, required=True)
|
||||
radiometric_data = load_json(args.radiometric_json, required=False) if args.radiometric_json else {}
|
||||
|
||||
# =========================
|
||||
# MODULE PARAMS FINAL
|
||||
# =========================
|
||||
module_params = deepcopy(module_base)
|
||||
module_params["schema"] = "multispec_module_params_v3"
|
||||
module_params["saved_at"] = now_str()
|
||||
|
||||
# =========================
|
||||
# ROOT / CAMERA
|
||||
# =========================
|
||||
root_updates = {
|
||||
"frame_type": cam_data.get("frame_type", fusion_data.get("frame_type")),
|
||||
"capture_mode_requested": cam_data.get("capture_mode_requested"),
|
||||
"capture_mode_effective": cam_data.get("capture_mode_effective"),
|
||||
"raw_policy": cam_data.get("raw_policy"),
|
||||
"sensor_width": cam_data.get("sensor_width", fusion_data.get("sensor_width")),
|
||||
"sensor_height": cam_data.get("sensor_height", fusion_data.get("sensor_height")),
|
||||
"bayer_pattern": cam_data.get("bayer_pattern", fusion_data.get("bayer_pattern")),
|
||||
}
|
||||
module_params = deep_merge(module_params, root_updates)
|
||||
|
||||
module_params["rgb_processing"] = deep_merge(
|
||||
deep_merge(DEFAULT_RGB_PROCESSING, module_base.get("rgb_processing", {})),
|
||||
cam_data.get("rgb_processing") if isinstance(cam_data.get("rgb_processing"), dict) else {},
|
||||
)
|
||||
|
||||
camera_settings = cam_data.get("camera_settings")
|
||||
if not isinstance(camera_settings, dict):
|
||||
camera_settings = module_base.get("camera_settings")
|
||||
if not isinstance(camera_settings, dict):
|
||||
raise RuntimeError("camera_json sem camera_settings válido e sem fallback no module_params base")
|
||||
module_params["camera_settings"] = camera_settings
|
||||
|
||||
module_params["rgb_calibration"] = deep_merge(
|
||||
module_base.get("rgb_calibration", {}),
|
||||
cam_data.get("rgb_calibration") if isinstance(cam_data.get("rgb_calibration"), dict) else {},
|
||||
)
|
||||
|
||||
# =========================
|
||||
# FUSION
|
||||
# =========================
|
||||
module_params["fusion_config"] = build_fusion_config(
|
||||
fusion_data,
|
||||
previous_fusion_config=module_base.get("fusion_config", {}),
|
||||
)
|
||||
|
||||
# =========================
|
||||
# RADIOMETRIC
|
||||
# =========================
|
||||
incoming_rad = pick_radiometric_config(radiometric_data, selected_profile=args.radiometric_profile)
|
||||
if not isinstance(incoming_rad, dict):
|
||||
incoming_rad = cam_data.get("radiometric_config") if isinstance(cam_data.get("radiometric_config"), dict) else {}
|
||||
|
||||
module_params["radiometric_config"] = normalize_radiometric_config(
|
||||
module_base.get("radiometric_config", {}),
|
||||
incoming_rad,
|
||||
)
|
||||
|
||||
incoming_rad_norm = first_dict(
|
||||
radiometric_data.get("radiometric_normalization") if isinstance(radiometric_data, dict) else None,
|
||||
cam_data.get("radiometric_normalization") if isinstance(cam_data, dict) else None,
|
||||
) or {}
|
||||
module_params["radiometric_normalization"] = normalize_radiometric_normalization(
|
||||
module_base.get("radiometric_normalization", {}),
|
||||
incoming_rad_norm,
|
||||
)
|
||||
|
||||
incoming_patch_norm = first_dict(
|
||||
radiometric_data.get("patch_normalization") if isinstance(radiometric_data, dict) else None,
|
||||
cam_data.get("patch_normalization") if isinstance(cam_data, dict) else None,
|
||||
) or {}
|
||||
module_params["patch_normalization"] = normalize_patch_normalization_contract(
|
||||
module_base.get("patch_normalization", {}),
|
||||
incoming_patch_norm,
|
||||
)
|
||||
|
||||
# =========================
|
||||
# FLATFIELD
|
||||
# =========================
|
||||
previous_flatfield = module_base.get("flatfield_config", {}) or {}
|
||||
if args.disable_flatfield:
|
||||
module_params["flatfield_config"] = deep_merge(previous_flatfield, {
|
||||
"enabled": False,
|
||||
"reason": "desabilitado via --disable_flatfield",
|
||||
})
|
||||
elif args.flatfield_json and os.path.isfile(args.flatfield_json):
|
||||
flatfield_data = load_json(args.flatfield_json, required=True)
|
||||
module_params["flatfield_config"] = build_flatfield_config(
|
||||
args.flatfield_json,
|
||||
flatfield_data,
|
||||
previous_flatfield_config=previous_flatfield,
|
||||
)
|
||||
else:
|
||||
# Não achou novo flatfield: preserva o anterior se já existia.
|
||||
module_params["flatfield_config"] = deep_merge(previous_flatfield, DEFAULT_FLATFIELD_RUNTIME)
|
||||
if not module_params["flatfield_config"].get("enabled", False):
|
||||
module_params["flatfield_config"]["reason"] = "flatfield não informado ou arquivo inexistente"
|
||||
|
||||
# =========================
|
||||
# Save
|
||||
# =========================
|
||||
save_json(args.out, module_params)
|
||||
|
||||
print(f"[OK] module_params gerado em: {args.out}")
|
||||
print("[OK] contrato preservado: rgb_processing, patch_normalization, radiometric_config e knobs runtime do flatfield")
|
||||
|
||||
flat_cfg = module_params.get("flatfield_config", {}) or {}
|
||||
if flat_cfg.get("enabled"):
|
||||
print(f"[OK] flatfield habilitado: {flat_cfg.get('npz_file')}")
|
||||
else:
|
||||
print(f"[WARN] flatfield desabilitado: {flat_cfg.get('reason')}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue