Перейти до основного вмісту

Візуальні вузли фронтенду EV74

Використовуйте операції EV74 через публічні фабрики вузлів Graph. Установіть узгоджений набір пакетів Core, Scheduler, Runner, Kernels і прошивки EV74. Старі ідентифікатори графів не перевіряють сумісність нативної прошивки; застосунку не потрібні ідентифікатори диспетчера.

Параметри якості зберігають наявне використання на рівні вихідного коду та стандартні позиції виходів, але змінюють компонування TrackKLTOptions у C++; наявні бінарні файли C++ не є ABI-сумісними. Перезберіть застосунки C++ і розширення Python із відповідною версією Core. Для запитів трекера v2 використовуйте узгоджений набір Kernels, Runner, Scheduler і прошивки EV74. Наявні нативні запити v1 і далі підтримуються; це не робить запити v2 сумісними зі старішою прошивкою.

Фабрика вузлівПризначення
nodes::FeatureHistogram / pyneat.nodes.feature_histogramГістограма відтінків сірого
nodes::GriderFast / pyneat.nodes.grider_fastКути FAST, розподілені за сіткою
nodes::TrackDescriptor / pyneat.nodes.track_descriptorКути FAST і дескриптори BRIEF
nodes::TrackKLT / pyneat.nodes.track_kltПірамідальне відстеження KLT та необов’язкове виявлення ознак поточного кадру

Контракти тензорів​

Логічна форма зображень — [B,H,W], де B — це batch_size. Не об’єднуйте пакет із висотою зображення. Входи пристрою можуть мати окремі виділення або коректні представлення спільного сховища. Обхідний шлях із копіюванням через CPU не потрібний.

ВузолВходиТипові публічні виходи
FeatureHistogramUInt8 [B,H,W]Int32 [B,256]
GriderFastUInt8 [B,H,W]Int32 [B,1+3*max_features]
TrackDescriptorUInt8 [B,H,W]Int32 [B,1+3*max_features]; Int32 [B,max_features,8]
TrackKLTUInt8 [B,H,W]; UInt8 [B,H,W]; Int32 [B,num_points,2]Float32 [B,num_points,2]; Int32 [B,num_points,1]

Формат ознак для кожного елемента пакета — [count,x0,y0,score0,...]. Читайте лише перші count записів. Невикористана місткість не є списком ознак. TrackDescriptor потребує descriptor_words == 8; кожний рядок дескриптора відповідає тому самому рядку вибраних ознак.

Вибір за сіткою та межі​

grid_x і grid_y ділять усе зображення на комірки. За місткості K і кількості комірок M кожна має K / M місць; перші K % M комірок у порядку рядків отримують ще одне. У кожній комірці вибираються найвищі оцінки, а загальний результат упорядковується за спаданням оцінки, за рівності — за зростанням (y,x). Розріджені комірки не передають свої місця іншим. min_px_dist пригнічує близькі точки навіть через межі комірок; точна рівність відстані дозволена. Після пригнічення кандидатів не додають, тому результат може містити менше ніж max_features точок.

Звичайний FAST включає центри x=3, y=3, x=W-4 і y=H-4. TrackDescriptor потребує повного фрагмента BRIEF 31×31, тому центри мають бути щонайменше за 15 пікселів від кожного краю. Відсутність дескрипторів у рядку 3 є очікуваною.

Входи та виходи KLT​

Передавайте впорядкований TensorList: попереднє зображення, поточне зображення, вхідні точки. На цьому прямому публічному маршруті з кількома входами непорожній логічний route.name має відповідати налаштованій позиції, а не змінювати порядок списку. Правильно впорядковані безіменні тензори також дозволені. Відсутні входи, суперечливі імена, неправильні типи чи форми та недоступні діапазони відхиляються до подання, зокрема й у наступних кадрах.

Щоб повторно використати сумісний вихідний тензор, зробіть поверхневу копію та перейменуйте або очистьте лише route.name для нової публічної позиції. Збережіть сховище, зміщення та метадані фізичного маршруту. Це правило не перейменовує внутрішні зв’язки графа й не замінює явний процесор вхідного маршруту моделі.

