Przejdź do głównej zawartości

Jak woksel uzyskuje położenie (x,y,z)

Tablica nie ma zatem położenia. Jak woksel je uzyskuje? W tej sekcji zbudujemy odwzorowanie afiniczne całkowitego indeksu woksela (i, j, k) na fizyczną współrzędną pacjenta (x, y, z) — relację afiniczną, a nie czysto liniową: liniowy składnik kierunku i odstępów wraz z przesunięciem o początek układu — oraz prześledzimy ją na konkretnych liczbach. Gdy potrafisz zapisać to odwzorowanie, porządkowanie przekrojów, zmiana próbkowania i porównywanie CT↔SEG stają się działaniami arytmetycznymi.

Gdzie znajduje się woksel (0,0,0)?

Położenie woksela we współrzędnych pacjenta zależy od trzech poznanych już wielkości geometrycznych: początku układu, odstępów i kierunku. Pierwszy woksel (0,0,0) znajduje się w początku układu. Aby dotrzeć do dowolnego innego woksela, wykonujesz kroki wzdłuż trzech osi; każdy krok jest skalowany odstępem właściwym dla danej osi i zwrócony zgodnie z jej kierunkiem. Złożenie tych kroków daje przekształcenie afiniczne.

Geometria w terminologii DICOM

Jest to trwały punkt odniesienia dla odwzorowania indeksu piksela na współrzędne pacjenta i w przeciwnym kierunku. Opis jest zgodny z modułem Image Plane Module standardu DICOM (PS3.3 C.7.6.2.1.1).

Indeksy pikseli DICOM mają postać (i, j), gdzie:

  • i = indeks kolumny (0 … Columns−1): wzrost i oznacza przemieszczanie się wzdłuż wiersza przesyłanej macierzy obrazu — jest to konwencja poruszania się po macierzy lub obrazie, a nie anatomiczny kierunek w lewo lub w prawo.
  • j = indeks wiersza (0 … Rows−1): wzrost j oznacza przemieszczanie się wzdłuż kolumny przesyłanej macierzy — również jest to konwencja poruszania się, a nie anatomiczny kierunek w górę lub w dół.

Anatomiczny kierunek każdego indeksu określa ImageOrientationPatient, a nie słowa „wiersz” i „kolumna”.

ImageOrientationPatient (0020,0037) = sześć cosinusów kierunkowych:

  • pierwsza trójka [rx, ry, rz] = kierunek wiersza = kierunek wzrostu i;
  • druga trójka [cx, cy, cz] = kierunek kolumny = kierunek wzrostu j.

PixelSpacing (0028,0030) = [row spacing, column spacing]:

  • pierwsza wartość = odstęp między wierszami = odległość między sąsiednimi wierszami = krok wykonywany, gdy indeks wiersza j zwiększa się o 1;
  • druga wartość = odstęp między kolumnami = odległość między sąsiednimi kolumnami = krok wykonywany, gdy indeks kolumny i zwiększa się o 1.

Pułapkę stanowi krzyżowe powiązanie tych elementów (poświęcamy mu następną sekcję): cosinus kierunkowy wiersza łączy się z odstępem między kolumnami i odwrotnie.

Równanie w płaszczyźnie

Dla pojedynczej ramki współrzędną pacjenta odpowiadającą pikselowi (i, j) opisuje równanie:

P(i, j) = P0
+ i · (column spacing) · [rx, ry, rz] # move along a row (i increases)
+ j · (row spacing) · [cx, cy, cz] # move along a column (j increases)

gdzie P0 = ImagePositionPatient (0020,0032) oznacza położenie pierwszego (lewego górnego) piksela tej ramki. Trzecią oś dodaje normalna do przekroju — tym zajmuje się sekcja o porządkowaniu przekrojów.

Przykład liczbowy rozwiązany krok po kroku

Rozważmy prosty osiowy przekrój wyrównany z osiami układu współrzędnych — częsty przypadek — w którym wiersz jest zwrócony wzdłuż +x, a kolumna wzdłuż +y:

