低光量画像は高画質でキャプチャするのが難しい画像です。絞りとセンサー サイズが固定されているモバイル デバイスでは、特にキャプチャするのが難しくなります。 低光量を補正するために、デバイスでは露出時間を長くしたり、センサー ゲインを上げたりする場合がありますが、これにより、モーション ブラーが発生したり、画像のノイズが増えたりする可能性があります。
LowLightFusion class を使用すると、時間的に非常に近接している複数のフレームからのピクセル情報をサンプリングすることによって、低光量画像の画質が向上します。つまり、短時間のバースト画像によって、ノイズとモーション ブラーが減少します。 これは、写真編集アプリなどに追加できる便利な機能です。
この機能は、AdvancedPhotoCapture クラスを介して利用することもできます。このクラスでは、必要に応じて、画像のキャプチャの直後に低光量 Fusion アルゴリズムを一連の画像に適用します。 この機能の実装方法については、「低光量写真のキャプチャ」をご覧ください。
処理する画像を準備する
この例では、LowLightFusion クラス および FileOpenPicker を使用して、ユーザーが低光量 Fusion を実行する複数の画像を選択できるようにする方法について説明します。
最初に、アルゴリズムで受け入れる画像の枚数 (フレームとも呼ばれます) を決定し、これらのフレームを格納するリストを作成する必要があります。
// Query the supported max number of input bitmap frames for Low Light Fusion
int maxFrames = LowLightFusion.MaxSupportedFrameCount;
// The bitmap frames to perform Low Light Fusion on.
var framelist = new List<SoftwareBitmap>(maxFrames);
低光量 Fusion アルゴリズムで受け入れるフレームの枚数を決定したら、FileOpenPicker を使用して、アルゴリズムで利用される画像をユーザーが選択できるようにすることができます。
var fileOpenPicker = new FileOpenPicker();
fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileOpenPicker.FileTypeFilter.Add(".png");
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
var inputFiles = await fileOpenPicker.PickMultipleFilesAsync();
if (inputFiles == null)
{
// The user cancelled the picking operation
return null;
}
if(inputFiles.Count >= maxFrames)
{
Debug.WriteLine("You can only choose up to {0} image(s) to input.", maxFrames);
}
適切な枚数のフレームが選択されているので、次に、フレームを SoftwareBitmaps にデコードし、SoftwareBitmaps が LowLightFusion の正しい形式になっていることを確認する必要があります。
SoftwareBitmap softwareBitmap;
// Decode the images into bitmaps
for (int i = 0; i < inputFiles.Count; i++)
{
using (IRandomAccessStream stream = await inputFiles[0].OpenAsync(FileAccessMode.Read))
{
// Create the decoder from the stream
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
// Get the SoftwareBitmap representation of the file
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
framelist.Add(softwareBitmap);
}
}
// Ensure that the selected bitmap frames have an acceptable pixel format for Low Light Fusion.
// For this sample, we'll use the pixel format at index 0.
IReadOnlyList<BitmapPixelFormat> formats = LowLightFusion.SupportedBitmapPixelFormats;
BitmapPixelFormat llfFormat = formats[0];
for (int i = 0; i < framelist.Count; i++)
{
if (framelist[i].BitmapPixelFormat == llfFormat)
{
// The pixel format is acceptable
}
else
{
// Convert the pixel format
framelist[i] = SoftwareBitmap.Convert(framelist[i], llfFormat);
}
}
return framelist;
複数のビットマップを 1 つのビットマップに合成する
適切な枚数のフレームが受け付け可能な形式になっているので、次に、FuseAsync メソッドを使用して、低光量 Fusion アルゴリズムを適用します。 結果として生成される処理済みの画像は、鮮明度が向上しており、SoftwareBitmap の形式になります。
LowLightFusionResult result = await LowLightFusion.FuseAsync(pictures);
最後に、ユーザーが使い慣れた "通常" の画像形式 (作業を開始したときと同様の画像形式) にエンコードし保存することによって、生成された SoftwareBitmap をクリーンアップします。
// Convert bitmap to Rgba16, Rgba8, or Bgra8 for encoding.
var frameConverted = SoftwareBitmap.Convert(frame, BitmapPixelFormat.Bgra8);
var fileSavePicker = new FileSavePicker();
fileSavePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileSavePicker.FileTypeChoices.Add("PNG files", new List<string>() { ".png" });
fileSavePicker.SuggestedFileName = "LLF Output";
var outputFile = await fileSavePicker.PickSaveFileAsync();
if (outputFile == null)
{
// The user cancelled the picking operation
return;
}
// Encode and save the image
using (IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
{
// Create an encoder with the desired format
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
// Set the software bitmap
encoder.SetSoftwareBitmap(frameConverted);
try
{
await encoder.FlushAsync();
}
catch (Exception err)
{
switch (err.HResult)
{
case unchecked((int)0x88982F81): // WINCODEC_ERR_UNSUPPORTEDOPERATION
// If the encoder does not support writing a thumbnail, then try again
// but disable thumbnail generation.
encoder.IsThumbnailGenerated = false;
break;
default:
throw err;
}
}
if (encoder.IsThumbnailGenerated == false)
{
await encoder.FlushAsync();
}
}
適用前と適用後
1 つの入力画像と、低光量 Fusion アルゴリズムを適用した結果の出力画像の例を示します。
入力フレーム | 低光量 Fusion による出力 |
---|---|
![]() |
![]() |
照明やバナーの周囲の影の鮮明さが向上したことが、入力フレームから確認できます。