Типово TrackKLT публікує точки та статус. detect_new_features != 0 додає ознаки, виявлені на поточному зображенні. За вимкненого виявлення прихований вихід ознак не виділяється. publish_error = true додає Float32 [B,num_points,1] після наявних виходів: індекс 2 без виявлення, індекс 3 із виявленням. Позиції наявних виходів не змінюються.

Приклад C++​

Надайте два вектори зображень UInt8 640×480 і початкові координати Int32 64×2. Нижче кожний вхід має незалежне сховище EV74. Повертаються точки, статус і похибка.

#include <neat.h>
#include <cstdint>
#include <vector>

using namespace simaai::neat;

TensorList track_pair(const std::vector<std::uint8_t>& previous,
const std::vector<std::uint8_t>& current,
const std::vector<std::int32_t>& xy) {
constexpr int width = 640, height = 480, count = 64;
auto image = [&](const auto& pixels, const char* name) {
auto tensor = Tensor::from_vector(pixels, {1, height, width}, TensorMemory::EV74);
tensor.layout = TensorLayout::HW;
tensor.axis_semantics = {TensorAxisSemantic::N, TensorAxisSemantic::H,
TensorAxisSemantic::W};
tensor.route.name = name;
return tensor;
};
auto points = Tensor::from_vector(xy, {1, count, 2}, TensorMemory::EV74);
points.route.name = "input_points";
TensorList inputs{image(previous, "prev_image"), image(current, "cur_image"), points};

InputOptions input;
input.payload_type = PayloadType::Tensor;
input.format = FormatTag::UINT8;
input.width = input.max_width = width;
input.height = input.max_height = height;
input.depth = input.max_depth = 1;
input.memory_policy = InputMemoryPolicy::Ev74;
input.buffer_name = "prev_image";
input.caps_override = "application/vnd.simaai.tensor, representation=(string)tensor-set, "
"storage=(string)tensorbuffer";

TrackKLTOptions klt;
klt.width = width;
klt.height = height;
klt.num_points = count;
klt.win_half = 7;
klt.max_level = 2;
klt.max_iters = 20;
klt.publish_error = true;

Graph graph;
graph.add(nodes::Input(input));
graph.add(nodes::TrackKLT(klt));
graph.add(nodes::Output());
RunOptions options;
options.output_memory = OutputMemory::Owned;
Run run = graph.build(inputs, options);
TensorList outputs;
try {
outputs = run.run(inputs, 30000);
} catch (...) {
run.close();
throw;
}
run.close();
return outputs;
}

Керування якістю​

ПараметрТипове значенняЗначення
publish_errorfalseПублікує середню абсолютну різницю яскравості в кінцевій координаті. Типове output_error_name — output_error.
error_threshold-1.0-1 вимикає перевірку; інакше це скінченний поріг у [0,255]. Залишок вище порога відхиляється, рівність дозволена. Фільтрування працює і без публікації похибки.
min_eig_threshold0.00 вимикає перевірку; інакше це скінченний додатний поріг нормалізованого мінімального власного значення для оцінки текстури.
require_convergencefalseВимагає, щоб кінцеве оновлення в повній роздільності виконувало критерій збіжності. За false саме досягнення ліміту ітерацій не означає невдачі.

Залишок — це різниця яскравості, а не зміщення в пікселях чи впевненість. Його обчислюють у поверненій координаті; +inf означає, що коректний залишок не було обчислено. Показник текстури ділить найменше власне значення матриці центральних градієнтів на площу вікна й 255²; його масштаб не взаємозамінний із порогами OpenCV. Вибирайте пороги на репрезентативних калібрувальних даних, перевіряючи і збереження коректних траєкторій, і відхилення хибних.

Перевіряйте статус перед використанням координат. Некоректні початкові точки до розв’язання зберігають свої координати зі статусом 0. Скінченна обчислена точка поза зображенням або кандидат, відхилений порогом якості, може зберігати обчислені координати зі статусом 0. Типовий статус позначає придатність розв’язання й геометрії, а не доводить правильність відповідності в реальному світі.

Рух, межі та фіксована кількість точок​