ImageOrientationPatient = [1, 0, 0, 0, 1, 0] # row=+x, col=+y
PixelSpacing = [0.8, 0.8] # [row spacing, col spacing] mm
ImagePositionPatient = [-200, -150, 42.0] # P0, LPS mm

Gdzie znajduje się piksel w kolumnie i = 100 i wierszu j = 200?

P(100, 200) = [-200, -150, 42.0]
+ 100 · 0.8 · [1, 0, 0] = [+80, 0, 0]
+ 200 · 0.8 · [0, 1, 0] = [ 0, +160, 0]
-------------------------------
= [-120, +10, 42.0] mm (LPS)

Indeks woksela (i,j)=(100,200) prowadzi krokami po 0,8 mm wzdłuż odpowiednich kierunków od P0 do punktu LPS (-120,10,42.0) mm; pokazano także zależność afiniczną.

Przedstawiony punkt pochodzi z przykładu liczbowego w tej sekcji: od P0 każdy krok i przesuwa się o 0,8 mm wzdłuż kierunku wiersza, a każdy krok j o 0,8 mm wzdłuż kierunku kolumny, zatem (i, j) = (100, 200) prowadzi do punktu (−120, +10, 42.0) mm w LPS.

Zwróć uwagę, że składowa z nie zmieniła się (42.0) — ale wniosek ten dotyczy wyłącznie tego przykładu. Dzieje się tak, ponieważ osiowy przekrój jest wyrównany z osiami: oba cosinusy kierunkowe w płaszczyźnie mają zerowe składowe z. W płaszczyźnie skośnej, czołowej lub strzałkowej wektory kierunkowe w płaszczyźnie mają składowe z, dlatego ruch w obrębie jednego przekroju może zmieniać współrzędną z pacjenta — przechodzenie między przekrojami nie jest jedynym sposobem zmiany z. W tym przykładzie liczbowym trzecią oś obrazu wyznacza geometria między przekrojami, czyli normalna do przekroju (sekcja o porządkowaniu przekrojów).

Wynik można odczytać następująco: „indeks woksela (100, 200) na tym przekroju odpowiada fizycznemu punktowi położonemu 120 mm na prawo od początku układu współrzędnych i 10 mm ku tyłowi, na wysokości 42 mm”. Indeks tablicy stał się położeniem w ciele pacjenta wyrażonym w milimetrach. Na tym właśnie polega jedyne zadanie przekształcenia afinicznego. Każde pytanie „czy ta maska znajduje się we właściwym miejscu?” sprowadza się do zastosowania tego odwzorowania i porównania współrzędnych.

Warto wyraźnie wskazać dwie kontrole zawarte w tym przykładzie. Woksel w początku układu (i = 0, j = 0) to po prostu P0 = [-200, -150, 42.0] — początek układu jest dosłownie położeniem pierwszego piksela. Zwiększenie i o 1 powoduje dodanie 1 · (column spacing) · row direction = 1 · 0.8 · [1,0,0] = [0.8, 0, 0], czyli 0,8 mm wzdłuż +x. Te 0,8 mm jest odstępem między kolumnami. „Odstęp” nie jest zatem abstrakcyjnym polem metadanych — w tym przykładzie rozwiązanym krok po kroku jest odległością między środkami sąsiednich próbek wzdłuż odpowiedniej osi obrazu. Odstęp wyznacza ten krok współrzędnych, lecz nie jest automatycznie fizycznym obszarem tkanki reprezentowanym przez woksel, grubością warstwy, jądrem czułości ani rozdzielczością przestrzenną. Obliczenia wyprowadziły z geometrii krok współrzędnych, a nie uniwersalny fizyczny rozmiar jednego woksela.

Przekształcenie afiniczne jako macierz

Umieść początek układu, odstępy i kierunek w jednej macierzy 4×4 A (we współrzędnych jednorodnych), a odwzorowanie stanie się pojedynczym mnożeniem:

[ x ] [ D·diag(s) | origin ] [ i ]
[ y ] = [ | ] · [ j ]
[ z ] [ | ] [ k ]
[ 1 ] [ 0 0 0 | 1 ] [ 1 ]

