Strumienie wyjściowe, przycinanie i powiększanie

Strumienie wyjściowe

W przypadku wszystkich rozdzielczości i formatów wyjściowych aparat działa wyłącznie na podstawie potoku opartego na ANativeWindow. Możesz skonfigurować wiele strumieni jednocześnie, aby wysyłać pojedynczą ramkę do wielu celów, takich jak GPU, koder wideo, RenderScript lub bufor widoczny w aplikacji (bufory RAW Bayera, przetworzone bufory YUV lub bufory z kodowaniem JPEG).

W celu optymalizacji te strumienie wyjściowe muszą zostać skonfigurowane z wyprzedzeniem, a ich liczba jest ograniczona. Umożliwia to wstępną alokację buforów pamięci i konfigurację sprzętu kamery, dzięki czemu podczas przesyłania żądań z wieloma lub różnymi ścieżkami wyjściowymi nie będzie opóźnień w spełnianiu żądań.

Więcej informacji o gwarantowanych kombinacjach danych wyjściowych strumienia, które zależą od obsługiwanego poziomu sprzętu, znajdziesz w artykule createCaptureSession().

Przycinanie

Przycinanie pełnego zbioru pikseli (w przypadku cyfrowego powiększenia i innych zastosowań, w których pożądane jest mniejsze pole widzenia) jest przekazywane za pomocą ustawienia ANDROID_SCALER_CROP_REGION. Jest to ustawienie na potrzeby poszczególnych żądań i może się zmieniać w zależności od żądania. Jest to kluczowe ustawienie do płynnego stosowania cyfrowego powiększenia.

Region jest zdefiniowany jako prostokąt (x, y, szerokość, wysokość), gdzie (x, y) opisuje lewy górny róg prostokąta. Prostokąt jest zdefiniowany w układzie współrzędnych aktywnego tablicznego czujnika, przy czym współrzędne (0,0) odpowiadają lewemu górnemu wierzchołkowi tablicy aktywnych pikseli. Dlatego szerokość i wysokość nie mogą być większe niż wymiary podane w polu informacji statycznej ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY. Minimalna dozwolona szerokość i wysokość są zgłaszane przez HAL za pomocą pola statycznych informacji ANDROID_SCALER_MAX_DIGITAL_ZOOM, które opisuje maksymalny obsługiwany współczynnik powiększenia. Dlatego minimalna szerokość i wysokość regionu przycinania to:

  {width, height} =
   { floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[0] /
       ANDROID_SCALER_MAX_DIGITAL_ZOOM),
     floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[1] /
       ANDROID_SCALER_MAX_DIGITAL_ZOOM) }

Jeśli region przycinania musi spełniać określone wymagania (np. musi zaczynać się na parzystych współrzędnych, a jego szerokość/wysokość musi być parzysta), HAL musi wykonać niezbędne zaokrąglenie i zapisać ostateczny region przycinania użyty w metadanych wyniku wyjściowego. Podobnie, jeśli HAL implementuje stabilizację wideo, musi dostosować obszar przycinania wyniku, aby opisać obszar faktycznie uwzględniony w wyjściu po zastosowaniu stabilizacji wideo. Ogólnie rzecz biorąc, aplikacja korzystająca z kamery musi mieć możliwość określenia pola widzenia na podstawie regionu przycięcia, wymiarów czujnika obrazu i ogniskowej obiektywu.

Ponieważ region przycinania jest stosowany we wszystkich strumieniach, które mogą mieć inne proporcje niż region przycinania, dokładny obszar czujnika używany w przypadku każdego strumienia może być mniejszy niż region przycinania. Każdy strumień powinien zachowywać kwadratowe piksele i stosunek proporcji, przy minimalnym przycięciu zdefiniowanego obszaru. Jeśli format obrazu strumienia jest szerszy niż obszar przycinania, strumień powinien zostać przycięty w pionie, a jeśli format obrazu strumienia jest węższy niż obszar przycinania, strumień powinien zostać przycięty w poziomie.

W każdym przypadku przycięty strumień musi być wyśrodkowany w całym obszarze przycięcia, a każdy strumień jest przycięty tylko w poziomie lub w pionie w stosunku do pełnego obszaru przycięcia, nigdy w obu kierunkach.

Jeśli na przykład zdefiniujesz 2 strumy: 640 x 480 (format obrazu 4:3) i 1280 x 720 (format obrazu 16:9), poniżej znajdziesz oczekiwane regiony wyjściowe dla każdego strumienia w przypadku kilku przykładowych regionów przycięcia na hipotetycznym czujniku 3 MP (macierz 2000 x 1500 pikseli).

Region przycięcia: (500, 375, 1000, 750) (format obrazu 4:3)
Przycięty strumień 640 x 480: (500, 375, 1000, 750) (równy regionowi przycięcia)
Przycięty strumień 1280 x 720: (500, 469, 1000, 562)

crop-region-43-ratio

Rysunek 1. Format obrazu 4:3

Region przycięcia: (500, 375, 1333, 750) (format obrazu 16:9)
Przycięty obraz strumienia 640 x 480: (666, 375, 1000, 750)
Przycięty obraz strumienia 1280 x 720: (500, 375, 1333, 750) (równy regionowi przycięcia)

crop-region-169-ratio

Rysunek 2. Współczynnik proporcji 16:9

Region przycięcia: (500, 375, 750, 750) (format obrazu 1:1)
640 x 480: (500, 469, 750, 562)
1280 x 720: (500, 543, 750, 414)

crop-region-11-ratio

Rysunek 3. Format obrazu 1:1

