エクスポート (0) 印刷
すべて展開

方法: Windows Phone 用カメラ アプリケーションでグレースケールを処理する

2012/02/09

Windows Phone OS 7.1 を使用して、プログラムによってデバイス カメラにアクセスできます。このトピックでは、カメラ プレビュー バッファーからのライブ ビデオ フレームを変更する方法について説明します。このトピックで説明しているアプリケーションでは、カメラからのアルファ、赤、緑、青 (ARGB) の各フレームを処理し、それらをグレースケールに変換する方法を示しています。このトピックは、カメラのグレースケールのサンプルに対応しています。完全なプロジェクトをダウンロードするには、「Windows Phone のコード サンプル」を参照してください。

ヒントヒント:

アプリケーションで、グレースケール フレームのみ必要で、色を処理する必要がない場合は、GetPreviewBufferY(array<Byte>[]()[][]) メソッドを使用することを検討してください。このメソッドでは効率的な YCbCr 形式を使用して、カメラ プレビュー バッファーから輝度 (Y) 情報のみをキャプチャします。詳細については、「Windows Phone のカメラ カラーの変換 (YCbCr から ARGB)」を参照してください。

このトピックは 2 つの部分で構成されています。

重要な注重要な注:

Windows Phone OS 7.1 の機能を使用するために、Windows Phone OS 7.0 アプリケーションをアップグレードした場合、カメラ機能 ID_CAP_ISV_CAMERA はアプリケーション マニフェスト ファイル WMAppManifest.xml に自動的に追加されません。ID_CAP_ISV_CAMERA がないと、カメラ API を使用したアプリケーションは機能しません。新しい Windows Phone OS 7.1 プロジェクトで、この機能はアプリケーション マニフェスト ファイルに含まれます。

次のイメージに、このトピックで作成されるカメラ アプリケーションを示します。

AP_Con_CameraGrayscale
注注:

このトピックは、C# 開発を基にしていますが、Visual Basic のコードも提供しています。

このセクションでは、カメラ UI を作成します。この UI は、ファインダー領域、カラー モードとグレースケール モードを切り替えるボタン StackPanel コントロール、グレースケール表示のためにファインダー領域に重なって表示される Image コントロールから構成されます。

