2012-10-31 14 views
8

W mojej aplikacji otrzymuję ramkę głębi podobną do ramki głębi pobranej z próbki głębokości. Czego nie rozumiem, to dlaczego w obrazie występują dyskretne poziomy? Nie wiem, co nazywam tymi nagłymi zmianami wartości głębokości. Najwyraźniej moja połowa prawej ręki jest cała czarna, a moja lewa ręka wydaje się podzielona na 3 takie poziomy. Co to jest i jak mogę to usunąć?Obraz głębokości matrycy

Kinect Depth Basics Sample http://i46.tinypic.com/2hwekxd.jpg

Kiedy uruchomić aplikację KinectExplorer Sample uzyskać głębię następująco. To jest obraz głębi, który chcę wygenerować z surowych danych głębi.

Kinect Explorer http://i50.tinypic.com/2rwx1z5.jpg

Używam Microsoft Kinect SDK (v1.6) NuiApi wraz z OpenCV. Mam następujący kod:

BYTE *pBuffer = (BYTE*)depthLockedRect.pBits; //pointer to data having 8-bit jump 
USHORT *depthBuffer = (USHORT*) pBuffer; //pointer to data having 16-bit jump 
int cn = 4; 
this->depthFinal = cv::Mat::zeros(depthHeight,depthWidth,CV_8UC4); //8bit 4 channel 
for(int i=0;i<this->depthFinal.rows;i++){ 
    for(int j=0;j<this->depthFinal.cols;j++){ 
     USHORT realdepth = ((*depthBuffer)&0x0fff); //Taking 12LSBs for depth 
     BYTE intensity = (BYTE)((255*realdepth)/0x0fff); //Scaling to 255 scale grayscale 
     this->depthFinal.data[i*this->depthFinal.cols*cn + j*cn + 0] = intensity; 
     this->depthFinal.data[i*this->depthFinal.cols*cn + j*cn + 1] = intensity; 
     this->depthFinal.data[i*this->depthFinal.cols*cn + j*cn + 2] = intensity; 
     depthBuffer++; 
    } 
} 
+0

Proszę dokładnie sprawdzić swoje zdjęcia, nie są wyświetlane. –

+0

Zmieniono adresy URL obrazów. Sprawdź ponownie. – thinkquester

+0

Co to jest '' cn'' i czy naprawdę musi to być '' 4'', a nie '' 3''? Byłoby również podejrzenie, gdzie faktycznie wydrukujesz obraz. – Tim

Odpowiedz

0

Wizualizacja danych głębia obrazu ma dyskretne poziomy, które są zgrubne (od 0 do 255 w przykładzie kodu), ale dane rzeczywista głębokość obrazu są numery od 0 do 2047. Nadal dyskretny, oczywiście, ale nie w tak grubych jednostkach, jak kolory wybrane do ich przedstawienia.

5

Paski, które widzisz, są spowodowane wartościami głębokości wrapping spowodowanymi przez operację %256. Zamiast stosowania operację modulo (%256), który jest przyczyną pasma, aby pokazać się, przemapować wartości głębokości wzdłuż całego zakresu, np:

BYTE intensity = depth == 0 || depth > 4095 ? 0 : 255 - (BYTE)(((float)depth/4095.0f) * 255.0f); 

w przypadku, gdy głębokość max 2048, wymień 4095 z 2047 .

Więcej wskazówek:

  1. Kinect przypuszczalnie zwraca wartość 11bit (0-2047), ale używać tylko 8bit (0-255).
  2. Nowe wersje Kinect wydają się zwracać 12-bitową wartość (0-4096)
  3. w kodzie źródłowym eksploratora Kinect, jest tam plik o nazwie DepthColorizer.cs, w którym większość magii zdaje się dziać. Wierzę, że ten kod sprawia, że ​​wartości głębi są tak gładkie w eksploratorze kinetycznym - ale mogę się mylić.
+0

Jeśli zawinąłeś wartości głębokości, używając mniejszej wartości jako modulo, czy prążki byłyby bardziej oddalone? –

1

Napotkałem ten sam problem podczas pracy nad projektem, który obejmował wizualizację mapy głębokości. Jednak użyłem OpenNI SDK z OpenCV zamiast bibliotek Kinect SDK. Problem był taki sam i dlatego rozwiązanie zadziała tak samo jak dla mnie.

Jak wspomniano w poprzednich odpowiedziach na pytanie, mapa głębokości kinetycznej jest 11-bitowa (0-2047). W przykładach używane są 8-bitowe typy danych.

Co zrobiłem w moim kodu, aby ominąć to było nabyć mapę głębokości do 16-bitowej Mat, a następnie przekształcić go do 8-bitowej uchar Mat używając opcji skalowania w convertTo funkcji dla Mat

najpierw zainicjować Mat do pozyskiwania danych głębokość

Mat depthMat16UC1(XN_VGA_Y_RES, XN_VGA_X_RES, CV_16UC1); 

Tutaj XN_VGA_Y_RES, XN_VGA_X_RES określa rozdzielczość nabytej głębokości mapie.

Kod gdzie mogę zrobić to w następujący sposób:

depthMat16UC1.data = ((uchar*)depthMD.Data()); 
depthMat16UC1.convertTo(depthMat8UC1, CV_8U, 0.05f); 
imshow("Depth Image", depthMat8UC1); 

depthMD to metadane zawierające dane pobierane z czujnika Kinect.

Mam nadzieję, że to pomoże w pewien sposób.

0

Kinometr v2 może mieć głębokość 8 metrów (ale dokładność powyżej 4,5 zmniejsza). Zaczyna się około 0,4 metra. Tak więc należy wyrazić liczbę 8000 dla koloru. Sposobem na to jest użycie kolorów RGB tylko liczb. następnie można potencjalnie przechowywać liczbę jak 255x255x255 i piksel. Lub jeśli miałeś inny format kolorów, to byłby inny. Przechowywanie 8000 w tej liczbie maksymalnej 255x255x255 spowoduje powstanie pewnej ilości R + G + B, co daje efekt pasmowania.

Ale można oczywiście złożyć 8000 lub odjąć liczbę lub usunąć ponad pewną wartość.