Элементы управления камерой вручную в Xamarin.iOS
Элементы управления камерой вручную, предоставляемые AVFoundation Framework
в iOS 8, позволяют мобильному приложению полностью контролировать камеру устройства iOS. Этот точный уровень управления можно использовать для создания приложений камеры профессионального уровня и предоставления артистских композиций путем настройки параметров камеры при принятии по-прежнему изображения или видео.
Эти элементы управления также могут быть полезными при разработке научных или промышленных приложений, где результаты менее ориентированы на правильность или красоту изображения, а также ориентированы на выделение некоторых признаков или элементов изображения.
Объекты захвата AVFoundation
Независимо от того, принимает ли видео или все еще изображения с помощью камеры на устройстве iOS, процесс, используемый для записи этих изображений, в значительной степени совпадает. Это верно для приложений, использующих автоматические элементы управления камеры по умолчанию или те, которые используют новые элементы управления ручной камеры:
Входные данные взяты из AVCaptureDeviceInput
AVCaptureSession
объекта в пути AVCaptureConnection
. Результатом является либо вывод в виде по-прежнему изображения, либо в виде видеопотока. Весь процесс управляется с помощью AVCaptureDevice
.
Предоставленные вручную элементы управления
Используя новые API, предоставляемые iOS 8, приложение может контролировать следующие функции камеры:
- Фокус вручную. Благодаря тому, что конечный пользователь может напрямую контролировать фокус, приложение может обеспечить больше контроля над изображением.
- Экспозиция вручную . Предоставляя ручной контроль над экспозицией, приложение может обеспечить больше свободы для пользователей и позволить им достичь стилизованного вида.
- Ручной баланс белого баланса — белый баланс используется для настройки цвета в изображении— часто, чтобы сделать его реалистичным. Различные источники света имеют разные цветовые температуры, а параметры камеры, используемые для захвата изображения, корректируются для компенсации этих различий. Опять же, позволяя пользователю контролировать белый баланс, пользователи могут вносить корректировки, которые не могут быть выполнены автоматически.
iOS 8 предоставляет расширения и улучшения существующих API iOS, чтобы обеспечить этот подробный контроль над процессом захвата изображений.
Требования
Для выполнения описанных в этой статье действий необходимо выполнить следующие действия.
- Xcode 7+ и iOS 8 или более поздних версий — на компьютере разработчика необходимо установить и настроить интерфейсы API Apple Xcode 7 и iOS 8 или более поздних версий.
- Visual Studio для Mac — последняя версия Visual Studio для Mac должна быть установлена и настроена на устройстве пользователя.
- Устройство iOS 8 — устройство iOS под управлением последней версии iOS 8. Функции камеры нельзя протестировать в симуляторе iOS.
Общая настройка записи AV
При записи видео на устройстве iOS существует некоторый общий код установки, который всегда требуется. В этом разделе описана минимальная настройка, необходимая для записи видео с камеры устройства iOS и отображения видео в UIImageView
режиме реального времени.
Делегат буфера выходных данных
Одним из первых вещей будет делегат для мониторинга буфера выходных данных образца и отображения изображения, полученного из буфера UIImageView
в пользовательском интерфейсе приложения.
Следующая подпрограмма будет отслеживать пример буфера и обновлять пользовательский интерфейс:
using System;
using Foundation;
using UIKit;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using AVFoundation;
using CoreVideo;
using CoreMedia;
using CoreGraphics;
namespace ManualCameraControls
{
public class OutputRecorder : AVCaptureVideoDataOutputSampleBufferDelegate
{
#region Computed Properties
public UIImageView DisplayView { get; set; }
#endregion
#region Constructors
public OutputRecorder ()
{
}
#endregion
#region Private Methods
private UIImage GetImageFromSampleBuffer(CMSampleBuffer sampleBuffer) {
// Get a pixel buffer from the sample buffer
using (var pixelBuffer = sampleBuffer.GetImageBuffer () as CVPixelBuffer) {
// Lock the base address
pixelBuffer.Lock (0);
// Prepare to decode buffer
var flags = CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Little;
// Decode buffer - Create a new colorspace
using (var cs = CGColorSpace.CreateDeviceRGB ()) {
// Create new context from buffer
using (var context = new CGBitmapContext (pixelBuffer.BaseAddress,
pixelBuffer.Width,
pixelBuffer.Height,
8,
pixelBuffer.BytesPerRow,
cs,
(CGImageAlphaInfo)flags)) {
// Get the image from the context
using (var cgImage = context.ToImage ()) {
// Unlock and return image
pixelBuffer.Unlock (0);
return UIImage.FromImage (cgImage);
}
}
}
}
}
#endregion
#region Override Methods
public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
{
// Trap all errors
try {
// Grab an image from the buffer
var image = GetImageFromSampleBuffer(sampleBuffer);
// Display the image
if (DisplayView !=null) {
DisplayView.BeginInvokeOnMainThread(() => {
// Set the image
if (DisplayView.Image != null) DisplayView.Image.Dispose();
DisplayView.Image = image;
// Rotate image to the correct display orientation
DisplayView.Transform = CGAffineTransform.MakeRotation((float)Math.PI/2);
});
}
// IMPORTANT: You must release the buffer because AVFoundation has a fixed number
// of buffers and will stop delivering frames if it runs out.
sampleBuffer.Dispose();
}
catch(Exception e) {
// Report error
Console.WriteLine ("Error sampling buffer: {0}", e.Message);
}
}
#endregion
}
}
С помощью этой подпрограммы можно изменить, AppDelegate
чтобы открыть сеанс записи av для записи видеотрансляций.
Создание сеанса записи AV
Сеанс записи AV используется для управления записью видеотрансляций с камеры устройства iOS и требуется для получения видео в приложение iOS. Так как пример ManualCameraControl
приложения использует сеанс записи в нескольких разных местах, он будет настроен в приложении и доступен для AppDelegate
всего приложения.
Выполните следующие действия, чтобы изменить приложение AppDelegate
и добавить необходимый код:
Дважды щелкните
AppDelegate.cs
файл в Обозреватель решений, чтобы открыть его для редактирования.Добавьте в начало файла следующие инструкции using.
using System; using Foundation; using UIKit; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Linq; using AVFoundation; using CoreVideo; using CoreMedia; using CoreGraphics; using CoreFoundation;
Добавьте в класс следующие частные переменные и вычисляемых свойств
AppDelegate
:#region Private Variables private NSError Error; #endregion #region Computed Properties public override UIWindow Window {get;set;} public bool CameraAvailable { get; set; } public AVCaptureSession Session { get; set; } public AVCaptureDevice CaptureDevice { get; set; } public OutputRecorder Recorder { get; set; } public DispatchQueue Queue { get; set; } public AVCaptureDeviceInput Input { get; set; } #endregion
Переопределите готовый метод и измените его на:
public override void FinishedLaunching (UIApplication application) { // Create a new capture session Session = new AVCaptureSession (); Session.SessionPreset = AVCaptureSession.PresetMedium; // Create a device input CaptureDevice = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video); if (CaptureDevice == null) { // Video capture not supported, abort Console.WriteLine ("Video recording not supported on this device"); CameraAvailable = false; return; } // Prepare device for configuration CaptureDevice.LockForConfiguration (out Error); if (Error != null) { // There has been an issue, abort Console.WriteLine ("Error: {0}", Error.LocalizedDescription); CaptureDevice.UnlockForConfiguration (); return; } // Configure stream for 15 frames per second (fps) CaptureDevice.ActiveVideoMinFrameDuration = new CMTime (1, 15); // Unlock configuration CaptureDevice.UnlockForConfiguration (); // Get input from capture device Input = AVCaptureDeviceInput.FromDevice (CaptureDevice); if (Input == null) { // Error, report and abort Console.WriteLine ("Unable to gain input from capture device."); CameraAvailable = false; return; } // Attach input to session Session.AddInput (Input); // Create a new output var output = new AVCaptureVideoDataOutput (); var settings = new AVVideoSettingsUncompressed (); settings.PixelFormatType = CVPixelFormatType.CV32BGRA; output.WeakVideoSettings = settings.Dictionary; // Configure and attach to the output to the session Queue = new DispatchQueue ("ManCamQueue"); Recorder = new OutputRecorder (); output.SetSampleBufferDelegate (Recorder, Queue); Session.AddOutput (output); // Let tabs know that a camera is available CameraAvailable = true; }
Сохраните изменения в файле.
С помощью этого кода можно легко реализовать элементы управления ручной камерой для экспериментирования и тестирования.
Фокус вручную
Позволяя конечному пользователю напрямую контролировать фокус, приложение может обеспечить более художественный контроль над изображением.
Например, профессиональный фотограф может смягчить фокус изображения для достижения эффекта Боке. Или создайте эффект вытягивания фокуса.
Для ученых или писателя медицинских приложений приложение может потребоваться программно переместить объектив вокруг экспериментов. В любом случае новый API позволяет пользователю или приложению управлять фокусом во время создания изображения.
Принцип работы фокуса
Перед обсуждением сведений об управлении фокусом в приложении IOS 8. Давайте рассмотрим, как фокус работает на устройстве iOS:
Свет входит в объектив камеры на устройстве iOS и сосредоточен на датчике изображения. Расстояние объектива от датчика управления, где фокус-точка (область, в которой изображение будет отображаться самым острым) находится в связи с датчиком. Чем дальше объектив от датчика, объекты расстояния кажутся самыми острыми и ближе, рядом с объектами кажутся самыми острыми.
В устройстве iOS объектив перемещается ближе или дальше от датчика магнитами и спрингами. В результате точное расположение объектива невозможно, так как оно будет зависеть от устройства к устройству и может влиять на такие параметры, как ориентация устройства или возраст устройства и весной.
Важные термины фокуса
При работе с фокусом есть несколько терминов, с которыми должен ознакомиться разработчик:
- Глубина поля — расстояние между ближайшими и самыми дальними объектами в фокусе.
- Макрос - Это ближайший конец спектра фокуса и является ближайшим расстоянием, на котором объектив может сосредоточиться.
- Бесконечность - это дальний конец спектра фокуса и является самым дальним расстоянием, на котором объектив может сосредоточиться.
- Гиперфокальное расстояние — это точка в спектре фокуса, где самый дальний объект в кадре находится только в конце фокуса. Другими словами, это фокусовое положение, которое максимизирует глубину поля.
- Положение объектива — это то, что управляет всеми выше другими терминами. Это расстояние от датчика и таким образом контроллер фокуса.
Учитывая эти термины и знания, новые элементы управления фокусом вручную можно успешно реализовать в приложении iOS 8.
Существующие элементы управления фокусом
IOS 7 и более ранние версии предоставляют существующие элементы управления фокусом через FocusMode
свойство:
AVCaptureFocusModeLocked
— фокус заблокирован в одной точке фокуса.AVCaptureFocusModeAutoFocus
- Камера подметает объектив через все фокусные точки, пока он не находит острый фокус, а затем остается там.AVCaptureFocusModeContinuousAutoFocus
— камера перенаправляется всякий раз, когда обнаруживает состояние вне фокуса.
Существующие элементы управления также предоставили точку интереса к набору черезFocusPointOfInterest
свойство, чтобы пользователь смог коснуться, чтобы сосредоточиться на определенной области. Приложение также может отслеживать движение объектива IsAdjustingFocus
, отслеживая свойство.
Кроме того, ограничение диапазона было предоставлено свойством AutoFocusRangeRestriction
следующим образом:
AVCaptureAutoFocusRangeRestrictionNear
— ограничивает автофокус до близлежащих глубин. Полезно в таких ситуациях, как сканирование QR-кода или штрихкода.AVCaptureAutoFocusRangeRestrictionFar
— ограничивает автофокус до удаленных глубин. Полезно в ситуациях, когда объекты, которые, как известно, не имеют значения, находятся в поле представления (например, рамка окна).
Наконец, есть SmoothAutoFocus
свойство, которое замедляет алгоритм автоматического фокуса и выполняет его в меньших добавках, чтобы избежать перемещения артефактов при записи видео.
Новые элементы управления фокусом в iOS 8
Помимо функций, уже предоставляемых iOS 7 и более поздних версий, теперь доступны следующие функции для управления фокусом в iOS 8.
- Полное управление положением объектива при блокировке фокуса вручную.
- Наблюдение за положением объектива в любом режиме фокуса.
Чтобы реализовать указанные выше функции, класс был изменен, чтобы включить свойство только LensPosition
для чтения, AVCaptureDevice
используемое для получения текущей позиции объектива камеры.
Чтобы управлять положением объектива вручную, устройство записи должно находиться в режиме заблокированного фокуса. Пример:
CaptureDevice.FocusMode = AVCaptureFocusMode.Locked;
Метод SetFocusModeLocked
устройства захвата используется для настройки положения объектива камеры. Необязательный подпрограмма обратного вызова может быть предоставлена для получения уведомлений, когда изменения вступает в силу. Пример:
ThisApp.CaptureDevice.LockForConfiguration(out Error);
ThisApp.CaptureDevice.SetFocusModeLocked(Position.Value,null);
ThisApp.CaptureDevice.UnlockForConfiguration();
Как показано в приведенном выше коде, устройство записи должно быть заблокировано для настройки, прежде чем изменить положение объектива. Допустимые значения положения объектива : от 0,0 до 1.0.
Пример фокусировки вручную
С помощью кода UIViewController
установки общей программы записи AV можно добавить в раскадровку приложения и настроить следующим образом:
Представление содержит следующие основные элементы:
- Будет
UIImageView
отображаться видеотрансляции. - Значение
UISegmentedControl
, которое изменит режим фокусировки с автоматического на заблокированное. - Объект
UISlider
, который будет отображать и обновлять текущую позицию объектива.
Выполните следующие действия, чтобы подключить контроллер представления для управления фокусом вручную:
Добавьте операторы using:
using System; using Foundation; using UIKit; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Linq; using AVFoundation; using CoreVideo; using CoreMedia; using CoreGraphics; using CoreFoundation; using System.Timers;
Добавьте следующие частные переменные:
#region Private Variables private NSError Error; private bool Automatic = true; #endregion
Добавьте следующие вычисляемые свойства:
#region Computed Properties public AppDelegate ThisApp { get { return (AppDelegate)UIApplication.SharedApplication.Delegate; } } public Timer SampleTimer { get; set; } #endregion
Переопределите
ViewDidLoad
метод и добавьте следующий код:public override void ViewDidLoad () { base.ViewDidLoad (); // Hide no camera label NoCamera.Hidden = ThisApp.CameraAvailable; // Attach to camera view ThisApp.Recorder.DisplayView = CameraView; // Create a timer to monitor and update the UI SampleTimer = new Timer (5000); SampleTimer.Elapsed += (sender, e) => { // Update position slider Position.BeginInvokeOnMainThread(() =>{ Position.Value = ThisApp.Input.Device.LensPosition; }); }; // Watch for value changes Segments.ValueChanged += (object sender, EventArgs e) => { // Lock device for change ThisApp.CaptureDevice.LockForConfiguration(out Error); // Take action based on the segment selected switch(Segments.SelectedSegment) { case 0: // Activate auto focus and start monitoring position Position.Enabled = false; ThisApp.CaptureDevice.FocusMode = AVCaptureFocusMode.ContinuousAutoFocus; SampleTimer.Start(); Automatic = true; break; case 1: // Stop auto focus and allow the user to control the camera SampleTimer.Stop(); ThisApp.CaptureDevice.FocusMode = AVCaptureFocusMode.Locked; Automatic = false; Position.Enabled = true; break; } // Unlock device ThisApp.CaptureDevice.UnlockForConfiguration(); }; // Monitor position changes Position.ValueChanged += (object sender, EventArgs e) => { // If we are in the automatic mode, ignore changes if (Automatic) return; // Update Focus position ThisApp.CaptureDevice.LockForConfiguration(out Error); ThisApp.CaptureDevice.SetFocusModeLocked(Position.Value,null); ThisApp.CaptureDevice.UnlockForConfiguration(); }; }
Переопределите
ViewDidAppear
метод и добавьте следующее, чтобы начать запись при загрузке представления:public override void ViewDidAppear (bool animated) { base.ViewDidAppear (animated); // Start udating the display if (ThisApp.CameraAvailable) { // Remap to this camera view ThisApp.Recorder.DisplayView = CameraView; ThisApp.Session.StartRunning (); SampleTimer.Start (); } }
При использовании камеры в автоматическом режиме ползунок будет автоматически перемещаться по мере настройки фокуса камеры:
Коснитесь заблокированного сегмента и перетащите ползунок положения, чтобы настроить положение объектива вручную:
Остановите приложение.
Приведенный выше код показал, как отслеживать положение объектива, когда камера находится в автоматическом режиме или использовать ползунок для управления положением объектива, когда он находится в режиме блокировки.
Воздействие вручную
Экспозиция относится к яркости изображения относительно исходной яркости и определяется тем, сколько света попадает в датчик, на сколько времени и на уровне получения датчика (сопоставление ISO). Предоставляя ручной контроль над экспозицией, приложение может обеспечить больше свободы для конечного пользователя и позволить им достичь стилизованного внешнего вида.
С помощью элементов управления экспозицией вручную пользователь может получить изображение от нереалистично яркого до темного и настроенного:
Опять же, это можно сделать автоматически с помощью программного управления для научных приложений или с помощью ручных элементов управления, предоставляемых пользовательским интерфейсом приложений. В любом случае новые API экспозиции iOS 8 обеспечивают точный контроль над параметрами экспозиции камеры.
Принцип работы экспозиции
Перед обсуждением сведений об управлении воздействием в приложении IOS 8. Давайте рассмотрим, как работает экспозиция:
Ниже приведены три основных элемента, которые объединяются для контроля воздействия:
- Скорость затвора — это продолжительность времени, когда затвор открыт, чтобы позволить свету на датчик камеры. Чем короче время открытия затвора, тем меньше света впустит и хрустящий изображение является (меньше размытия движения). Чем дольше затвор открыт, тем больше света впустит и чем больше размытия движения, что происходит.
- Сопоставление ISO — это термин, заимствованный из фотографии пленки и относится к чувствительности химических веществ в пленке к свету. Низкие значения ISO в пленке имеют меньше зерна и более тонкого воспроизведения цветов; низкие значения ISO на цифровых датчиках имеют меньше шума датчика, но меньше яркости. Чем выше значение ISO, тем ярче изображение, но с большим шумом датчика. "ISO" на цифровом датчике является мерой электронного получения, а не физической функции.
- Диафрагма объектива — это размер открывающегося объектива. На всех устройствах iOS диафрагма объектива фиксирована, поэтому единственными двумя значениями, которые можно использовать для настройки экспозиции, являются скорость затвора и ISO.
Как работает непрерывная автоматическая экспозиция
Прежде чем узнать, как работает ручное воздействие, рекомендуется понять, как работает непрерывная автоматическая экспозиция на устройстве iOS.
Во-первых, это блок автоматической экспозиции, он имеет задание вычисления идеальной экспозиции и постоянно кормится статистикой измерения. Эта информация используется для вычисления оптимальной смеси ISO и скорости затвора, чтобы получить сцену хорошо освещенной. Этот цикл называется циклом AE.
Как работает заблокированная экспозиция
Далее давайте рассмотрим, как заблокированная экспозиция работает на устройствах iOS.
Опять же, у вас есть блок автоматического воздействия, который пытается вычислить оптимальные значения iOS и Duration. Однако в этом режиме блок AE отключен от подсистемы статистики измерения.
Существующие элементы управления экспозицией
IOS 7 и более поздних версий предоставьте следующие существующие элементы управления экспозицией ExposureMode
с помощью свойства:
AVCaptureExposureModeLocked
— примеры сцены один раз и используют эти значения во всей сцене.AVCaptureExposureModeContinuousAutoExposure
— примеры сцены непрерывно, чтобы убедиться, что она хорошо освещена.
Можно ExposurePointOfInterest
использовать для касания для предоставления сцены, выбрав целевой объект для предоставления, и приложение может отслеживать AdjustingExposure
свойство, чтобы увидеть, когда настраивается экспозиция.
Новые элементы управления экспозицией в iOS 8
Помимо функций, уже предоставляемых iOS 7 и более поздних версий, теперь доступны следующие функции для управления экспозицией в iOS 8:
- Полностью настраиваемое воздействие вручную.
- Получение, установка и ключевое значение отслеживают скорость ввода-вывода и скорость затвора (длительность).
Для реализации указанных выше функций добавлен новый AVCaptureExposureModeCustom
режим. Если камера находится в пользовательском режиме, можно использовать следующий код для настройки длительности экспозиции и ISO:
CaptureDevice.LockForConfiguration(out Error);
CaptureDevice.LockExposure(DurationValue,ISOValue,null);
CaptureDevice.UnlockForConfiguration();
В режимах авто и блокировки приложение может настроить предвзятость подпрограммы автоматического воздействия с помощью следующего кода:
CaptureDevice.LockForConfiguration(out Error);
CaptureDevice.SetExposureTargetBias(Value,null);
CaptureDevice.UnlockForConfiguration();
Минимальные и максимальные диапазоны параметров зависят от устройства, на котором работает приложение, поэтому они никогда не должны быть жестко закодированы. Вместо этого используйте следующие свойства, чтобы получить минимальные и максимальные диапазоны значений:
CaptureDevice.MinExposureTargetBias
CaptureDevice.MaxExposureTargetBias
CaptureDevice.ActiveFormat.MinISO
CaptureDevice.ActiveFormat.MaxISO
CaptureDevice.ActiveFormat.MinExposureDuration
CaptureDevice.ActiveFormat.MaxExposureDuration
Как показано в приведенном выше коде, устройство записи должно быть заблокировано для настройки перед изменением воздействия.
Пример экспозиции вручную
С помощью кода UIViewController
установки общей программы записи AV можно добавить в раскадровку приложения и настроить следующим образом:
Представление содержит следующие основные элементы:
- Будет
UIImageView
отображаться видеотрансляции. - Значение
UISegmentedControl
, которое изменит режим фокусировки с автоматического на заблокированное. - Четыре
UISlider
элемента управления, отображающие и обновляющие смещение, длительность, ISO и предвзятость.
Выполните следующие действия, чтобы подключить контроллер представления для ручного управления экспозицией.
Добавьте операторы using:
using System; using Foundation; using UIKit; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Linq; using AVFoundation; using CoreVideo; using CoreMedia; using CoreGraphics; using CoreFoundation; using System.Timers;
Добавьте следующие частные переменные:
#region Private Variables private NSError Error; private bool Automatic = true; private nfloat ExposureDurationPower = 5; private nfloat ExposureMinimumDuration = 1.0f/1000.0f; #endregion
Добавьте следующие вычисляемые свойства:
#region Computed Properties public AppDelegate ThisApp { get { return (AppDelegate)UIApplication.SharedApplication.Delegate; } } public Timer SampleTimer { get; set; } #endregion
Переопределите
ViewDidLoad
метод и добавьте следующий код:public override void ViewDidLoad () { base.ViewDidLoad (); // Hide no camera label NoCamera.Hidden = ThisApp.CameraAvailable; // Attach to camera view ThisApp.Recorder.DisplayView = CameraView; // Set min and max values Offset.MinValue = ThisApp.CaptureDevice.MinExposureTargetBias; Offset.MaxValue = ThisApp.CaptureDevice.MaxExposureTargetBias; Duration.MinValue = 0.0f; Duration.MaxValue = 1.0f; ISO.MinValue = ThisApp.CaptureDevice.ActiveFormat.MinISO; ISO.MaxValue = ThisApp.CaptureDevice.ActiveFormat.MaxISO; Bias.MinValue = ThisApp.CaptureDevice.MinExposureTargetBias; Bias.MaxValue = ThisApp.CaptureDevice.MaxExposureTargetBias; // Create a timer to monitor and update the UI SampleTimer = new Timer (5000); SampleTimer.Elapsed += (sender, e) => { // Update position slider Offset.BeginInvokeOnMainThread(() =>{ Offset.Value = ThisApp.Input.Device.ExposureTargetOffset; }); Duration.BeginInvokeOnMainThread(() =>{ var newDurationSeconds = CMTimeGetSeconds(ThisApp.Input.Device.ExposureDuration); var minDurationSeconds = Math.Max(CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MinExposureDuration), ExposureMinimumDuration); var maxDurationSeconds = CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MaxExposureDuration); var p = (newDurationSeconds - minDurationSeconds) / (maxDurationSeconds - minDurationSeconds); Duration.Value = (float)Math.Pow(p, 1.0f/ExposureDurationPower); }); ISO.BeginInvokeOnMainThread(() => { ISO.Value = ThisApp.Input.Device.ISO; }); Bias.BeginInvokeOnMainThread(() => { Bias.Value = ThisApp.Input.Device.ExposureTargetBias; }); }; // Watch for value changes Segments.ValueChanged += (object sender, EventArgs e) => { // Lock device for change ThisApp.CaptureDevice.LockForConfiguration(out Error); // Take action based on the segment selected switch(Segments.SelectedSegment) { case 0: // Activate auto exposure and start monitoring position Duration.Enabled = false; ISO.Enabled = false; ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.ContinuousAutoExposure; SampleTimer.Start(); Automatic = true; break; case 1: // Lock exposure and allow the user to control the camera SampleTimer.Stop(); ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.Locked; Automatic = false; Duration.Enabled = false; ISO.Enabled = false; break; case 2: // Custom exposure and allow the user to control the camera SampleTimer.Stop(); ThisApp.CaptureDevice.ExposureMode = AVCaptureExposureMode.Custom; Automatic = false; Duration.Enabled = true; ISO.Enabled = true; break; } // Unlock device ThisApp.CaptureDevice.UnlockForConfiguration(); }; // Monitor position changes Duration.ValueChanged += (object sender, EventArgs e) => { // If we are in the automatic mode, ignore changes if (Automatic) return; // Calculate value var p = Math.Pow(Duration.Value,ExposureDurationPower); var minDurationSeconds = Math.Max(CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MinExposureDuration),ExposureMinimumDuration); var maxDurationSeconds = CMTimeGetSeconds(ThisApp.CaptureDevice.ActiveFormat.MaxExposureDuration); var newDurationSeconds = p * (maxDurationSeconds - minDurationSeconds) +minDurationSeconds; // Update Focus position ThisApp.CaptureDevice.LockForConfiguration(out Error); ThisApp.CaptureDevice.LockExposure(CMTime.FromSeconds(p,1000*1000*1000),ThisApp.CaptureDevice.ISO,null); ThisApp.CaptureDevice.UnlockForConfiguration(); }; ISO.ValueChanged += (object sender, EventArgs e) => { // If we are in the automatic mode, ignore changes if (Automatic) return; // Update Focus position ThisApp.CaptureDevice.LockForConfiguration(out Error); ThisApp.CaptureDevice.LockExposure(ThisApp.CaptureDevice.ExposureDuration,ISO.Value,null); ThisApp.CaptureDevice.UnlockForConfiguration(); }; Bias.ValueChanged += (object sender, EventArgs e) => { // If we are in the automatic mode, ignore changes // if (Automatic) return; // Update Focus position ThisApp.CaptureDevice.LockForConfiguration(out Error); ThisApp.CaptureDevice.SetExposureTargetBias(Bias.Value,null); ThisApp.CaptureDevice.UnlockForConfiguration(); }; }
Переопределите
ViewDidAppear
метод и добавьте следующее, чтобы начать запись при загрузке представления:public override void ViewDidAppear (bool animated) { base.ViewDidAppear (animated); // Start udating the display if (ThisApp.CameraAvailable) { // Remap to this camera view ThisApp.Recorder.DisplayView = CameraView; ThisApp.Session.StartRunning (); SampleTimer.Start (); } }
При использовании камеры в автоматическом режиме ползунки будут автоматически перемещаться по мере настройки экспозиции камеры:
Коснитесь заблокированного сегмента и перетащите ползунок Предвзятости, чтобы настроить предвзятость автоматического воздействия вручную:
Коснитесь пользовательского сегмента и перетащите ползунки "Длительность" и "ISO", чтобы вручную управлять экспозицией:
Остановите приложение.
Приведенный выше код показал, как отслеживать параметры экспозиции, когда камера находится в автоматическом режиме, и как использовать ползунки для управления экспозицией, когда она находится в заблокированных или настраиваемых режимах.
Балансировка белого трафика вручную
Элементы управления "Белый баланс" позволяют пользователям настраивать баланс колозера на изображении, чтобы сделать их более реалистичным. Различные источники света имеют разные цветовые температуры, а параметры камеры, используемые для захвата изображения, должны быть скорректированы для компенсации этих различий. Опять же, позволяя пользователю контролировать белый баланс, они могут внести профессиональные корректировки, что автоматические подпрограммы не способны достичь художественных эффектов.
Например, дневной свет имеет синеватый литый, в то время как тюнгстен накаливания свет имеет более теплый, желтый оранжевый оттенок. (Запутанно, "холодные" цвета имеют более высокие температуры цвета, чем "теплые" цвета. Температура цвета является физической мерой, а не перцептуальной.)
Человеческий ум очень хорошо компенсирует различия в цветовой температуре, но это то, что камера не может сделать. Камера работает путем повышения цвета на противоположном спектре, чтобы настроить различия в цвете.
Новый API экспозиции iOS 8 позволяет приложению контролировать процесс и обеспечивать точное управление параметрами баланса камеры.
Как работает баланс белого цвета
Перед обсуждением сведений о контроле баланса в приложении IOS 8. Давайте рассмотрим, как работает баланс белого цвета:
В исследовании восприятия цвета пространство цветов CIE 1931 RGB и CIE 1931 XYZ цветового пространства являются первыми математически определенными цветовыми пространствами. Они были созданы Международной комиссией по освещению (CIE) в 1931 году.
На приведенной выше диаграмме показаны все цвета, видимые человеческому глазу, от глубокого синего до ярко-зеленого до ярко-красного. Любую точку на схеме можно отобразить со значением X и Y, как показано на приведенном выше графике.
Как видно на графике, существуют значения X и Y, которые могут быть выложены на графе, который будет находиться за пределами диапазона человеческого зрения, и в результате эти цвета не могут быть воспроизведены камерой.
Меньшая кривая на приведенной выше диаграмме называется Планкским Локусом, который выражает цветовую температуру (в градусах кельвин), с более высокими числами на синей стороне (горячим) и более низкими числами на красной стороне (прохладнее). Это полезно для типичных ситуаций освещения.
В условиях смешанного освещения корректировки баланса белого баланса необходимо будет отклонить от Планкского локуса, чтобы внести необходимые изменения. В таких ситуациях корректировка должна быть перемещена на зеленую или красную или пурпурную сторону шкалы CIE.
Устройства iOS компенсируют цветовые приведение путем повышения противоположного получения цвета. Например, если сцена имеет слишком много синего цвета, то красный выигрыш будет повышен, чтобы компенсировать. Эти значения получения определяются для конкретных устройств, поэтому они зависят от устройств.
Существующие элементы управления балансом белого цвета
IOS 7 и более поздних версий предоставил следующие существующие элементы управления White Balance через WhiteBalanceMode
свойство:
AVCapture WhiteBalance ModeLocked
— примеры сцены один раз и использование этих значений во всей сцене.AVCapture WhiteBalance ModeContinuousAutoExposure
— примеры сцены непрерывно, чтобы убедиться, что она хорошо сбалансирована.
Приложение может отслеживать AdjustingWhiteBalance
свойство, чтобы узнать, когда настраивается экспозиция.
Новые элементы управления "Белый баланс" в iOS 8
Помимо функций, уже предоставляемых iOS 7 и более поздних версий, теперь доступны следующие функции для управления белым балансом в iOS 8.
- Полностью ручное управление преимуществами RGB устройства.
- Получение, установка и ключевое значение отслеживают преимущества RGB устройства.
- Поддержка белого баланса с помощью серой карточки.
- Подпрограммы преобразования в независимые от устройства цветовые пространства и из нее.
Для реализации указанных выше функций AVCaptureWhiteBalanceGain
структура была добавлена со следующими элементами:
RedGain
GreenGain
BlueGain
Максимальное увеличение баланса в настоящее время составляет четыре (4) и может быть готово из MaxWhiteBalanceGain
свойства. Таким образом, юридический диапазон составляет от одного (1) до MaxWhiteBalanceGain
(4) в настоящее время.
Свойство DeviceWhiteBalanceGains
можно использовать для наблюдения за текущими значениями. Используйте SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains
для настройки баланса, когда камера находится в заблокированном режиме балансировки белого баланса.
Подпрограммы преобразования
Подпрограммы преобразования были добавлены в iOS 8, чтобы помочь в преобразовании и из нее независимых цветовых пространств устройств. Для реализации подпрограмм AVCaptureWhiteBalanceChromaticityValues
преобразования структура была добавлена со следующими элементами:
X
— значение от 0 до 1.Y
— значение от 0 до 1.
Структура AVCaptureWhiteBalanceTemperatureAndTintValues
также добавлена со следующими элементами:
Temperature
— значение с плавающей запятой в градусах Кельвина.Tint
— смещение от зеленого или магдента от 0 до 150 с положительными значениями к зеленому направлению и отрицательному направлению в магенду.
CaptureDevice.GetTemperatureAndTintValues
CaptureDevice.GetDeviceWhiteBalanceGains
Используйте методы для преобразования между температурой и тоном, хроматистью и RGB-цветными пространствами.
Примечание.
Подпрограммы преобразования более точны, чем ближе значение, которое необходимо преобразовать, — в Планкийский локус.
Поддержка серых карточек
Apple использует термин "Серый мир" для обозначения поддержки серых карт, встроенной в iOS 8. Он позволяет пользователю сосредоточиться на физической серой карточке, которая охватывает по крайней мере 50 % центра кадра и использует это для настройки белого баланса. Цель серой карточки — достичь белого цвета, который появляется нейтральным.
Это можно реализовать в приложении, побудив пользователя разместить физическую серую карточку перед камерой, отслеживать GrayWorldDeviceWhiteBalanceGains
свойство и ждать, пока значения не урегулироваться.
Затем приложение заблокирует получение белого баланса для SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains
метода, используя значения из GrayWorldDeviceWhiteBalanceGains
свойства, чтобы применить изменения.
Устройство записи должно быть заблокировано для настройки перед изменением в белом балансе.
Пример балансировки белого баланса вручную
С помощью кода UIViewController
установки общей программы записи AV можно добавить в раскадровку приложения и настроить следующим образом:
Представление содержит следующие основные элементы:
- Будет
UIImageView
отображаться видеотрансляции. - Значение
UISegmentedControl
, которое изменит режим фокусировки с автоматического на заблокированное. - Два
UISlider
элемента управления, отображающие и обновляющие температуру и тон. - Используется
UIButton
для выборки пробела серой карточки (серый мир) и задания белого баланса с помощью этих значений.
Выполните следующие действия, чтобы подключить контроллер представления для ручного элемента управления "Белый баланс".
Добавьте операторы using:
using System; using Foundation; using UIKit; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Linq; using AVFoundation; using CoreVideo; using CoreMedia; using CoreGraphics; using CoreFoundation; using System.Timers;
Добавьте следующие частные переменные:
#region Private Variables private NSError Error; private bool Automatic = true; #endregion
Добавьте следующие вычисляемые свойства:
#region Computed Properties public AppDelegate ThisApp { get { return (AppDelegate)UIApplication.SharedApplication.Delegate; } } public Timer SampleTimer { get; set; } #endregion
Добавьте следующий частный метод, чтобы задать новый баланс температуры и тон.
#region Private Methods void SetTemperatureAndTint() { // Grab current temp and tint var TempAndTint = new AVCaptureWhiteBalanceTemperatureAndTintValues (Temperature.Value, Tint.Value); // Convert Color space var gains = ThisApp.CaptureDevice.GetDeviceWhiteBalanceGains (TempAndTint); // Set the new values if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) { gains = NomralizeGains (gains); ThisApp.CaptureDevice.SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains (gains, null); ThisApp.CaptureDevice.UnlockForConfiguration (); } } AVCaptureWhiteBalanceGains NomralizeGains (AVCaptureWhiteBalanceGains gains) { gains.RedGain = Math.Max (1, gains.RedGain); gains.BlueGain = Math.Max (1, gains.BlueGain); gains.GreenGain = Math.Max (1, gains.GreenGain); float maxGain = ThisApp.CaptureDevice.MaxWhiteBalanceGain; gains.RedGain = Math.Min (maxGain, gains.RedGain); gains.BlueGain = Math.Min (maxGain, gains.BlueGain); gains.GreenGain = Math.Min (maxGain, gains.GreenGain); return gains; } #endregion
Переопределите
ViewDidLoad
метод и добавьте следующий код:public override void ViewDidLoad () { base.ViewDidLoad (); // Hide no camera label NoCamera.Hidden = ThisApp.CameraAvailable; // Attach to camera view ThisApp.Recorder.DisplayView = CameraView; // Set min and max values Temperature.MinValue = 1000f; Temperature.MaxValue = 10000f; Tint.MinValue = -150f; Tint.MaxValue = 150f; // Create a timer to monitor and update the UI SampleTimer = new Timer (5000); SampleTimer.Elapsed += (sender, e) => { // Convert color space var TempAndTint = ThisApp.CaptureDevice.GetTemperatureAndTintValues (ThisApp.CaptureDevice.DeviceWhiteBalanceGains); // Update slider positions Temperature.BeginInvokeOnMainThread (() => { Temperature.Value = TempAndTint.Temperature; }); Tint.BeginInvokeOnMainThread (() => { Tint.Value = TempAndTint.Tint; }); }; // Watch for value changes Segments.ValueChanged += (sender, e) => { // Lock device for change if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) { // Take action based on the segment selected switch (Segments.SelectedSegment) { case 0: // Activate auto focus and start monitoring position Temperature.Enabled = false; Tint.Enabled = false; ThisApp.CaptureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.ContinuousAutoWhiteBalance; SampleTimer.Start (); Automatic = true; break; case 1: // Stop auto focus and allow the user to control the camera SampleTimer.Stop (); ThisApp.CaptureDevice.WhiteBalanceMode = AVCaptureWhiteBalanceMode.Locked; Automatic = false; Temperature.Enabled = true; Tint.Enabled = true; break; } // Unlock device ThisApp.CaptureDevice.UnlockForConfiguration (); } }; // Monitor position changes Temperature.TouchUpInside += (sender, e) => { // If we are in the automatic mode, ignore changes if (Automatic) return; // Update white balance SetTemperatureAndTint (); }; Tint.TouchUpInside += (sender, e) => { // If we are in the automatic mode, ignore changes if (Automatic) return; // Update white balance SetTemperatureAndTint (); }; GrayCardButton.TouchUpInside += (sender, e) => { // If we are in the automatic mode, ignore changes if (Automatic) return; // Get gray card values var gains = ThisApp.CaptureDevice.GrayWorldDeviceWhiteBalanceGains; // Set the new values if (ThisApp.CaptureDevice.LockForConfiguration (out Error)) { ThisApp.CaptureDevice.SetWhiteBalanceModeLockedWithDeviceWhiteBalanceGains (gains, null); ThisApp.CaptureDevice.UnlockForConfiguration (); } }; }
Переопределите
ViewDidAppear
метод и добавьте следующее, чтобы начать запись при загрузке представления:public override void ViewDidAppear (bool animated) { base.ViewDidAppear (animated); // Start udating the display if (ThisApp.CameraAvailable) { // Remap to this camera view ThisApp.Recorder.DisplayView = CameraView; ThisApp.Session.StartRunning (); SampleTimer.Start (); } }
Сохраните изменения кода и запустите приложение.
При использовании камеры в автоматическом режиме ползунки будут автоматически перемещаться, так как камера настраивает баланс белого цвета:
Коснитесь заблокированного сегмента и перетащите ползунки Temp и Tint, чтобы настроить баланс белого цвета вручную:
Если сегмент заблокирован по-прежнему выбран, поместите физическую серую карточку перед камерой и нажмите кнопку "Серая карточка", чтобы настроить белый баланс на серый мир:
Остановите приложение.
Приведенный выше код показывает, как отслеживать параметры баланса белого цвета, если камера находится в автоматическом режиме или использует ползунки для управления балансом белого цвета, когда он находится в режиме блокировки.
Запечатленное скобок
Запись с квадратными скобками основана на параметрах, представленных выше, и позволяет приложению захватить момент времени различными способами.
Просто говоря, скобок захвата является всплеском по-прежнему изображений, сделанных с различными параметрами от рисунка до рисунка.
С помощью записи с квадратными скобками в iOS 8 приложение может предустановить ряд элементов управления камерой вручную, выполнить одну команду и вернуть текущую сцену серии изображений для каждого из предустановок вручную.
Основы записи с квадратными скобками
Опять же, скобок захвата является всплеском по-прежнему изображений, сделанных с различными параметрами от рисунка до рисунка. Доступны следующие типы записей с квадратными скобками:
- Автоматическая скобка экспозиции — где все изображения имеют разнообразную величину предвзятости.
- Ручная скобка экспозиции — где все изображения имеют разнообразную скорость затвора (длительность) и объем ISO.
- Простая скобка всплеска — серия по-прежнему изображений, сделанных в быстром последовательности.
Новые элементы управления захвата с квадратными скобками в iOS 8
Все команды записи с квадратными скобками реализуются в AVCaptureStillImageOutput
классе. CaptureStillImageBracket
Используйте метод, чтобы получить ряд изображений с заданным массивом параметров.
Для обработки параметров реализованы два новых класса:
AVCaptureAutoExposureBracketedStillImageSettings
— оно имеет одно свойство,ExposureTargetBias
используемое для задания предвзятости для автоматической скобки экспозиции.AVCaptureManual
ExposureBracketedStillImageSettings
— Он имеет два свойства,ExposureDuration
иISO
используется для установки скорости затвора и ISO для ручной скобки экспозиции.
Элементы управления "Запись в скобках" и "Не"
Do's
Ниже приведен список действий, которые необходимо сделать при использовании элементов управления "Запись в скобках" в iOS 8.
- Подготовьте приложение к худшей ситуации захвата путем вызова
PrepareToCaptureStillImageBracket
метода. - Предположим, что образец буферов будет поступать из одного общего пула.
- Чтобы освободить память, выделенную предыдущим вызовом подготовки, вызовите
PrepareToCaptureStillImageBracket
еще раз и отправьте его массив одного объекта.
Не давайте
Ниже приведен список вещей, которые не должны выполняться при использовании элементов управления "Запись в скобках" в iOS 8.
- Не смешивайте типы параметров записи с квадратными скобками в одном захвате.
- Не запрашивайте больше
MaxBracketedCaptureStillImageCount
изображений в одном захвате.
Сведения о захвате в квадратных скобках
При работе с записью с квадратными скобками в iOS 8 следует учитывать следующие сведения:
- Параметры с квадратными скобками временно переопределяют
AVCaptureDevice
параметры. - Параметры стабилизации изображений и флэш-памяти игнорируются.
- Все изображения должны использовать один и тот же формат вывода (jpeg, png и т. д.)
- Предварительный просмотр видео может удалять кадры.
- Запись с квадратными скобками поддерживается на всех устройствах, совместимых с iOS 8.
Учитывая эти сведения, давайте рассмотрим пример использования скобок для захвата в iOS 8.
Пример записи скобок
С помощью кода UIViewController
установки общей программы записи AV можно добавить в раскадровку приложения и настроить следующим образом:
Представление содержит следующие основные элементы:
- Будет
UIImageView
отображаться видеотрансляции. - Три
UIImageViews
, которые будут отображать результаты захвата. - Для
UIScrollView
размещения видеотрансляции и просмотра результатов. - Используется
UIButton
для захвата с квадратными скобками с некоторыми предварительно заданными параметрами.
Выполните следующие действия, чтобы подключить контроллер представления для записи в квадратных скобках:
Добавьте операторы using:
using System; using System.Drawing; using Foundation; using UIKit; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Linq; using AVFoundation; using CoreVideo; using CoreMedia; using CoreGraphics; using CoreFoundation; using CoreImage;
Добавьте следующие частные переменные:
#region Private Variables private NSError Error; private List<UIImageView> Output = new List<UIImageView>(); private nint OutputIndex = 0; #endregion
Добавьте следующие вычисляемые свойства:
#region Computed Properties public AppDelegate ThisApp { get { return (AppDelegate)UIApplication.SharedApplication.Delegate; } } #endregion
Добавьте следующий закрытый метод для создания необходимых представлений выходных изображений:
#region Private Methods private UIImageView BuildOutputView(nint n) { // Create a new image view controller var imageView = new UIImageView (new CGRect (CameraView.Frame.Width * n, 0, CameraView.Frame.Width, CameraView.Frame.Height)); // Load a temp image imageView.Image = UIImage.FromFile ("Default-568h@2x.png"); // Add a label UILabel label = new UILabel (new CGRect (0, 20, CameraView.Frame.Width, 24)); label.TextColor = UIColor.White; label.Text = string.Format ("Bracketed Image {0}", n); imageView.AddSubview (label); // Add to scrolling view ScrollView.AddSubview (imageView); // Return new image view return imageView; } #endregion
Переопределите
ViewDidLoad
метод и добавьте следующий код:public override void ViewDidLoad () { base.ViewDidLoad (); // Hide no camera label NoCamera.Hidden = ThisApp.CameraAvailable; // Attach to camera view ThisApp.Recorder.DisplayView = CameraView; // Setup scrolling area ScrollView.ContentSize = new SizeF (CameraView.Frame.Width * 4, CameraView.Frame.Height); // Add output views Output.Add (BuildOutputView (1)); Output.Add (BuildOutputView (2)); Output.Add (BuildOutputView (3)); // Create preset settings var Settings = new AVCaptureBracketedStillImageSettings[] { AVCaptureAutoExposureBracketedStillImageSettings.Create(-2.0f), AVCaptureAutoExposureBracketedStillImageSettings.Create(0.0f), AVCaptureAutoExposureBracketedStillImageSettings.Create(2.0f) }; // Wireup capture button CaptureButton.TouchUpInside += (sender, e) => { // Reset output index OutputIndex = 0; // Tell the camera that we are getting ready to do a bracketed capture ThisApp.StillImageOutput.PrepareToCaptureStillImageBracket(ThisApp.StillImageOutput.Connections[0],Settings,async (bool ready, NSError err) => { // Was there an error, if so report it if (err!=null) { Console.WriteLine("Error: {0}",err.LocalizedDescription); } }); // Ask the camera to snap a bracketed capture ThisApp.StillImageOutput.CaptureStillImageBracket(ThisApp.StillImageOutput.Connections[0],Settings, (sampleBuffer, settings, err) =>{ // Convert raw image stream into a Core Image Image var imageData = AVCaptureStillImageOutput.JpegStillToNSData(sampleBuffer); var image = CIImage.FromData(imageData); // Display the resulting image Output[OutputIndex++].Image = UIImage.FromImage(image); // IMPORTANT: You must release the buffer because AVFoundation has a fixed number // of buffers and will stop delivering frames if it runs out. sampleBuffer.Dispose(); }); }; }
Переопределите
ViewDidAppear
метод и добавьте следующий код:public override void ViewDidAppear (bool animated) { base.ViewDidAppear (animated); // Start udating the display if (ThisApp.CameraAvailable) { // Remap to this camera view ThisApp.Recorder.DisplayView = CameraView; ThisApp.Session.StartRunning (); } }
Сохраните изменения кода и запустите приложение.
Кадр сцены и нажмите кнопку "Захватить скобку":
Проводите пальцем вправо влево, чтобы увидеть три изображения, сделанные в скобках:
Остановите приложение.
Приведенный выше код показано, как настроить и принять функцию автоматического захвата скобок в квадратных скобках в iOS 8.
Итоги
В этой статье мы рассмотрели введение в новые элементы управления ручной камеры, предоставляемые iOS 8, и рассмотрели основы того, что они делают и как они работают. Мы дали примеры ручного фокуса, ручной экспозиции и ручного белого баланса. Наконец, мы дали пример создания скобок с помощью ранее рассмотренных элементов управления камерой вручную.