feat: add RELLIS dataset compatibility smoke
This commit is contained in:
@@ -8,12 +8,15 @@ import {
|
||||
import {
|
||||
fetchDatasetGatewayCatalog,
|
||||
type DatasetGatewayCatalog,
|
||||
type DatasetSource,
|
||||
type DatasetSourceAdmissionStatus,
|
||||
} from "../core/lidar/datasetGateway";
|
||||
import {
|
||||
fetchPolygonRunCatalog,
|
||||
type PolygonRunCatalog,
|
||||
} from "../core/polygon/runArchive";
|
||||
import { GooseDatasetReview } from "./GooseDatasetReview";
|
||||
import { RellisDatasetReview } from "./RellisDatasetReview";
|
||||
|
||||
const representationLabels: Record<string, string> = {
|
||||
"native-scan": "Исходный скан",
|
||||
@@ -27,15 +30,17 @@ function errorMessage(error: unknown): string {
|
||||
: "Каталог датасетов недоступен.";
|
||||
}
|
||||
|
||||
function admissionLabel(status: DatasetGatewayCatalog["source"]["admissionStatus"]) {
|
||||
const labels: Record<typeof status, string> = {
|
||||
function admissionLabel(status: DatasetSourceAdmissionStatus): string {
|
||||
const labels: Record<DatasetSourceAdmissionStatus, string> = {
|
||||
"blocked-storage-policy": "Worker не настроен",
|
||||
"ready-for-download": "Готов к загрузке",
|
||||
"ready-for-smoke": "Готов к smoke",
|
||||
downloading: "Загружается",
|
||||
downloaded: "Загружен",
|
||||
verifying: "Проверяется",
|
||||
verified: "Проверен",
|
||||
"frame-ready": "Первый кадр готов",
|
||||
"frame-ready": "Dataset готов",
|
||||
"smoke-ready": "Smoke готов",
|
||||
};
|
||||
return labels[status];
|
||||
}
|
||||
@@ -55,12 +60,42 @@ function isGooseQualificationRun(
|
||||
&& item.scenarioGeneration.startsWith("goose-3d");
|
||||
}
|
||||
|
||||
function sourceReady(source: DatasetSource): boolean {
|
||||
return source.admissionStatus === "frame-ready"
|
||||
|| source.admissionStatus === "smoke-ready";
|
||||
}
|
||||
|
||||
function sourceDescription(source: DatasetSource): string {
|
||||
if (source.sourceKind === "goose") {
|
||||
return "Восемь фрагментов и 961 разреженный размеченный оборот VLS-128. Здесь уже опубликовано покадровое сравнение текущего ground baseline и Patchwork++.";
|
||||
}
|
||||
return "Независимый off-road источник с Ouster OS1 64. Сейчас открыт официальный frame 000104 для проверки reader, осей, ontology и ground-policy; полный benchmark ещё не выполнялся.";
|
||||
}
|
||||
|
||||
function sourceFooter(source: DatasetSource, storageReady: boolean): string {
|
||||
if (source.admissionStatus === "frame-ready") {
|
||||
return "Native scans и разметка приняты. Можно открыть фрагменты и результаты алгоритмов.";
|
||||
}
|
||||
if (source.admissionStatus === "smoke-ready") {
|
||||
return "Официальный пример совместим. Можно проверить scan, классы и ground mapping.";
|
||||
}
|
||||
if (source.admissionStatus === "downloading") {
|
||||
return "Архив остаётся на D worker; после загрузки проверяются digest, лицензия и point-label alignment.";
|
||||
}
|
||||
if (!storageReady) {
|
||||
return "Сначала нужен допущенный Dataset Root на диске D worker.";
|
||||
}
|
||||
return source.sourceKind === "rellis"
|
||||
? "Следующий шаг: пропустить официальный 24 МБ example через smoke admission."
|
||||
: "Следующий шаг: загрузить validation archive на worker и проверить hash/license.";
|
||||
}
|
||||
|
||||
export function DatasetGatewayWorkspace() {
|
||||
const [catalog, setCatalog] = useState<DatasetGatewayCatalog | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [reloadGeneration, setReloadGeneration] = useState(0);
|
||||
const [previewOpen, setPreviewOpen] = useState(false);
|
||||
const [openSourceId, setOpenSourceId] = useState<string | null>(null);
|
||||
const [runCatalog, setRunCatalog] = useState<PolygonRunCatalog | null>(null);
|
||||
const [selectedRunId, setSelectedRunId] = useState<string | null>(null);
|
||||
const [runError, setRunError] = useState<string | null>(null);
|
||||
@@ -85,7 +120,9 @@ export function DatasetGatewayWorkspace() {
|
||||
}, [reloadGeneration]);
|
||||
|
||||
useEffect(() => {
|
||||
if (catalog?.source.admissionStatus !== "downloading") return;
|
||||
if (!catalog?.sources.some((source) => source.admissionStatus === "downloading")) {
|
||||
return;
|
||||
}
|
||||
const timer = window.setTimeout(
|
||||
() => setReloadGeneration((value) => value + 1),
|
||||
5_000,
|
||||
@@ -113,10 +150,10 @@ export function DatasetGatewayWorkspace() {
|
||||
return () => controller.abort();
|
||||
}, []);
|
||||
|
||||
const downloadProgress = catalog?.source.archive
|
||||
? catalog.source.archive.bytesTransferred / catalog.source.archive.totalBytes
|
||||
: null;
|
||||
const gooseRuns = runCatalog?.items.filter(isGooseQualificationRun) ?? [];
|
||||
const openSource = catalog?.sources.find(
|
||||
(source) => source.sourceId === openSourceId,
|
||||
) ?? null;
|
||||
|
||||
return (
|
||||
<div className="standard-workspace dataset-workspace">
|
||||
@@ -125,17 +162,17 @@ export function DatasetGatewayWorkspace() {
|
||||
<span className="section-eyebrow">ЗАЧЕМ ЭТО НУЖНО</span>
|
||||
<h2>Независимая проверка алгоритмов</h2>
|
||||
<p>
|
||||
Датасет содержит известные размеченные данные. Мы показываем
|
||||
конкретный фрагмент, результаты каждого алгоритма и ошибки
|
||||
относительно разметки. Он не подмешивается в диагностику реального
|
||||
сенсора и не заменяет closed-loop симуляцию.
|
||||
Каждый источник остаётся отдельным: собственные sensor domain,
|
||||
разметка, лицензия и результаты. Совпадение результата на GOOSE и
|
||||
RELLIS снижает риск подгонки под один датасет, но не заменяет replay
|
||||
реального сенсора и closed-loop симуляцию.
|
||||
</p>
|
||||
</div>
|
||||
<ol aria-label="Как использовать датасет">
|
||||
<li><span>01</span>Выбрать фрагмент</li>
|
||||
<li><span>02</span>Посмотреть сканы</li>
|
||||
<li><span>01</span>Выбрать источник</li>
|
||||
<li><span>02</span>Проверить scan и labels</li>
|
||||
<li><span>03</span>Сравнить алгоритмы</li>
|
||||
<li><span>04</span>Проверить риски</li>
|
||||
<li><span>04</span>Проверить переносимость</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
@@ -171,80 +208,91 @@ export function DatasetGatewayWorkspace() {
|
||||
</StatusBadge>
|
||||
</header>
|
||||
|
||||
<article className="dataset-entry">
|
||||
<div className="dataset-entry__identity">
|
||||
<span className="dataset-entry__mark">G</span>
|
||||
<div>
|
||||
<span>PUBLIC · OFF-ROAD · LABELED</span>
|
||||
<h3>{catalog.source.displayName}</h3>
|
||||
<p>
|
||||
Validation split: восемь фрагментов исходных записей и 961
|
||||
разреженный размеченный оборот VLS-128. Это коллекция native
|
||||
scans для perception, а не непрерывное видео или траектория
|
||||
машины.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<dl>
|
||||
<div>
|
||||
<dt>Состояние</dt>
|
||||
<dd>{admissionLabel(catalog.source.admissionStatus)}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Validation</dt>
|
||||
<dd>{catalog.source.validationArchiveGb} ГБ</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Группы</dt>
|
||||
<dd>{catalog.source.superclasses.length} superclass</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Лицензия</dt>
|
||||
<dd>{catalog.source.license}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{catalog.source.admissionStatus === "downloading"
|
||||
&& catalog.source.archive
|
||||
&& downloadProgress !== null ? (
|
||||
<div className="dataset-download" aria-label="Загрузка GOOSE validation">
|
||||
<span style={{ width: `${downloadProgress * 100}%` }} />
|
||||
<p>
|
||||
{formatBytes(catalog.source.archive.bytesTransferred)}
|
||||
{" из "}
|
||||
{formatBytes(catalog.source.archive.totalBytes)}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
<footer>
|
||||
<p>
|
||||
{catalog.source.admissionStatus === "frame-ready"
|
||||
? "Native scan и разметка прошли admission. Можно открыть независимый ground truth."
|
||||
: catalog.source.admissionStatus === "downloading"
|
||||
? "Архив остаётся на D worker. После загрузки проверим ZIP, лицензию, digest и point-label alignment."
|
||||
: catalog.storage.admitted
|
||||
? "Следующий шаг: загрузить validation archive на worker и проверить hash/license."
|
||||
: "Сначала нужно допустить Dataset Root на диске D worker. Сейчас открывать нечего."}
|
||||
</p>
|
||||
<div>
|
||||
<Button
|
||||
size="compact"
|
||||
variant="secondary"
|
||||
disabled={catalog.source.admissionStatus !== "frame-ready"}
|
||||
title={
|
||||
catalog.source.admissionStatus === "frame-ready"
|
||||
? "Открыть фрагменты, сканы и результаты анализа"
|
||||
: "Размеченные сканы ещё не импортированы"
|
||||
}
|
||||
onClick={() => setPreviewOpen((value) => !value)}
|
||||
<div className="dataset-library__entries">
|
||||
{catalog.sources.map((source) => {
|
||||
const downloadProgress = source.archive
|
||||
? source.archive.bytesTransferred / source.archive.totalBytes
|
||||
: null;
|
||||
const opened = source.sourceId === openSourceId;
|
||||
return (
|
||||
<article
|
||||
className="dataset-entry"
|
||||
data-source={source.sourceKind}
|
||||
key={source.sourceId}
|
||||
>
|
||||
{previewOpen ? "Закрыть датасет" : "Открыть датасет"}
|
||||
</Button>
|
||||
</div>
|
||||
</footer>
|
||||
</article>
|
||||
<div className="dataset-entry__identity">
|
||||
<span className="dataset-entry__mark">
|
||||
{source.sourceKind === "goose" ? "G" : "R"}
|
||||
</span>
|
||||
<div>
|
||||
<span>
|
||||
PUBLIC · OFF-ROAD · LABELED
|
||||
{source.sourceKind === "rellis" ? " · RESEARCH" : ""}
|
||||
</span>
|
||||
<h3>{source.displayName}</h3>
|
||||
<p>{sourceDescription(source)}</p>
|
||||
</div>
|
||||
</div>
|
||||
<dl>
|
||||
<div>
|
||||
<dt>Состояние</dt>
|
||||
<dd>{admissionLabel(source.admissionStatus)}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Сканер</dt>
|
||||
<dd>{source.sensor}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Размеченных сканов</dt>
|
||||
<dd>{source.annotatedScanCount.toLocaleString("ru-RU")}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Лицензия</dt>
|
||||
<dd>{source.license}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{source.admissionStatus === "downloading"
|
||||
&& source.archive
|
||||
&& downloadProgress !== null ? (
|
||||
<div
|
||||
className="dataset-download"
|
||||
aria-label={`Загрузка ${source.displayName}`}
|
||||
>
|
||||
<span style={{ width: `${downloadProgress * 100}%` }} />
|
||||
<p>
|
||||
{formatBytes(source.archive.bytesTransferred)}
|
||||
{" из "}
|
||||
{formatBytes(source.archive.totalBytes)}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
<footer>
|
||||
<p>{sourceFooter(source, catalog.storage.admitted)}</p>
|
||||
<div>
|
||||
<Button
|
||||
size="compact"
|
||||
variant="secondary"
|
||||
disabled={!sourceReady(source)}
|
||||
title={
|
||||
sourceReady(source)
|
||||
? "Открыть содержимое источника"
|
||||
: "Совместимый preview ещё не опубликован"
|
||||
}
|
||||
onClick={() => setOpenSourceId(
|
||||
opened ? null : source.sourceId,
|
||||
)}
|
||||
>
|
||||
{opened ? "Закрыть датасет" : "Открыть датасет"}
|
||||
</Button>
|
||||
</div>
|
||||
</footer>
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</GlassSurface>
|
||||
|
||||
{previewOpen && selectedRunId ? (
|
||||
{openSource?.sourceKind === "goose" && selectedRunId ? (
|
||||
<>
|
||||
{gooseRuns.length > 1 ? (
|
||||
<div className="dataset-result-select">
|
||||
@@ -267,12 +315,14 @@ export function DatasetGatewayWorkspace() {
|
||||
) : null}
|
||||
<GooseDatasetReview runId={selectedRunId} />
|
||||
</>
|
||||
) : previewOpen ? (
|
||||
) : openSource?.sourceKind === "goose" ? (
|
||||
<section className="polygon-review-unavailable">
|
||||
<StatusBadge tone="warning">Review недоступен</StatusBadge>
|
||||
<h3>Датасет принят, но результаты анализа не опубликованы</h3>
|
||||
<h3>GOOSE принят, но анализ не опубликован</h3>
|
||||
<p>{runError ?? "Нет совместимой версии покадрового анализа."}</p>
|
||||
</section>
|
||||
) : openSource?.sourceKind === "rellis" ? (
|
||||
<RellisDatasetReview />
|
||||
) : null}
|
||||
|
||||
<details className="dataset-contract">
|
||||
|
||||
@@ -24,6 +24,7 @@ export interface LidarGroundPointCloudFrame {
|
||||
disagreement: number[];
|
||||
candidateDisagreement?: number[];
|
||||
groundTruthGround?: number[];
|
||||
evaluationMask?: number[];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,13 +88,18 @@ function frameColors(
|
||||
);
|
||||
} else if (mode === "ground-truth") {
|
||||
const groundTruth = frame.masks.groundTruthGround?.[index] === 1;
|
||||
setRgb(
|
||||
colors,
|
||||
offset,
|
||||
groundTruth ? 0.76 : 0.29,
|
||||
groundTruth ? 0.86 : 0.33,
|
||||
groundTruth ? 0.52 : 0.36,
|
||||
);
|
||||
const evaluated = frame.masks.evaluationMask?.[index] !== 0;
|
||||
if (!evaluated) {
|
||||
setRgb(colors, offset, 0.86, 0.61, 0.24);
|
||||
} else {
|
||||
setRgb(
|
||||
colors,
|
||||
offset,
|
||||
groundTruth ? 0.76 : 0.29,
|
||||
groundTruth ? 0.86 : 0.33,
|
||||
groundTruth ? 0.52 : 0.36,
|
||||
);
|
||||
}
|
||||
} else if (mode === "current") {
|
||||
setRgb(
|
||||
colors,
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { StatusBadge } from "@nodedc/ui-react";
|
||||
|
||||
import {
|
||||
fetchDatasetNativeScanPreview,
|
||||
type DatasetNativeScanPreview,
|
||||
} from "../core/lidar/datasetGateway";
|
||||
import {
|
||||
LidarGroundPointCloud,
|
||||
type LidarGroundViewMode,
|
||||
} from "./LidarGroundPointCloud";
|
||||
|
||||
const modes: ReadonlyArray<[LidarGroundViewMode, string]> = [
|
||||
["intensity", "Исходный скан"],
|
||||
["semantic", "Классы RELLIS"],
|
||||
["ground-truth", "Ground target"],
|
||||
];
|
||||
|
||||
function formatPercent(value: number): string {
|
||||
return new Intl.NumberFormat("ru-RU", {
|
||||
style: "percent",
|
||||
maximumFractionDigits: 1,
|
||||
}).format(value);
|
||||
}
|
||||
|
||||
function errorMessage(error: unknown): string {
|
||||
return error instanceof Error && error.message.trim()
|
||||
? error.message
|
||||
: "Официальный пример RELLIS недоступен.";
|
||||
}
|
||||
|
||||
function modeExplanation(mode: LidarGroundViewMode): string {
|
||||
if (mode === "semantic") {
|
||||
return "Цвета из закреплённой официальной ontology RELLIS-3D.";
|
||||
}
|
||||
if (mode === "ground-truth") {
|
||||
return "Зелёный — ground, серый — non-ground, янтарный — ignore.";
|
||||
}
|
||||
return "Один исходный оборот Ouster OS1 64; цвет — нормализованная remission.";
|
||||
}
|
||||
|
||||
export function RellisDatasetReview() {
|
||||
const [preview, setPreview] = useState<DatasetNativeScanPreview | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [mode, setMode] = useState<LidarGroundViewMode>("semantic");
|
||||
|
||||
useEffect(() => {
|
||||
const controller = new AbortController();
|
||||
setError(null);
|
||||
void fetchDatasetNativeScanPreview({
|
||||
sourceId: "rellis-3d/v1.1",
|
||||
signal: controller.signal,
|
||||
})
|
||||
.then((value) => {
|
||||
if (!controller.signal.aborted) setPreview(value);
|
||||
})
|
||||
.catch((loadError: unknown) => {
|
||||
if (!controller.signal.aborted) setError(errorMessage(loadError));
|
||||
});
|
||||
return () => controller.abort();
|
||||
}, []);
|
||||
|
||||
const scene = useMemo(() => {
|
||||
if (!preview) return null;
|
||||
const empty = Array.from({ length: preview.pointCount }, () => 0);
|
||||
return {
|
||||
pointCount: preview.pointCount,
|
||||
pointsXyzM: preview.pointsXyzM,
|
||||
intensity0To255: preview.remission0To255,
|
||||
semanticRgb0To255: preview.semanticRgb0To255,
|
||||
masks: {
|
||||
currentGround: empty,
|
||||
currentAssigned: preview.evaluationMask,
|
||||
candidateGround: empty,
|
||||
candidateAssigned: preview.evaluationMask,
|
||||
disagreement: empty,
|
||||
groundTruthGround: preview.groundTruthGround,
|
||||
evaluationMask: preview.evaluationMask,
|
||||
},
|
||||
};
|
||||
}, [preview]);
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<section className="polygon-review-unavailable">
|
||||
<StatusBadge tone="danger">Smoke preview недоступен</StatusBadge>
|
||||
<h3>RELLIS-3D не открыт</h3>
|
||||
<p>{error}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
if (!preview || !scene) {
|
||||
return (
|
||||
<section className="polygon-review-unavailable">
|
||||
<StatusBadge tone="accent">Проверяем пример</StatusBadge>
|
||||
<h3>Открываем официальный RELLIS scan</h3>
|
||||
<p>Исходные dataset bytes не переносятся в браузер.</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
const evaluatedPoints = preview.evaluationMask.reduce(
|
||||
(total, value) => total + value,
|
||||
0,
|
||||
);
|
||||
const groundPoints = preview.groundTruthGround.reduce(
|
||||
(total, value, index) => total + value * (preview.evaluationMask[index] ?? 0),
|
||||
0,
|
||||
);
|
||||
const groundClasses = preview.classes.filter(
|
||||
(item) => item.groundTarget === "ground",
|
||||
);
|
||||
const nonGroundClasses = preview.classes.filter(
|
||||
(item) => item.groundTarget === "non-ground",
|
||||
);
|
||||
const ignoredClasses = preview.classes.filter(
|
||||
(item) => item.groundTarget === "ignore",
|
||||
);
|
||||
|
||||
return (
|
||||
<section
|
||||
className="dataset-sequence-review rellis-review"
|
||||
aria-label="Просмотр официального примера RELLIS-3D"
|
||||
>
|
||||
<header className="dataset-sequence-review__truth">
|
||||
<div>
|
||||
<span className="section-eyebrow">RELLIS S0 · COMPATIBILITY SMOKE</span>
|
||||
<h2>Официальный Ouster scan читается без конвертации формата</h2>
|
||||
<p>
|
||||
Frame {preview.frameId}: исходные XYZI и point-wise labels остались
|
||||
выровнены. Это проверка reader, осей, цветов и ground-policy — ещё не
|
||||
сравнение алгоритмов и не основание для навигации.
|
||||
</p>
|
||||
</div>
|
||||
<dl>
|
||||
<div>
|
||||
<dt>Исходных точек</dt>
|
||||
<dd>{preview.sourcePointCount.toLocaleString("ru-RU")}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Browser preview</dt>
|
||||
<dd>{preview.pointCount.toLocaleString("ru-RU")}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Sensor frame</dt>
|
||||
<dd>{preview.coordinateFrame?.frameId ?? "—"}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</header>
|
||||
|
||||
<section className="polygon-review-player">
|
||||
<header className="polygon-review-player__header">
|
||||
<div>
|
||||
<span className="section-eyebrow">OFFICIAL EXAMPLE · FRAME 000104</span>
|
||||
<strong>Ouster OS1 64 · X forward · Y left · Z up</strong>
|
||||
</div>
|
||||
<div className="polygon-review-mode" aria-label="Режим RELLIS preview">
|
||||
{modes.map(([viewMode, label]) => (
|
||||
<button
|
||||
type="button"
|
||||
key={viewMode}
|
||||
data-active={mode === viewMode ? "true" : undefined}
|
||||
onClick={() => setMode(viewMode)}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</header>
|
||||
<div className="polygon-review-stage">
|
||||
<LidarGroundPointCloud
|
||||
frame={scene}
|
||||
mode={mode}
|
||||
coordinateFrame="sensor-fixed"
|
||||
/>
|
||||
<div className="polygon-review-stage__legend">
|
||||
<strong>{modes.find(([viewMode]) => viewMode === mode)?.[1]}</strong>
|
||||
<span>{modeExplanation(mode)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="rellis-review__metrics">
|
||||
<article>
|
||||
<span>Оценимых точек preview</span>
|
||||
<strong>{formatPercent(evaluatedPoints / preview.pointCount)}</strong>
|
||||
<small>ignore не участвует в метриках</small>
|
||||
</article>
|
||||
<article>
|
||||
<span>Ground среди оценимых</span>
|
||||
<strong>
|
||||
{formatPercent(evaluatedPoints ? groundPoints / evaluatedPoints : 0)}
|
||||
</strong>
|
||||
<small>версионная mapping policy v1</small>
|
||||
</article>
|
||||
<article>
|
||||
<span>Классов в этом scan</span>
|
||||
<strong>{preview.classes.length}</strong>
|
||||
<small>из 20 классов ontology</small>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<section className="rellis-review__policy" aria-label="Ground target mapping">
|
||||
<header>
|
||||
<span className="section-eyebrow">GROUND TARGET POLICY V1</span>
|
||||
<h3>Что именно будет оцениваться</h3>
|
||||
<p>
|
||||
Mapping принадлежит Mission Core и версионируется отдельно от
|
||||
ontology датасета. Вода, лужи, void, sky и неопределённый object не
|
||||
засчитываются ни как ground, ни как obstacle.
|
||||
</p>
|
||||
</header>
|
||||
<div>
|
||||
<article>
|
||||
<span>Ground</span>
|
||||
<strong>{groundClasses.map((item) => item.className).join(" · ") || "—"}</strong>
|
||||
</article>
|
||||
<article>
|
||||
<span>Non-ground</span>
|
||||
<strong>
|
||||
{nonGroundClasses.map((item) => item.className).join(" · ") || "—"}
|
||||
</strong>
|
||||
</article>
|
||||
<article>
|
||||
<span>Ignore</span>
|
||||
<strong>{ignoredClasses.map((item) => item.className).join(" · ") || "—"}</strong>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p className="dataset-sequence-review__raw-note">
|
||||
Лицензия RELLIS-3D — CC-BY-NC-SA-3.0: источник годится для независимой
|
||||
исследовательской проверки, но коммерческое использование данных или
|
||||
производных моделей требует отдельного лицензионного решения.
|
||||
</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user