カメラ UI と基本機能を作成するには

  1. Visual Studio 2010 Express for Windows Phone で、[ファイル] メニューの [新しいプロジェクト] をクリックして新しいプロジェクトを作成します。

  2. [新しいプロジェクト] ウィンドウが表示されます。Visual C# のテンプレートを展開してから、Silverlight for Windows Phone のテンプレートを選択します。

  3. Windows Phone アプリケーション テンプレートを選択します。[名前] ボックスに選択した名前を入力します。

  4. [OK] をクリックします。[新しい Windows Phone アプリケーション] ウィンドウが表示されます。

  5. [ターゲットの Windows Phone のバージョン] メニューで、Windows Phone 7.1 が選択されていることを確認します。

  6. [OK] をクリックします。新しいプロジェクトが作成され、Visual Studio のデザイナー ウィンドウに MainPage.xaml が表示されます。

  7. [プロジェクト] メニューの [参照の追加] をクリックします。[.NET] タブで [Microsoft.XNA.Framework] を選択し、[OK] をクリックします。

  8. MainPage.xaml で、次のコードに示されているように phone:PhoneApplicationPage 要素を更新します。

        SupportedOrientations="Landscape" Orientation="LandscapeLeft"
        shell:SystemTray.IsVisible="False"
    
    

    これによって、ページが横向きに構成され、システム トレイが非表示になります。

  9. MainPage.xaml で、次のコードを使用して LayoutRoot という名前の Grid を置き換えます。

        <!--LayoutRoot is the root grid where all page content is placed-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="640" />
                <ColumnDefinition Width="160*" />
            </Grid.ColumnDefinitions>
    
            <!--Camera viewfinder >-->
            <Rectangle Width="640" Height="480" HorizontalAlignment="Left" >
                <Rectangle.Fill>
                    <VideoBrush x:Name="viewfinderBrush" />
                </Rectangle.Fill>
    
            </Rectangle>
    
            <!--Overlay for the viewfinder region to display grayscale WriteableBitmap objects-->
            <Image x:Name="MainImage" 
                   Width="320" Height="240" 
                   HorizontalAlignment="Left" VerticalAlignment="Bottom"  
                   Margin="16,0,0,16"
                   Stretch="Uniform"/>
    
            <!--Button StackPanel to the right of viewfinder>-->
            <StackPanel Grid.Column="1" >
                <Button             
                    Content="Gray: ON"
                    Name="GrayscaleOnButton"  
                    Click="GrayOn_Clicked" />
                <Button             
                    Content="Gray: OFF"
                    Name="GrayscaleOffButton"  
                    Click="GrayOff_Clicked" />
            </StackPanel>
    
            <!--Used for debugging >-->
            <TextBlock Height="40" HorizontalAlignment="Left" Margin="8,428,0,0" Name="txtDebug" VerticalAlignment="Top" Width="626" FontSize="24" FontWeight="ExtraBold" />
    
        </Grid>
    
    

    このコードでは、グレースケールのオンおよびオフのボタンを含む StackPanel コントロールのある 640 x 480 ファインダーを作成します。繰り返しますが、Image コントロールの目的は、グレースケール モードが選択された場合に、ファインダー領域を重ねて表示することです。これは、フレーム ポンプによって提供されるグレースケール WriteableBitmap オブジェクトの代替の表示領域を作成します。

  10. メイン ページの分離コード ファイル MainPage.xaml.cs を開き、ページの先頭に次のディレクティブを追加します。

    // Directives
    using Microsoft.Devices;
    using System.Windows.Media.Imaging;
    using System.Threading;
    
    
  11. MainPage.xaml.csMainPage クラスで、MainPage クラス コンストラクターの上に次の変数宣言を追加します。

        // Variables
        PhotoCamera cam = new PhotoCamera();
        private static ManualResetEvent pauseFramesEvent = new ManualResetEvent(true);
        private WriteableBitmap wb;
        private Thread ARGBFramesThread;
        private bool pumpARGBFrames;
    
    
  12. MainPage.xaml.cs で、次のコードを MainPage クラスに追加します。

    注注:

    この手順の以下の部分を完了するまで、Visual Studio によって、現在のコンテキストに存在しないメソッドに関するエラーが出力される可能性があります。これらのメソッドは、以下の手順で追加されます。

            //Code for camera initialization event, and setting the source for the viewfinder
            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
    
                // Check to see if the camera is available on the device.
                if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true) ||
                     (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) == true))
                {
                    // Initialize the default camera.
                    cam = new Microsoft.Devices.PhotoCamera();
    
                    //Event is fired when the PhotoCamera object has been initialized
                    cam.Initialized += new EventHandler<Microsoft.Devices.CameraOperationCompletedEventArgs>(cam_Initialized);
    
                    //Set the VideoBrush source to the camera
                    viewfinderBrush.SetSource(cam);
                }
                else
                {
                    // The camera is not supported on the device.
                    this.Dispatcher.BeginInvoke(delegate()
                    {
                        // Write message.
                        txtDebug.Text = "A Camera is not available on this device.";
                    });
    
                    // Disable UI.
                    GrayscaleOnButton.IsEnabled = false;
                    GrayscaleOffButton.IsEnabled = false;
                }
            }
    
            protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
            {
                if (cam != null)
                {
                    // Dispose of the camera to minimize power consumption and to expedite shutdown.
                    cam.Dispose();
    
                    // Release memory, ensure garbage collection.
                    cam.Initialized -= cam_Initialized;
                }
            }
    
    

    このコードでは OnNavigatedTo(NavigationEventArgs) メソッドを使用して、cam という名前の PhotoCamera オブジェクトを作成し、イベント ハンドラーを追加します。また、このコードは、VideoBrush ソースをデバイスのカメラ オブジェクト cam に設定します。デバイスでカメラを使用できない場合は、ボタンが無効にされ、UI にメッセージが表示されます。

    注注:

    カメラからビデオ フレームを取得するには、GetPreviewBufferArgb32(array<Int32>[]()[][]) メソッドで後述するように、PhotoCamera オブジェクトでビデオ プレビューを VideoBrush コントロールに表示するように設定する必要があります。

  13. MainPage.xaml.cs で、次のコードを MainPage クラスに追加します。

        protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            // Dispose camera to minimize power consumption and to expedite shutdown.
            cam.Dispose();
    
            // Release memory, ensure garbage collection.
            cam.Initialized -= cam_Initialized;
        }
    
    

    このコードにより、カメラに関係するメモリを解放できます。

  14. MainPage.xaml.cs で、次のコードを MainPage クラスに追加します。

    //Update UI if initialization succeeds
            void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
            {        
                if (e.Succeeded)
                {
                    this.Dispatcher.BeginInvoke(delegate()
                    {
                        txtDebug.Text = "Camera initialized";
                    });
                   
                }
            }
    
    

    このコードは、カメラの Initialized イベントを使用し、txtDebug という名前の TextBlock を更新します。アプリケーション UI は別のスレッドで実行されているので、状態を更新するには BeginInvoke メソッドが必要です。

  15. カメラ アプリケーションを作成するには、アプリケーション マニフェスト ファイルでカメラ機能を宣言する必要があります。これがないと、アプリケーションは機能しません。WMAppManifest.xml を開き、次の機能要素が存在していることを確認します。

    <Capability Name="ID_CAP_ISV_CAMERA"/>
    