gdzie D jest macierzą cosinusów kierunkowych 3×3 (kolumny to kierunki osi), diag(s) jest macierzą diagonalną 3×3, która skaluje każdą oś właściwym dla niej odstępem, a origin jest trójelementową kolumną przesunięcia. W zwykłej postaci trójwymiarowej relacja jest afiniczna — liniowy składnik kierunku i odstępów plus przesunięcie — i dopiero jednorodna reprezentacja 4×4 włącza przesunięcie do jednego mnożenia macierzy. Dokładnie taką macierz funkcja build_affine() w TRACE-CT konstruuje na podstawie IOP/IPP/odstępów i dokładnie te informacje SimpleITK przechowuje wewnętrznie jako GetOrigin()/GetSpacing()/GetDirection().

Co może się nie udać nawet przy prawidłowym przekształceniu afinicznym

  • Wolumeny skośne. Jeśli gantry było pochylone, macierz kierunku nie jest jednostkowa, a osie nie pokrywają się z +x/+y/+z. Stosuj pełną macierz; nie zakładaj, że „osiowy oznacza jednostkowy”.
  • Zmiany początku układu między przekrojami. Każdy przekrój ma własną wartość ImagePositionPatient. Przekształcenie afiniczne w płaszczyźnie jest wspólne dla regularnej serii, lecz P0 różni się między przekrojami — właśnie tę informację sekcja o porządkowaniu przekrojów wykorzystuje do ich uporządkowania.
  • LPS a RAS. W zwykłym obrazowaniu człowieka (BIPED) DICOM i ITK/SimpleITK przechowują współrzędne fizyczne w LPS, natomiast 3D Slicer przechowuje wewnętrzne współrzędne w RAS; przeliczenie na granicy zmienia znaki składowych x i y. Pominięcie tego przeliczenia albo wykonanie go dwukrotnie może odbić lub przemieścić współrzędne. Jest to ryzyko, które należy sprawdzić, a nie gwarancja widocznego odbicia: oprogramowanie odczytujące i zapisujące dane może wykonywać przeliczenie automatycznie.

Po zbudowaniu przekształcenia afinicznego pozostałe zagrożenie nie tkwi w samym odwzorowaniu, lecz w konwencjach, które dostarczają mu danych — w tym, który indeks oznacza co i które odstępy łączą się z którymi kierunkami. Następna sekcja szczegółowo omawia pułapkę wierszy i kolumn: dlaczego NumPy i SimpleITK indeksują ten sam woksel w przeciwnych kolejnościach.

Źródła

  • DICOM PS3.3, Image Plane Module (C.7.6.2) oraz Image Position and Image Orientation (C.7.6.2.1.1, Equation C.7.6.2.1-1) — semantyka indeksów pikseli, ImageOrientationPatient, PixelSpacing, ImagePositionPatient i odwzorowanie piksela na współrzędne pacjenta. (bieżące wydanie)
  • SimpleITK, Fundamental Concepts — początek układu, odstępy, kierunek i odwzorowanie indeksu na punkt fizyczny (GetOrigin()/GetSpacing()/GetDirection()), w tym konwersja tablic NumPy↔SimpleITK i odwrócona kolejność wymiarów. (dokumentacja)
  • Dokumentacja 3D Slicer, Coordinate systems — wewnętrzna konwencja RAS programu Slicer, przeliczenie LPS↔RAS na granicy oraz afiniczne przekształcenie obrazu. (dokumentacja)
  • TRACE-CT, scripts/seg_decode_resample.py, build_affine() — ograniczony dowód implementacyjny projektu dotyczący konstruowania przekształcenia afinicznego z IOP/IPP/odstępów. (commit 7aaf308c)

© 2026 Adrian Tkacz · BioMedical-IT
Oryginalne teksty i ilustracje są udostępniane na licencji Creative Commons Uznanie autorstwa–Użycie niekomercyjne 4.0 Międzynarodowe (CC BY-NC 4.0), o ile nie zaznaczono inaczej. Przy ponownym wykorzystaniu proszę podać Adrian Tkacz / BioMedical-IT jako autora i zamieścić odnośnik do oryginalnego źródła. Materiały osób trzecich zachowują własne prawa i warunki licencyjne.