可變相片序列
本文說明如何拍攝可變相片序列,這可讓您快速連續拍攝多個影像畫面,並設定每個畫面使用不同的對焦、閃光、ISO、曝光和曝光補償設定。 此功能可實現如建立高動態範圍 (HDR) 影像等案例。
如果您想要拍攝 HDR 影像,但不想實作自己的處理演算法,則可以使用 AdvancedPhotoCapture API 來使用 Windows 內建的 HDR 功能。 如需詳細資訊,請參閱高動態範圍 (HDR) 相片拍攝。
注意
本文以使用 MediaCapture 進行基本相片、視訊和音訊的擷取中所討論的概念和程式碼為基礎,說明實作基本相片和視訊擷取的步驟。 建議您先熟悉該文章中的基本媒體擷取模式後,再繼續進行更進階的擷取案例。 本文中的程式碼假設您的應用程式已經有已正確初始化的 MediaCapture 執行個體。
設定您的應用程式以使用可變相片序列拍攝
除了基本媒體拍攝所需的命名空間之外,實作可變相片序列拍攝還需要下列命名空間。
using Windows.Media.Capture.Core;
using Windows.Media.Devices.Core;
宣告成員變數來儲存 VariablePhotoSequenceCapture 物件,用來起始相片序列拍攝。 宣告 SoftwareBitmap 物件的陣列,以將每個拍攝的影像儲存在序列中。 此外,請宣告陣列來儲存每個畫面的 CapturedFrameControlValues 物件。 這可供影像處理演算法使用,以判斷用來擷取每個畫面的設定。 最後,宣告將用來追蹤目前正在擷取序列中哪個影像的索引。
VariablePhotoSequenceCapture _photoSequenceCapture;
SoftwareBitmap[] _images;
CapturedFrameControlValues[] _frameControlValues;
int _photoIndex;
準備可變照片序列拍攝
初始化 MediaCapture 之後,請從媒體拍攝的 VideoDeviceController 中取得 VariablePhotoSequenceController 的執行個體,並檢查 Supported 屬性,以確定目前裝置上支援可變相片序列。
var varPhotoSeqController = _mediaCapture.VideoDeviceController.VariablePhotoSequenceController;
if (!varPhotoSeqController.Supported)
{
ShowMessageToUser("Variable Photo Sequence is not supported");
return;
}
從可變相片序列控制器取得 FrameControlCapabilities 物件。 此物件有個屬性,可以針對相片序列裡的每個畫面進行所有設定。 包括:
本範例會為每個畫面設定不同的曝光補償值。 若要確認目前裝置的相片序列支援曝光補償,請透過 ExposureCompensation 屬性存取 FrameExposureCompensationCapabilities 物件,檢查其 Supported 屬性。
var frameCapabilities = varPhotoSeqController.FrameCapabilities;
if (!frameCapabilities.ExposureCompensation.Supported)
{
ShowMessageToUser("EVCompenstaion is not supported in FrameController");
return;
}
針對您想要拍攝的每個畫面建立新的 FrameController 物件。 此範例會拍攝三個畫面。 針對您想要在每個畫面改變的部分,設定控制項的值。 然後,清除 VariablePhotoSequenceController 的 DesiredFrameControllers 集合,並將每個畫面控制器新增至集合。
var frame0 = new FrameController();
var frame1 = new FrameController();
var frame2 = new FrameController();
frame0.ExposureCompensationControl.Value = -1.0f;
frame1.ExposureCompensationControl.Value = 0.0f;
frame2.ExposureCompensationControl.Value = 1.0f;
varPhotoSeqController.DesiredFrameControllers.Clear();
varPhotoSeqController.DesiredFrameControllers.Add(frame0);
varPhotoSeqController.DesiredFrameControllers.Add(frame1);
varPhotoSeqController.DesiredFrameControllers.Add(frame2);
建立 ImageEncodingProperties 物件,以設定您要用來拍攝影像的編碼方式。 呼叫靜態方法 MediaCapture.PrepareVariablePhotoSequenceCaptureAsync,傳入編碼屬性。 這個方法會傳回 VariablePhotoSequenceCapture 物件。 最後,註冊 PhotoCaptured 和 Stopped 事件的事件處理常式。
try
{
var imageEncodingProperties = ImageEncodingProperties.CreateJpeg();
_photoSequenceCapture = await _mediaCapture.PrepareVariablePhotoSequenceCaptureAsync(imageEncodingProperties);
_photoSequenceCapture.PhotoCaptured += OnPhotoCaptured;
_photoSequenceCapture.Stopped += OnStopped;
}
catch (Exception ex)
{
ShowMessageToUser("Exception in PrepareVariablePhotoSequence: " + ex.Message);
}
開始可變照片序列拍攝
若要開始拍攝可變相片序列,請呼叫 VariablePhotoSequenceCapture.StartAsync。 請務必初始化儲存所拍攝影像的陣列和畫面控制項的值,並將目前的索引設定為 0。 設定應用程式的錄製狀態變數並更新 UI,當此拍攝正在進行中的時候,停用另一個拍攝的啟動。
private async void StartPhotoCapture()
{
_images = new SoftwareBitmap[3];
_frameControlValues = new CapturedFrameControlValues[3];
_photoIndex = 0;
_isRecording = true;
await _photoSequenceCapture.StartAsync();
}
接收所拍攝的畫面
每張所拍攝的畫面,都會引發 PhotoCaptured 事件。 儲存畫面控制項的值以及所拍攝的畫面影像,然後遞增目前的畫面索引。 此範例示範如何取得每個畫面的 SoftwareBitmap 表示法。 如需使用 SoftwareBitmap 的詳細資訊,請參閱影像處理。
void OnPhotoCaptured(VariablePhotoSequenceCapture s, VariablePhotoCapturedEventArgs args)
{
_images[_photoIndex] = args.Frame.SoftwareBitmap;
_frameControlValues[_photoIndex] = args.CapturedFrameControlValues;
_photoIndex++;
}
處理可變相片序列擷取的完成
當序列中的所有畫面都已拍攝時,就會引發 Stopped 事件。 更新應用程式的錄製狀態,並更新 UI,讓使用者起始新的拍攝。 此時,您可以將拍攝的影像和畫面控制項的值傳遞至您的影像處理程式碼。
void OnStopped(object s, object e)
{
_isRecording = false;
MyPostProcessingFunction(_images, _frameControlValues, 3);
}
更新畫面控制器
如果您想要以不同的每張畫面設定來執行另一個可變相片序列拍攝,此時不需要完全重新初始化 VariablePhotoSequenceCapture。 您可以清除 DesiredFrameControllers 集合並新增畫面控制器,也可以修改現有的畫面控制器值。 下列範例會檢查 FrameFlashCapabilities 物件,以確認目前的裝置是否支援可變相片序列畫面的閃光燈和閃光燈強度。 如果是,則會更新每個畫面,以啟用 100% 強度的閃光燈。 先前針對每個畫面所設定的曝光補償值,仍在作用中。
var varPhotoSeqController = _mediaCapture.VideoDeviceController.VariablePhotoSequenceController;
if (varPhotoSeqController.FrameCapabilities.Flash.Supported &&
varPhotoSeqController.FrameCapabilities.Flash.PowerSupported)
{
for (int i = 0; i < varPhotoSeqController.DesiredFrameControllers.Count; i++)
{
varPhotoSeqController.DesiredFrameControllers[i].FlashControl.Mode = FrameFlashMode.Enable;
varPhotoSeqController.DesiredFrameControllers[i].FlashControl.PowerPercent = 100;
}
}
清除可變相片序列拍攝
當您完成拍攝可變相片序列或 app 暫停時,請呼叫 FinishAsync 來清除可變相片序列物件。 取消註冊物件的事件處理常式,並將其設定為 null。
await _photoSequenceCapture.FinishAsync();
_photoSequenceCapture.PhotoCaptured -= OnPhotoCaptured;
_photoSequenceCapture.Stopped -= OnStopped;
_photoSequenceCapture = null;
相關主題