このセクションでは、連携してカメラから ARGB (アルファ、赤、緑、青) フレームを取得し、それらをグレースケールに変換する 2 つのメソッドを作成します。

ARGB フレーム ポンプを作成するには

  1. MainPage.xaml.cs で、次のコードを MainPage クラスに追加します。

        // ARGB frame pump
        void PumpARGBFrames()
        {
            // Create capture buffer.
            int[] ARGBPx = new int[(int) cam.PreviewResolution.Width * (int) cam.PreviewResolution.Height];
    
            try
            {
                PhotoCamera phCam = (PhotoCamera)cam;
    
                while (pumpARGBFrames)
                {
                    pauseFramesEvent.WaitOne();
    
                    // Copies the current viewfinder frame into a buffer for further manipulation.
                    phCam.GetPreviewBufferArgb32(ARGBPx);
    
                    // Conversion to grayscale.
                    for (int i = 0; i < ARGBPx.Length; i++)
                    {
                        ARGBPx[i] = ColorToGray(ARGBPx[i]);
                    }
    
                    pauseFramesEvent.Reset();
                    Deployment.Current.Dispatcher.BeginInvoke(delegate()
                    {
                        // Copy to WriteableBitmap.
                        ARGBPx.CopyTo(wb.Pixels, 0);
                        wb.Invalidate();
    
                        pauseFramesEvent.Set();
                    });
                }
    
            }
            catch (Exception e)
            {
                this.Dispatcher.BeginInvoke(delegate()
                {
                    // Display error message.
                    txtDebug.Text = e.Message;
                });
            }
        }
    
        internal int ColorToGray(int color)
        {
            int gray = 0;
    
            int a = color >> 24;
            int r = (color & 0x00ff0000) >> 16;
            int g = (color & 0x0000ff00) >> 8;
            int b = (color & 0x000000ff);
    
            if ((r == g) && (g == b))
            {
                gray = color;
            }
            else
            {
                // Calculate for the illumination.
                // I =(int)(0.109375*R + 0.59375*G + 0.296875*B + 0.5)
                int i = (7 * r + 38 * g + 19 * b + 32) >> 6;
    
                gray = ((a & 0xFF) << 24) | ((i & 0xFF) << 16) | ((i & 0xFF) << 8) | (i & 0xFF);
            }
            return gray;
        }
    
    

    このコードでは、PumpARGBFrames (ARGB フレーム ポンプ) というメソッドは ARGB フレームを操作するためにバッファにコピーします。次に、各フレームがバッファ内にある間、ColorToGray メソッドを使用して、フレームをグレースケールに変換します。最後に、PumpARGBFrames は変換したフレームを wb という WriteableBitmap オブジェクトにコピーします。フレーム ポンプの連続処理によって、UI に表示される白黒のライブ ビデオを生成します。

    注注:

    カメラからビデオ フレームを取得するには、GetPreviewBufferArgb32(array<Int32>[]()[][]) メソッドで示すように、PhotoCamera オブジェクトでビデオ プレビューを VideoBrush コントロールに表示するように設定する必要があります。

  2. MainPage.xaml.cs で、次のコードを MainPage クラスに追加します。

        // Start ARGB to grayscale pump.
        private void GrayOn_Clicked(object sender, RoutedEventArgs e)
        {
            MainImage.Visibility = Visibility.Visible;
            pumpARGBFrames = true;
            ARGBFramesThread = new System.Threading.Thread(PumpARGBFrames);
    
            wb = new WriteableBitmap((int) cam.PreviewResolution.Width, (int) cam.PreviewResolution.Height);
            this.MainImage.Source = wb;
    
            // Start pump.
            ARGBFramesThread.Start();
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "ARGB to Grayscale";
            });
        }
    
        // Stop ARGB to grayscale pump.
        private void GrayOff_Clicked(object sender, RoutedEventArgs e)
        {
            MainImage.Visibility = Visibility.Collapsed;
            pumpARGBFrames = false;
    
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "";
            });
        }
    
    

    このコードで、GrayOn_Clicked メソッドは MainImage という名前の Image コントロールを画面を覆うようにサイズ変更し、そのコントロールを、ARGB フレーム ポンプによって更新される wb という名前の書き込み可能なビットマップを表示するように設定します。GrayOff_Clicked イベントは MainImage コントロールを折りたたみ、フレーム ポンプを停止します。

    注注:

    Image コントロールの表示は特定の状況で折りたたまれることに注意してください。繰り返しますが、このコントロールは標準カラー ファインダーの実装に重なって表示されます。コントロールはグレースケール表示のためにアクティブにされ、表示されます。

  3. デバイスで、[デバッグ] メニューの [デバッグ開始] をクリックしてアプリケーションを実行します。

表示:
© 2014 Microsoft