2012-05-27 10 views
17

Chcę wykonać przetwarzanie obrazu z nieprzetworzonym obrazem bez wyświetlania go na ekranie, co oczywiście zmniejsza wydajność.Zestaw SDK systemu Android: uzyskaj nieprzetworzony obraz z kamery podglądu bez wyświetlania go.

Zgodnie z odpowiedziami na ten temat Taking picture from camera without preview nie było możliwe w systemie Android 1.5, ale czy ktoś wie, czy jest to możliwe w systemie Android 4 (poziom API 15)?

+0

Po prostu wypróbowałeś pozorne rozwiązanie SurfaceTexture (metoda 2) na Samsung Galaxy S5. Nie działa po kilku klatkach. Moim rozwiązaniem jest wywołanie metody updateTexImage, ale użycie niepoprawnej nazwy tekstury z poprawnym kontekstem GL. Po wyciszeniu powstałego wyjątku wszystko działa sprawnie. – user3693576

Odpowiedz

41

W systemie Android 4 najprostszą opcją odbierania nieprzetworzonych danych obrazu bez wyświetlania go na ekranie jest użycie połączenia Camera.setPreviewTexture() w celu przekierowania ramek podglądu na GPU.

Można to wykorzystać na dwa sposoby:

  1. Czy rzeczywisty przetwarzania na GPU: Konfigurowanie kontekst OpenGL (OpenGL ES 2 tutorial) i utworzyć SurfaceTexture obiekt w tym kontekście. Następnie przekaż ten obiekt do setPreviewTexture i uruchom podgląd. Następnie w kodzie OpenGL można wywołać metodę SurfaceTexture.updateTexImage, a identyfikator tekstury powiązany z SurfaceTexture zostanie zaktualizowany do najnowszej klatki podglądu z kamery. Możesz także odczytywać dane tekstur RGB do procesora w celu dalszego przetwarzania za pomocą glReadPixels, jeśli chcesz.
  2. Przetwarzanie na procesorze: Możesz po prostu utworzyć obojętny obiekt SurfaceTexture bez ustawionego kontekstu OpenGL. Przekaż dowolną liczbę całkowitą jako identyfikator tekstury i podłącz SurfaceTexture do kamery za pomocą metody setPreviewTexture. Dopóki nie wywołasz funkcji updateTexImage, SurfaceTexture po prostu odrzuci wszystkie dane przekazane do niej przez kamerę. Następnie skonfiguruj wywołania zwrotne podglądu za pomocą setPreviewCallback i użyj tych danych (zazwyczaj w formacie YUV) do przetwarzania procesora. Jest to prawdopodobnie mniej wydajne niż pierwsze, ale nie wymaga znajomości OpenGL.
+0

Czy ktoś napotkał prosty przykład użycia glReadPixels po zwróceniu SurfaceTexture.updateTexImage? – wobbals

+0

Metoda 2 nie działa dla Nexusa 4. – user1914692

+0

@wobbals: Nie można bezpośrednio użyć 'glReadPixels()' wyjścia kamery (ten sam problem co http: // stackoverflow.com/questions/19366660/how-to-save-surfacetexture-as-bitmap/19370209 # 19370209). Najpierw wyślij to do bufora. Kilka wskazówek do przykładów tutaj: http://stackoverflow.com/questions/20710204/android-camera-preview-on-surfacetexture/21104769#21104769 – fadden

1

Ponieważ nie wolno mi komentować. Odnośnie odpowiedzi Eddy'ego. Musisz pracować z tym w NDK, ponieważ używanie interfejsu Java neguje jakiekolwiek korzyści związane z wydajnością. Praca z PixelBufferem jest absolutnie szalona z punktu widzenia wydajności. Konwersję z RGBA888 na YUV również trzeba wykonać w C.

Nie próbuj używać TextureView, ponieważ jest jeszcze gorzej. Będziesz musiał skopiować piksele do bitmapy, a następnie z mapy bitowej do tablicy przed konwersją na YUV. To samo w sobie zajmuje prawie 30% wykorzystania procesora na marki Nexus 7 2013.

Najbardziej efektywnym sposobem jest rozmowa z Camera.h bezpośrednio i obejście wszystkich interfejsów API Androida. Możesz stworzyć swój własny bufor i przechwycić dane YUV, zanim przejdzie on nigdzie indziej.

+1

Podczas gdy wywołania zwrotne podglądu nie są tak wydajne, jak bym chciał, nie są straszny. Otrzymujesz bajt [] danych YUV na ramkę, które można przesłać przez JNI do kodu przetwarzania natywnego z zerową liczbą kopii. Brak konwersji do bitmapy lub czegokolwiek innego. Używanie Camera.h bezpośrednio jest złym pomysłem, ponieważ ten interfejs jest prywatny i może ulec zmianie w dowolnym momencie. –

+0

Podgląd wywołań zwrotnych działa tylko z powierzchnią. Pytanie brzmiało, jak to zrobić, nie wyświetlając go wcale. Jedynym sposobem na zrobienie tego bez powierzchni jest użycie PixelBuffer. Standardowe wywołanie zwrotne w/Surface jest lepsze z punktu widzenia wydajności. Każde wywołanie zwrotne ma dwa cykle. Aparat kopiuje do wewnętrznego bufora; następnie do bufora powierzchni RGBA. Drugi cykl kopiuje wewnętrzny bufor do bufora wywołania zwrotnego. – bond

+0

Naprawdę nie jestem pewien, co masz na myśli przez PixelBuffer - nie ma interfejsu API o tej nazwie Jestem świadomy w Androidzie (masz na myśli Bitmap?). Callback podglądu działa dobrze z setPreviewTexture() oprócz setPreviewDisplay(), a ten pierwszy nie wymaga podglądu rysunku do dowolnego elementu interfejsu użytkownika. Kopie w warstwach natywnych i JNI są oporem wydajnościowym, zgadzam się, dlatego też zasugerowałem podejście do przetwarzania GPU, które nie ma narzutów. –

1

Wyświetlenie podglądu na ekranie nie ma konsekwencji dla wydajności. Na wszystkich urządzeniach, które spotkałem, wyjście kamery jest "podłączone" do powierzchni lub tekstury bez udziału procesora, wszystkie konwersje kolorów i skalowanie są obsługiwane przez dedykowany sprzęt.

Być może istnieją inne powody do "ukrycia" podglądu, ale należy pamiętać, że celem interfejsu API było przede wszystkim upewnienie się, że użytkownik końcowy widzi wszystko, co dociera z kamery do aplikacji, ze względu na prywatność i bezpieczeństwo .

Powiązane problemy