none
webカメラのシャッターボタンでイメージを保存したい RRS feed

  • 質問

  •  

    いつもお世話になっております。

     

    web(usb)カメラの映像を表示して、作成したアプリの画面上のボタン押下でイメージを表示・静止画保存することは出来たのですが、カメラにシャッターボタンが付いており、このボタン押下でイメージの静止画保存出来ないものかと考えております。

     

    カメラ付属のアプリケーションでは画像を表示し、ボタン押下でキャプチャできますのでこれと同じようなことがVBで出来ないものかと考えております。

     

    これを実現するにはどのようにすれば良いかご存知の方ご教授いただけないでしょうか。

     

    カメラ機器に依存するのかとも思いますが、エクスプローラで「カメラとスキャナ」にあるカメラデバイスをクリックするとカメラの画像が表示され、またカメラのシャッターボタンを押下でキャプチャ出来ていることから汎用的な機能で同様に出来るのではと考えております。

     

    現状、WEBカメラの表示については幾つかサイトを見て回ってサンプルを元に作成したぐらいの知識のみでございます。

    DirectShowではなくVFWでの実装かと思われます。

     

    何卒宜しくお願いいたします。

     

    環境ですが、

    OS:XPProSp2

    言語:VB.Net2005

    Webカメラ:ロジクール V-UBC40(?)、付属アプリはQuickCaptureで参照できております

    を使用しております。

     

    2008年8月29日 6:01

回答

  • 前回投稿したことをやってみました。結論から言うとできました。

    DirectShow.NET Libを使いました。

    http://directshownet.sourceforge.net/

     

    サンプルコードです。エラー処理は何もしていませんので注意してください。

     

    Imports DirectShowLib
    Imports System.Runtime.InteropServices

    Public Class Form1
        Implements ISampleGrabberCB

        Const S_OK As Integer = &H0
        Private comFilterGraph As IFilterGraph2
        Private comSampleGrabber As ISampleGrabber
        Private Buffer() As Byte
        Private SynchronizingObject As System.ComponentModel.ISynchronizeInvoke
        Delegate Sub CaptureDoneDelegate()

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim comCamera As IBaseFilter
            Dim comSampleGrabberIn As IPin
            Dim comStillOut As IPin
            Dim comCaptureOut As IPin
            Dim objCamera As Object = Nothing
            Dim Devices() As DsDevice
            Me.SynchronizingObject = Me
            Me.comFilterGraph = DirectCast(New FilterGraph, IFilterGraph2)
            'カメラフィルタの追加
            Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
            Devices(0).Mon.BindToObject(Nothing, Nothing, GetType(IBaseFilter).GUID, objCamera)
            comCamera = DirectCast(objCamera, IBaseFilter)
            Me.comFilterGraph.AddFilter(comCamera, "Camera")
            'キャプチャピンのレンダリング
            comCaptureOut = DsFindPin.ByCategory(comCamera, PinCategory.Capture, 0)
            Me.comFilterGraph.Render(comCaptureOut)
            'SampleGrabberの追加
            Me.comSampleGrabber = DirectCast(New SampleGrabber, ISampleGrabber)
            Me.comFilterGraph.AddFilter(DirectCast(comSampleGrabber, IBaseFilter), "SampleGrabber")
            'SampleGrabberの設定
            Dim Media As New AMMediaType
            Media.majorType = MediaType.Video
            Media.subType = MediaSubType.RGB24
            Media.formatType = FormatType.VideoInfo
            Me.comSampleGrabber.SetMediaType(Media)
            DsUtils.FreeAMMediaType(Media)
            Me.comSampleGrabber.SetBufferSamples(False)
            Me.comSampleGrabber.SetOneShot(False)
            Me.comSampleGrabber.SetCallback(Me, 1)
            'カメラの静止画ピンとSampleGrabberの接続
            comStillOut = DsFindPin.ByCategory(comCamera, PinCategory.Still, 0)
            comSampleGrabberIn = DsFindPin.ByDirection(comSampleGrabber, PinDirection.Input, 0)
            Me.comFilterGraph.Connect(comStillOut, comSampleGrabberIn)
            'シャッターボタンを有効にする
            DirectCast(comCamera, IAMVideoControl).SetMode(comStillOut, VideoControlFlags.ExternalTriggerEnable)
            'グラフの実行
            DirectCast(Me.comFilterGraph, IMediaControl).Run()
        End Sub

        Private Sub Byte2Bitmap()
            Dim VideoInfoHeader As VideoInfoHeader
            Dim Media As New AMMediaType
            comSampleGrabber.GetConnectedMediaType(Media)
            VideoInfoHeader = Marshal.PtrToStructure(Media.formatPtr, GetType(VideoInfoHeader))
            DsUtils.FreeAMMediaType(Media)
            Dim Width As Integer = VideoInfoHeader.BmiHeader.Width
            Dim Height As Integer = VideoInfoHeader.BmiHeader.Height
            Dim Stride As Integer = VideoInfoHeader.BmiHeader.BitCount / 8 * Width
            Dim Handle As GCHandle = GCHandle.Alloc(Buffer, GCHandleType.Pinned)
            Dim Scan0 As IntPtr = CType(Handle.AddrOfPinnedObject.ToInt32 + (Height - 1) * Stride, IntPtr)
            Me.BackgroundImage = New Bitmap(Width, Height, -Stride, Imaging.PixelFormat.Format24bppRgb, Scan0)
            Handle.Free()
        End Sub

        Public Function BufferCB(ByVal SampleTime As Double, ByVal pBuffer As System.IntPtr, ByVal BufferLen As Integer) As Integer Implements DirectShowLib.ISampleGrabberCB.BufferCB
            If Me.SynchronizingObject IsNot Nothing Then
                ReDim Buffer(BufferLen)
                Marshal.Copy(pBuffer, Buffer, 0, BufferLen)
                Me.SynchronizingObject.Invoke(New CaptureDoneDelegate(AddressOf Byte2Bitmap), New Object() {})
            End If
            Return S_OK
        End Function

        Public Function SampleCB(ByVal SampleTime As Double, ByVal pSample As DirectShowLib.IMediaSample) As Integer Implements DirectShowLib.ISampleGrabberCB.SampleCB
        End Function

    End Class

    2008年9月1日 16:11