Ostatni przykład: transmisja w formacie 1024 x 1024 w formacie kwadratowym zamiast 480p:
Region przycinania: (500, 375, 1000, 750) (format obrazu 4:3)
Przycięty obraz transmisji 1024 x 1024: (625, 375, 750, 750)
Przycięty obraz transmisji 1280 x 720: (500, 469, 1000, 562)

crop-region-43-square-ratio

Rysunek 4. Format obrazu 4:3, kwadrat

Przetwarzanie ponownie

Dodatkowa obsługa plików z obrazami w formacie RAW jest zapewniana przez przetwarzanie danych Bayera w formacie RAW. Dzięki temu system przetwarzania aparatu może przetworzyć wcześniej przechwycony bufor RAW i metadane (cały wcześniej nagrany obraz) w celu wygenerowania nowego renderowanego wyjścia YUV lub JPEG.

Zoom

Na urządzeniach z Androidem 11 lub nowszym aplikacja może używać powiększenia aparatu (cyfrowego i optycznego) za pomocą ustawienia ANDROID_CONTROL_ZOOM_RATIO.

Współczynnik powiększenia jest zdefiniowany jako współczynnik zmiennoprzecinkowy. Zamiast ANDROID_SCALER_CROP_REGION do przycinania i powiększania, aplikacja może używać ANDROID_CONTROL_ZOOM_RATIO do kontrolowania poziomu powiększenia oraz ANDROID_SCALER_CROP_REGION do przycinania poziomego i pionowy, aby uzyskać proporcje inne niż te z wbudowanego czujnika aparatu.

System z wieloma kamerami może zawierać więcej niż 1 obiektyw o różnych ogniskowych, a użytkownik może używać zoomu optycznego, przełączając się między obiektywami. Korzystanie z tabeli ANDROID_CONTROL_ZOOM_RATIO ma zalety w tych sytuacjach:

  • Zbliżanie z obiektywu szerokokątnego na teleobiektyw: współczynnik zmiennoprzecinkowy zapewnia większą precyzję w porównaniu z wartościami całkowitymi ANDROID_SCALER_CROP_REGION.
  • Zmniejszanie zoomu z obiektywu szerokokątnego na ultraszerokokątny: ANDROID_CONTROL_ZOOM_RATIO obsługuje zmniejszanie zoomu (<1.0f), podczas gdy ANDROID_SCALER_CROP_REGION tego nie robi.

Poniżej przedstawiamy kilka scenariuszy z różnymi współczynnikami powiększenia, regionami przycinania i strumieniami wyjściowymi, korzystając z tej samej hipotetycznej kamery zdefiniowanej w poprzedniej sekcji.

Współczynnik powiększenia: 2,0; 1/4 oryginalnego pola widzenia
Przycięty obszar: (0, 0, 2000, 1500) (format obrazu 4:3)
Przycięty obszar strumienia 640 x 480: (0, 0, 2000, 1500) (równy obszarowi przycięcia)
Przycięty obszar strumienia 1280 x 720: (0, 187, 2000, 1125)

zoom-ratio-2-crop-43

Rysunek 5. Powiększenie 2,0, format obrazu 4:3

Współczynnik powiększenia: 2,0; 1/4 oryginalnego pola widzenia
Obszar przycinania: (0, 187, 2000, 1125) (format 16:9)
Przycięty strumień 640 x 480: (250, 187, 1500, 1125) (format pillarbox)
Przycięty strumień 1280 x 720: (0, 187, 2000, 1125) (równy obszarowi przycinania)

zoom-ratio-2-crop-169

Rysunek 6. Zoom 2,0, format obrazu 16:9

Współczynnik zoomu: 0,5; 4 x oryginalne pole widzenia (przełączenie z obiektywu szerokokątnego na ultraszerokokątnego)
Przycięty obszar: (250, 0, 1500, 1500) (format obrazu 1:1)
Przycięty obszar strumienia 640 x 480: (250, 187, 1500, 1125) (format obrazu letterbox)
Przycięty obszar strumienia 1280 x 720: (250, 328, 1500, 844) (format obrazu letterbox)

images/zoom-ratio-0.5-crop-11

Rysunek 7. Powiększenie 0,5, format obrazu 1:1

Jak widać na powyższych wykresach, system współrzędnych regionu przycięcia zmienia się na rzeczywiste pole widzenia po przybliżeniu i jest reprezentowane przez prostokąt o tych wymiarach: (0, 0, activeArrayWith, activeArrayHeight). To samo dotyczy regionów AE/AWB/AF oraz twarzy. Ta zmiana systemu współrzędnych nie dotyczy rejestrowania w formacie RAW ani powiązanych z nim metadanych, takich jak intrinsicCalibration i lensShadingMap.

W tym samym hipotetycznym przykładzie, zakładając, że strumień wyjściowy 1 (640 x 480) jest strumieniem wizjer, powiększenie 2,0x można uzyskać na jeden z tych 2 sposobów:

  • zoomRatio = 2.0, scaler.cropRegion = (0, 0, 2000, 1500)
  • zoomRatio = 1.0 (wartość domyślna), scaler.cropRegion = (500, 375, 1000, 750)

Aby aplikacja ustawiła android.control.aeRegions na lewy górny ćwiartkę pola widzenia wizjera, ustaw android.control.aeRegions na (0, 0, 1000, 750), a android.control.zoomRatio na 2.0. Aplikacja może też ustawić android.control.aeRegions na region odpowiadający wartości (500, 375, 1000, 750) w przypadku android.control.zoomRatio1.0.