Коли уточнення виходить за поточну плитку зображення, її повторно центрують і завантажують. Рух не обмежується мовчки діапазоном пошуку ±4 пікселі. Кількість завантажень та ітерацій обмежена. Граничні плитки повторюють крайні пікселі, використовуючи DMA лише всередині зображення. Це усуває стару смугу виключення, залежну від рівня піраміди, але не гарантує відстеження за довільного руху, перекриття чи неоднозначної текстури.

Початкові точки Core залишаються Int32, результати — Float32. num_points фіксується під час побудови графа. Для невикористаної позиції задайте некоректні координати, наприклад (-1,-1), і перевіряйте статус. (0,0) є коректною координатою краю, а не маркером неактивності. Обидві піраміди зображень перебудовуються за кожного виклику; повторне використання попередньої піраміди не передбачається.

Параметри Python​

Python надає ті самі параметри. Створюйте входи через Tensor.from_numpy(..., memory="ev74"), зберігайте контракт порядку входів і будуйте публічний вузол, як у C++.

import pyneat

options = pyneat.TrackKLTOptions()
options.width, options.height = 640, 480
options.num_points = 64
options.win_half, options.max_level, options.max_iters = 7, 2, 20
options.publish_error = True
options.error_threshold = -1.0
options.min_eig_threshold = 0.0
options.require_convergence = False
node = pyneat.nodes.track_klt(options)

Перевірка​

Налаштовані імена портів мають бути непорожніми та унікальними. Некоректні розміри, кількості, вікна, рівні піраміди, розміри дескрипторів і нескінченні або позадіапазонні параметри якості відхиляються. Не обходьте перевірки й не змінюйте лише тип тензора для перетворення значень.

Запуск тестів коректності​

На DevKit задайте CORE_TEST_DIR як каталог установлених тестів Core або тестів нативного збирання, а потім виконайте:

ctest --test-dir "$CORE_TEST_DIR" \
-R '^(grider_fast|track_descriptor|track_klt)_ev_test$' --output-on-failure

Кожний зареєстрований тест виконує повну матрицю свого ядра. GriderFast перевіряє сітку, відстань і межі FAST; TrackDescriptor — також точну відповідність дескрипторів; TrackKLT — незалежні входи, повторне використання кадрів, перевірку, якість, рух, межі та детектор. Окремі швидкі набори є базовими тестами гістограми, KLT без виявлення та відхилення пакета і не замінюють числову перевірку.

Глибина Metoak (C++)​

nodes::MetoakDepth відновлює наявний API MetoakDepthOptions. Вузол приймає шість іменованих тензорів і разом публікує RGB, глибину та XYZ. Він виконує обчислення EV74, а не захоплення з камери; синтетичні тензори можна використовувати без камери.

На відміну від пакетних вузлів вище, Metoak завжди використовує пакет з одного елемента без початкового виміру пакета. Установіть парні W у межах [8,2048] і H у межах [8,1536]. Збережіть канонічні назви маршрутів і передавайте входи в наведеному порядку.

ТензорТип данихФорма
y_srcUInt8[H,W]
u_src, v_srcUInt8[H/2,W/2]
disp_srcUInt16[H,W]
bf_mm_srcFloat32[1]
proj_srcFloat32[3]
rgb_dstUInt8[H,W,3]
depth_dstUInt16[H,W]
points_dstFloat32[H,W,3]

y_src, u_src і v_src — окремі площини I420. Масштаб диспаратності — 32. Для кожного кадру передавайте додатне скінченне bf_mm_src (база × фокусна відстань, mm) та proj_src = {fx_fy, cx, cy}. fx_fy має бути додатним, а всі три значення — скінченними. Калібрування можна змінювати між кадрами.

Глибина округлюється до mm з насиченням до межі UInt16; XYZ використовує неокруглену глибину в m. Нульова диспаратність дає нульову глибину та NaN у XYZ. Усі три виходи доступні, хоча основний опис виходу відповідає глибині.

MetoakDepthOptions depth;
depth.width = 640;
depth.height = 360;
graph.add(nodes::MetoakDepth(depth));

Наявні поля debug, num_buffers і element_name залишаються доступними. num_buffers = 0 використовує типову місткість графа; додатне значення задає виконавчу місткість цього етапу. Відновлено публічний API C++; фабрика Metoak для Python не додається.