すべての返信

  • ロジクールさんのほうでWebカメラを制御するSDKを提供しているかどうかがポイントとなります。

    画像の保存そのものはできるようですから、.NETベースから利用できるライブラリが提供されているのでしょう。
    SDKにシャッターを押したときのイベントを取得方法があるのではないでしょうか?

    2008年8月29日 6:24
  • GX999様

    回答いただきまことにありがとうございます。

    返答遅くなり申し訳ございません。

     

     GX999 さんからの引用
    ロジクールさんのほうでWebカメラを制御するSDKを提供しているかどうかがポイントとなります。

     

    そうですね、、ロジクールからSDK等があれば良いのですがサイトを見たところそれらしい情報はなさそうではあります。。

     

    付属のCDから何か掴めないかもう少し調査してみます。

    サイトのページからはQcamR E 2500というのが似たような形をしています。。

     

    また何か情報ありましたらよろしくお願いいたします。

     

     


     

    2008年9月1日 14:12
  • DirectShowでキャプチャグラフを作成し,IAMVideoControlインターフェイスを使えばシャッターボタンを有効にできるのでは?

     

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

     

    試していませんので,確証はありませんが。

    2008年9月1日 14:49
  • 前回投稿したことをやってみました。結論から言うとできました。

    DirectShow.NET Libを使いました。

    http://directshownet.sourceforge.net/

     

    サンプルコードです。エラー処理は何もしていませんので注意してください。

     

    Imports DirectShowLib
    Imports System.Runtime.InteropServices

    Public Class Form1
        Implements ISampleGrabberCB

        Const S_OK As Integer = &H0
        Private comFilterGraph As IFilterGraph2
        Private comSampleGrabber As ISampleGrabber
        Private Buffer() As Byte
        Private SynchronizingObject As System.ComponentModel.ISynchronizeInvoke
        Delegate Sub CaptureDoneDelegate()

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim comCamera As IBaseFilter
            Dim comSampleGrabberIn As IPin
            Dim comStillOut As IPin
            Dim comCaptureOut As IPin
            Dim objCamera As Object = Nothing
            Dim Devices() As DsDevice
            Me.SynchronizingObject = Me
            Me.comFilterGraph = DirectCast(New FilterGraph, IFilterGraph2)
            'カメラフィルタの追加
            Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
            Devices(0).Mon.BindToObject(Nothing, Nothing, GetType(IBaseFilter).GUID, objCamera)
            comCamera = DirectCast(objCamera, IBaseFilter)
            Me.comFilterGraph.AddFilter(comCamera, "Camera")
            'キャプチャピンのレンダリング
            comCaptureOut = DsFindPin.ByCategory(comCamera, PinCategory.Capture, 0)
            Me.comFilterGraph.Render(comCaptureOut)
            'SampleGrabberの追加
            Me.comSampleGrabber = DirectCast(New SampleGrabber, ISampleGrabber)
            Me.comFilterGraph.AddFilter(DirectCast(comSampleGrabber, IBaseFilter), "SampleGrabber")
            'SampleGrabberの設定
            Dim Media As New AMMediaType
            Media.majorType = MediaType.Video
            Media.subType = MediaSubType.RGB24
            Media.formatType = FormatType.VideoInfo
            Me.comSampleGrabber.SetMediaType(Media)
            DsUtils.FreeAMMediaType(Media)
            Me.comSampleGrabber.SetBufferSamples(False)
            Me.comSampleGrabber.SetOneShot(False)
            Me.comSampleGrabber.SetCallback(Me, 1)
            'カメラの静止画ピンとSampleGrabberの接続
            comStillOut = DsFindPin.ByCategory(comCamera, PinCategory.Still, 0)
            comSampleGrabberIn = DsFindPin.ByDirection(comSampleGrabber, PinDirection.Input, 0)
            Me.comFilterGraph.Connect(comStillOut, comSampleGrabberIn)
            'シャッターボタンを有効にする
            DirectCast(comCamera, IAMVideoControl).SetMode(comStillOut, VideoControlFlags.ExternalTriggerEnable)
            'グラフの実行
            DirectCast(Me.comFilterGraph, IMediaControl).Run()
        End Sub

        Private Sub Byte2Bitmap()
            Dim VideoInfoHeader As VideoInfoHeader
            Dim Media As New AMMediaType
            comSampleGrabber.GetConnectedMediaType(Media)
            VideoInfoHeader = Marshal.PtrToStructure(Media.formatPtr, GetType(VideoInfoHeader))
            DsUtils.FreeAMMediaType(Media)
            Dim Width As Integer = VideoInfoHeader.BmiHeader.Width
            Dim Height As Integer = VideoInfoHeader.BmiHeader.Height
            Dim Stride As Integer = VideoInfoHeader.BmiHeader.BitCount / 8 * Width
            Dim Handle As GCHandle = GCHandle.Alloc(Buffer, GCHandleType.Pinned)
            Dim Scan0 As IntPtr = CType(Handle.AddrOfPinnedObject.ToInt32 + (Height - 1) * Stride, IntPtr)
            Me.BackgroundImage = New Bitmap(Width, Height, -Stride, Imaging.PixelFormat.Format24bppRgb, Scan0)
            Handle.Free()
        End Sub

        Public Function BufferCB(ByVal SampleTime As Double, ByVal pBuffer As System.IntPtr, ByVal BufferLen As Integer) As Integer Implements DirectShowLib.ISampleGrabberCB.BufferCB
            If Me.SynchronizingObject IsNot Nothing Then
                ReDim Buffer(BufferLen)
                Marshal.Copy(pBuffer, Buffer, 0, BufferLen)
                Me.SynchronizingObject.Invoke(New CaptureDoneDelegate(AddressOf Byte2Bitmap), New Object() {})
            End If
            Return S_OK
        End Function

        Public Function SampleCB(ByVal SampleTime As Double, ByVal pSample As DirectShowLib.IMediaSample) As Integer Implements DirectShowLib.ISampleGrabberCB.SampleCB
        End Function

    End Class

    2008年9月1日 16:11
  •  

    YAS.s様

    回答いただきありがとうございます。

    返答遅れまして誠に申し訳ございません。。

     

     YAS.s さんからの引用

    前回投稿したことをやってみました。結論から言うとできました。

    DirectShow.NET Libを使いました。

    http://directshownet.sourceforge.net/

     

     

    おお、すばらしい。GJです!

    上記コードで実現できました。ありがとうございました。

     

    こちらをベースに組込んでみようと思います。

    とりあえずは、、

     

    'フォームのピクチャーボックスを親コントロールにしてその上にイメージを表示
    DirectCast(Me.comFilterGraph, IVideoWindow).put_Owner(PictureBox1.Handle)
    DirectCast(Me.comFilterGraph, IVideoWindow).put_WindowStyle(WindowStyle.Child)
    DirectCast(Me.comFilterGraph, IVideoWindow).SetWindowPosition(0, 0, PictureBox1.Width, PictureBox1.Height)


    な形でフォームに組み込んで見たり、ファイルに保存したりするようにしてみます。

     

    2008年9月3日 8:55