none
カメラ制御に関して RRS feed

  • 質問

  • Windows8.1, Visual Studio 2013 VBでの開発を行っています。

    カメラ制御を行いたいのですが。Windowsストアアプリではできるのですが、訳あって、Windowsフォームでの開発を行っています。

    どのように行うかを教えていただけないでしょうか。出来ないのであれば、WindowsフォームからWindowsストアアプリの呼び出し方法でもかまいません。

    よろしくお願いします。

    下記の内容はWindows8.1 Windowsストアアプリで調べた結果です。これは問題ありません。

    dim dialog = New Windows.Media.Capture.CameraCaptureUI()

    dialog.PhotoSettings.Format = Windows.Media.Capture.CameraCaptureUIPhotoFormat.Png

    dim file = Await dialog.CaptureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.Photo)

    If (File IsNot Nothing) Then

      dim MsgBox = New Windows.UI.Popups.MessageDialog(File.Path, "撮影結果)

      Awaint MsgBox.ShowAsync()

    End If

    2015年1月19日 1:04

回答

  • WindowsFormからWinRTのdllを呼んでカメラ撮影できます。
    http://blogs.msdn.com/b/eternalcoding/archive/2013/10/29/how-to-use-specific-winrt-api-from-desktop-apps-capturing-a-photo-using-your-webcam-into-a-wpf-app.aspx
    を参考にしました。

    • TargetPlatformVersionを設定してWinRTのdllを使用することを宣言
    • System.Runtime.WindowsRuntime.dll
    • System.Runtime.dll
    • System.Runtime.InteropServices.WindowsRuntime.dll
    • System.Threading.Tasks.dll
    • System.IO.dll
    • Windows.winmd

    などの参照を追加するとWindows.Media.Captureを使用してのカメラ撮影が行えました。

    Imports Windows.Devices.Enumeration
    Imports Windows.Media.Capture
    Imports Windows.Media.MediaProperties
    Imports Windows.Storage.Streams
    
    Public Class Form1
    
        Dim pictureBox1 As PictureBox
        Dim listBox1 As ListBox
    
        Sub New()
            InitializeComponent()
    
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            Me.Width = 600
            Me.Height = 600
    
            Dim panel1 = New System.Windows.Forms.Panel()
            panel1.Width = 100
            panel1.Dock = DockStyle.Left
            Me.Controls.Add(panel1)
    
            Dim label1 = New Label()
            label1.Text = "カメラ一覧"
            panel1.Controls.Add(label1)
    
            listBox1 = New ListBox()
            listBox1.Width = 100
            listBox1.Top = label1.Height
            listBox1.DisplayMember = "Name"
            AddHandler listBox1.SelectedIndexChanged, Sub(s, e)
                                                          CaptureImage()
                                                      End Sub
            panel1.Controls.Add(listBox1)
    
            Dim button1 = New Button()
            button1.Text = "Capture"
            button1.Top = listBox1.Top + listBox1.Height + 5
            button1.AutoSize = True
            AddHandler button1.Click, Sub(s, e)
                                          CaptureImage()
                                      End Sub
            panel1.Controls.Add(button1)
    
            pictureBox1 = New PictureBox()
            pictureBox1.Dock = DockStyle.Fill
            pictureBox1.BackColor = Color.White
            Me.Controls.Add(pictureBox1)
    
            AddHandler Me.Shown, AddressOf Form1_Shown
        End Sub
    
        Private Async Sub Form1_Shown(sender As Object, e As EventArgs)
            '利用可能なビデオデバイス(カメラ)を探す
            Dim devices = Await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(DeviceClass.VideoCapture)
            If (devices.Count = 0) Then
    
                MessageBox.Show("カメラが見つかりませんでした", "Error", MessageBoxButtons.OK)
                Return
            End If
            Me.listBox1.DataSource = devices.ToArray()
    
        End Sub
    
    
        Private Async Sub CaptureImage()
            Me.Enabled = False
            Try
    
                Dim di = DirectCast(listBox1.SelectedItem, DeviceInformation)
    
                Using mediaCapture1 As New MediaCapture()
    
                    AddHandler mediaCapture1.Failed, Sub(s, errorEventArgs)
                                                         MessageBox.Show("キャプチャできませんでした:" + errorEventArgs.Message, "Error", MessageBoxButtons.OK)
                                                     End Sub
    
                    Dim setting As New MediaCaptureInitializationSettings()
                    setting.VideoDeviceId = di.Id 'カメラ選択
                    setting.StreamingCaptureMode = StreamingCaptureMode.Video
                    Await mediaCapture1.InitializeAsync(setting)
    
                    Dim pngProperties = ImageEncodingProperties.CreatePng()
                    pngProperties.Width = CType(pictureBox1.Width, UInteger)
                    pngProperties.Height = CType(pictureBox1.Height, UInteger)
    
                    Using randomAccessStream As New InMemoryRandomAccessStream()
    
                        Await mediaCapture1.CapturePhotoToStreamAsync(pngProperties, randomAccessStream)
    
                        randomAccessStream.Seek(0)
    
                        'ビットマップにして表示
                        Dim stream = System.IO.WindowsRuntimeStreamExtensions.AsStream(randomAccessStream)
                        Dim img = System.Drawing.Image.FromStream(stream)
                        Me.pictureBox1.Image = img
                    End Using
                End Using
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
            Me.Enabled = True
        End Sub
    End Class

    VB.NetとC#を、それぞれWindowsFormsとWPFで書いてみました。
    GithubZipファイル。
    Windows8.1 32bitでプロジェクトを作ったので64bitだとうまくファイル参照ができないかも。その場合はProgramFiles(x86)のReference AssembliesとWindows Kitsにあるファイルを参照しなおしてみてください。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答の候補に設定 星 睦美 2015年2月4日 4:26
    • 回答としてマーク MS初心者 2015年2月5日 1:11
    2015年2月1日 12:23
  • カメラの露出調整などを設定しないと周囲の明るさによっては上手く撮影できません。

    Private Async Sub CaptureImage()
        Me.Enabled = False
        Try
    
            Dim di = DirectCast(listBox1.SelectedItem, DeviceInformation)
    
            Using mediaCapture1 As New MediaCapture()
    
                AddHandler mediaCapture1.Failed, Sub(s, errorEventArgs)
                                                     MessageBox.Show("キャプチャできませんでした:" + errorEventArgs.Message, "Error", MessageBoxButtons.OK)
                                                 End Sub
    
                Dim setting As New MediaCaptureInitializationSettings()
                setting.VideoDeviceId = di.Id 'カメラ選択
                setting.StreamingCaptureMode = StreamingCaptureMode.Video
                Await mediaCapture1.InitializeAsync(setting)
    
                'ビデオの露出などの調整がたぶん自動になっていないので自動に設定する
                Dim vcon = mediaCapture1.VideoDeviceController
                vcon.Brightness.TrySetAuto(True)
                vcon.Contrast.TrySetAuto(True)
    
                Dim pngProperties = ImageEncodingProperties.CreatePng()
                pngProperties.Width = CType(pictureBox1.Width, UInteger)
                pngProperties.Height = CType(pictureBox1.Height, UInteger)
    
                Using randomAccessStream As New InMemoryRandomAccessStream()
    
                    Await mediaCapture1.CapturePhotoToStreamAsync(pngProperties, randomAccessStream)
    
                    randomAccessStream.Seek(0)
    
                    'ビットマップにして表示
                    Dim stream = System.IO.WindowsRuntimeStreamExtensions.AsStream(randomAccessStream)
                    Dim img = System.Drawing.Image.FromStream(stream)
                    Me.pictureBox1.Image = img
                End Using
            End Using
    
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        Me.Enabled = True
    End Sub

    WindowsRTのライブラリでのカメラ制御なので
    https://msdn.microsoft.com/ja-jp/library/windows/hardware/dn265153.aspx
    のカメラオプションあたりを参考にしてください。
    それでもわからない場合はキーワードをいろいろ変えて検索してみるしかないです。

    最初に質問した内容が解決したなら放置せずに、解決となるのに役立った返信に回答マークをつけましょう。いくつでもつけられます。
    質問の内容が当初の内容から変わってきたら判り易いタイトルの新規の質問にしましょう。後で同じ悩みの人が探しやすくなります。

    #名前の後ろの(MVP)は勝手につく所属名のようなものなので不要です。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク MS初心者 2015年2月5日 1:10
    2015年2月4日 15:18

すべての返信

  • 通常の方法ということであれば、DirectShowを使用するかOpenCV等を利用して取り込むことになると思います。

    DirectShow for Visual Basic

    http://msdn.microsoft.com/ja-jp/library/dd188521.aspx

    また、Multimedia Control(MCI)というWin32APIもありますが、ちょっと自分は最近使ってなく思い出せないので参考までに。

    2015年1月19日 1:18
  • CryEarth tomoyuki sasaki 様

    ありがとうございます。

    http://msdn.microsoft.com/ja-jp/library/dd188521.aspxを参照したのですが、良く分かりません。

    ダウンロードの必要があるみたいですが、何をどうすべきか、良く分かりません。

    出来れば、方法を教えていただければ助かるのですが。

    2015年1月19日 2:02
  • 申し訳ありませんDirectShowはDirectX SDK ではなくWindows SDKに移動しています。

    ダウンロードは"WindowsR Server 2003 SP1 Platform SDK Full Download"「http://www.microsoft.com/downloads/en/details.aspx?FamilyID=EBA0128F-A770-45F1-86F3-7AB010B398A3」から行えるのですが、導入方法が特殊です。

    コマンドプロンプトの使用方法などがわからない場合は、お勧めできなので、申し訳ありませんが私の書き込みを忘れてください。

    英語でですが、DirectShow.NET を使用したWPFでのCapture方法を見つけましたので、これではいかがでしょうか?

    http://www.codeproject.com/Articles/18511/Webcam-using-DirectShow-NET

    2015年1月19日 4:46
  • 初めから参照の追加ダイアログには「ActiveMovie control type library」が含まれています。何をダウンロードしたいのか把握できていますか?

    # DirectShowを使う方法が適切なのかについてはちょっと私には判断できません。

    2015年1月19日 5:21
  • 佐祐理様

    いろいと調べていたのですが、結果的には出来ませんでした。

    ActiveMovie control type libraryで使用可能なのでしょうか。

    具体的な方法をお教え下さい。

    2015年1月30日 1:09
  • WindowsFormからWinRTのdllを呼んでカメラ撮影できます。
    http://blogs.msdn.com/b/eternalcoding/archive/2013/10/29/how-to-use-specific-winrt-api-from-desktop-apps-capturing-a-photo-using-your-webcam-into-a-wpf-app.aspx
    を参考にしました。

    • TargetPlatformVersionを設定してWinRTのdllを使用することを宣言
    • System.Runtime.WindowsRuntime.dll
    • System.Runtime.dll
    • System.Runtime.InteropServices.WindowsRuntime.dll
    • System.Threading.Tasks.dll
    • System.IO.dll
    • Windows.winmd

    などの参照を追加するとWindows.Media.Captureを使用してのカメラ撮影が行えました。

    Imports Windows.Devices.Enumeration
    Imports Windows.Media.Capture
    Imports Windows.Media.MediaProperties
    Imports Windows.Storage.Streams
    
    Public Class Form1
    
        Dim pictureBox1 As PictureBox
        Dim listBox1 As ListBox
    
        Sub New()
            InitializeComponent()
    
            ' InitializeComponent() 呼び出しの後で初期化を追加します。
            Me.Width = 600
            Me.Height = 600
    
            Dim panel1 = New System.Windows.Forms.Panel()
            panel1.Width = 100
            panel1.Dock = DockStyle.Left
            Me.Controls.Add(panel1)
    
            Dim label1 = New Label()
            label1.Text = "カメラ一覧"
            panel1.Controls.Add(label1)
    
            listBox1 = New ListBox()
            listBox1.Width = 100
            listBox1.Top = label1.Height
            listBox1.DisplayMember = "Name"
            AddHandler listBox1.SelectedIndexChanged, Sub(s, e)
                                                          CaptureImage()
                                                      End Sub
            panel1.Controls.Add(listBox1)
    
            Dim button1 = New Button()
            button1.Text = "Capture"
            button1.Top = listBox1.Top + listBox1.Height + 5
            button1.AutoSize = True
            AddHandler button1.Click, Sub(s, e)
                                          CaptureImage()
                                      End Sub
            panel1.Controls.Add(button1)
    
            pictureBox1 = New PictureBox()
            pictureBox1.Dock = DockStyle.Fill
            pictureBox1.BackColor = Color.White
            Me.Controls.Add(pictureBox1)
    
            AddHandler Me.Shown, AddressOf Form1_Shown
        End Sub
    
        Private Async Sub Form1_Shown(sender As Object, e As EventArgs)
            '利用可能なビデオデバイス(カメラ)を探す
            Dim devices = Await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(DeviceClass.VideoCapture)
            If (devices.Count = 0) Then
    
                MessageBox.Show("カメラが見つかりませんでした", "Error", MessageBoxButtons.OK)
                Return
            End If
            Me.listBox1.DataSource = devices.ToArray()
    
        End Sub
    
    
        Private Async Sub CaptureImage()
            Me.Enabled = False
            Try
    
                Dim di = DirectCast(listBox1.SelectedItem, DeviceInformation)
    
                Using mediaCapture1 As New MediaCapture()
    
                    AddHandler mediaCapture1.Failed, Sub(s, errorEventArgs)
                                                         MessageBox.Show("キャプチャできませんでした:" + errorEventArgs.Message, "Error", MessageBoxButtons.OK)
                                                     End Sub
    
                    Dim setting As New MediaCaptureInitializationSettings()
                    setting.VideoDeviceId = di.Id 'カメラ選択
                    setting.StreamingCaptureMode = StreamingCaptureMode.Video
                    Await mediaCapture1.InitializeAsync(setting)
    
                    Dim pngProperties = ImageEncodingProperties.CreatePng()
                    pngProperties.Width = CType(pictureBox1.Width, UInteger)
                    pngProperties.Height = CType(pictureBox1.Height, UInteger)
    
                    Using randomAccessStream As New InMemoryRandomAccessStream()
    
                        Await mediaCapture1.CapturePhotoToStreamAsync(pngProperties, randomAccessStream)
    
                        randomAccessStream.Seek(0)
    
                        'ビットマップにして表示
                        Dim stream = System.IO.WindowsRuntimeStreamExtensions.AsStream(randomAccessStream)
                        Dim img = System.Drawing.Image.FromStream(stream)
                        Me.pictureBox1.Image = img
                    End Using
                End Using
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
            Me.Enabled = True
        End Sub
    End Class

    VB.NetとC#を、それぞれWindowsFormsとWPFで書いてみました。
    GithubZipファイル。
    Windows8.1 32bitでプロジェクトを作ったので64bitだとうまくファイル参照ができないかも。その場合はProgramFiles(x86)のReference AssembliesとWindows Kitsにあるファイルを参照しなおしてみてください。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答の候補に設定 星 睦美 2015年2月4日 4:26
    • 回答としてマーク MS初心者 2015年2月5日 1:11
    2015年2月1日 12:23
  • gekka(MVP)様

    ありがとうございます。

    下記の3点でエラーとなります。

    Dim devices = Await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(DeviceClass.VideoCapture)
    Await mediaCapture1.InitializeAsync(setting)
    Await mediaCapture1.CapturePhotoToStreamAsync(pngProperties, randomAccessStream)

    待機可能ではありません、と。

    何か宣言、やり方が間違っているのでしょうか?


    2015年2月2日 2:31
  • 必要なdllが正しく参照ができていないとそのエラーが出ます。

    GithubZipにあるプロジェクトでそのエラーが出るのでしょうか?
    その場合はプロジェクトの参照で失敗している参照がないか確認して環境に合わせて訂正してください。

    プロジェクトを使っていないなら、先のレスの頭に記述してあるdllとwinmdをすべて参照に追加してください。
    まずはzipファイルのプロジェクトで動作確認することを推奨します。

    #64bit環境でも正常にビルドが通ることは確認できた


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 編集済み gekkaMVP 2015年2月2日 3:48
    2015年2月2日 3:48
  • gekka(MVP)様

    ZIPでは確認できました。

    参照がたりないのだと思います。

    もう少しやってみます。

    ありがとうございました。

    2015年2月2日 4:14
  • gekka(MVP)様

    なんとか出来ました。

    参照のDLLの場所が違っていたみたいです。

    今回の件とは違いますが、今回の場合のように、カメラの使用方法等はどのように見つけるのですか?

    今後の為に是非教えて下さい。

    でも本当に助かりました。

    2015年2月2日 5:05
  • gekka(MVP)様

    何度もすみません。表示等は出来たのですが、暗くて光ってる物しか表示されません。ライト等。

    もっときれいに表示の方法はあるのですか。

    調べたのですが、やはり分かりませんでした。

    ドライバはOV2722ですが、ドライバの問題なのか表示の方法が悪いのか。

    ただし、Xamlでは表示されます。

    2015年2月4日 2:00
  • カメラの露出調整などを設定しないと周囲の明るさによっては上手く撮影できません。

    Private Async Sub CaptureImage()
        Me.Enabled = False
        Try
    
            Dim di = DirectCast(listBox1.SelectedItem, DeviceInformation)
    
            Using mediaCapture1 As New MediaCapture()
    
                AddHandler mediaCapture1.Failed, Sub(s, errorEventArgs)
                                                     MessageBox.Show("キャプチャできませんでした:" + errorEventArgs.Message, "Error", MessageBoxButtons.OK)
                                                 End Sub
    
                Dim setting As New MediaCaptureInitializationSettings()
                setting.VideoDeviceId = di.Id 'カメラ選択
                setting.StreamingCaptureMode = StreamingCaptureMode.Video
                Await mediaCapture1.InitializeAsync(setting)
    
                'ビデオの露出などの調整がたぶん自動になっていないので自動に設定する
                Dim vcon = mediaCapture1.VideoDeviceController
                vcon.Brightness.TrySetAuto(True)
                vcon.Contrast.TrySetAuto(True)
    
                Dim pngProperties = ImageEncodingProperties.CreatePng()
                pngProperties.Width = CType(pictureBox1.Width, UInteger)
                pngProperties.Height = CType(pictureBox1.Height, UInteger)
    
                Using randomAccessStream As New InMemoryRandomAccessStream()
    
                    Await mediaCapture1.CapturePhotoToStreamAsync(pngProperties, randomAccessStream)
    
                    randomAccessStream.Seek(0)
    
                    'ビットマップにして表示
                    Dim stream = System.IO.WindowsRuntimeStreamExtensions.AsStream(randomAccessStream)
                    Dim img = System.Drawing.Image.FromStream(stream)
                    Me.pictureBox1.Image = img
                End Using
            End Using
    
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        Me.Enabled = True
    End Sub

    WindowsRTのライブラリでのカメラ制御なので
    https://msdn.microsoft.com/ja-jp/library/windows/hardware/dn265153.aspx
    のカメラオプションあたりを参考にしてください。
    それでもわからない場合はキーワードをいろいろ変えて検索してみるしかないです。

    最初に質問した内容が解決したなら放置せずに、解決となるのに役立った返信に回答マークをつけましょう。いくつでもつけられます。
    質問の内容が当初の内容から変わってきたら判り易いタイトルの新規の質問にしましょう。後で同じ悩みの人が探しやすくなります。

    #名前の後ろの(MVP)は勝手につく所属名のようなものなので不要です。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク MS初心者 2015年2月5日 1:10
    2015年2月4日 15:18
  • gekka様

    いろいろありがとうございました。

    設定をいろいろ試してやってみます。

    それと、諸々の注意、気をつけます。

    2015年2月5日 1:10
  • gekka様

    何度もすみません。

    >ビデオの露出などの調整がたぶん自動になっていないので自動に設定する
    >Dim vcon = mediaCapture1.VideoDeviceController
    >vcon
    .Brightness.TrySetAuto(True)
    >vcon
    .Contrast.TrySetAuto(True)

    とか、設定を自動以外で自分で設定しても何も変わりませんでした。

    動画として表示し、撮影はできないのでしょうか。

    >WindowsRTのライブラリでのカメラ制御なので
    >https://msdn.microsoft.com/ja-jp/library/windows/hardware/dn265153.aspx
    >のカメラオプションあたりを参考にしてください。

    参考にしたのですが、良く分かりませんでした。

    教えていただけると助かります。

    2015年2月13日 4:03