カメラ映像を表示するには

解決


VB&.net初心者  2010-12-08 23:07:02  No: 147252

違うVB2-6専用掲示板に書いてしまったので、こちらでもう一度お願いします。

キャプチャーボードを使用して、カメラのライブ映像を画面に表示させたいのですが上手くいきません。

DirectShow.NETを使用するを教えてもらい、とりあえず「DirectShowLib-2005.dll」ダウンロードして参照しただけで、この後が分かりません。
どんな手順でキャプチャーボードにアクセスすればいいのでしょうか。

それと、graphedt.exeを使って映像が出るのかやってみましたが出ませんでした。(付属ソフトでは画像が表示されています。)
何か環境が悪いのでしょうか?

環境は
WIN7
VS2010

よろしくお願いします。


オショウ  2010-12-09 04:20:48  No: 147253

キャプチャボードとは、どこのメーカーの型式は何?
付属ソフトは、ボード特有の機能を使っている場合もありますが
OSが認識できる一般的な方法では・・・

Video for Windows
や、
TWAIN

にてアクセスし画像を取得できます。

上記機能を使って画像を表示するソフトウェアは検索すれば
いろいろありますし、.NETでもサンプルは見つかるはずです

OSが標準的に認識しているのであればVideo for Windows
でも撮れますので、当然、DirectShowでも撮れます。

※  私は昔、そうやって作りました・・・

以上。参考まで


YAS  2010-12-11 17:04:28  No: 147254

VideoCaptureSourcesを検索し,最初に見つけたデバイスの映像をフォームに表示するサンプルです。
(DirectShowLib-2005.Dllを参照設定してください。)
デバイスの出力ピンを検索し,最初に見つけた出力ピンをレンダリングしているので,デバイスのピンの構成によっては映像が表示されません。その時は
comOutPin = DsFindPin.ByDirection(DirectCast(CameraFilter, IBaseFilter), PinDirection.Output, 0)
の最後の「0」を1や2などに変えてみてください。

Option Explicit On
Option Strict On

Imports DirectShowLib
Imports System.Runtime.InteropServices

Public Class Form1

    Dim comGraph As New FilterGraph

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.SetupGraph()
        Me.SetupVideoWindow(Me.Handle)
        DirectCast(Me.comGraph, IMediaControl).Run()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        DirectCast(Me.comGraph, IMediaControl).Stop()
        If Me.comGraph IsNot Nothing Then
            Marshal.ReleaseComObject(Me.comGraph)
            Me.comGraph = Nothing
        End If
    End Sub

    Private Sub SetupGraph()
        Dim CameraDevice As DsDevice = Nothing
        Dim CameraFilter As IBaseFilter = Nothing
        CameraDevice = GetCameraDevice()
        If CameraDevice Is Nothing Then
            Throw New Exception("カメラが接続されていません。")
        End If
        CameraFilter = GetCameraFilter(CameraDevice)
        DirectCast(Me.comGraph, IGraphBuilder).AddFilter(CameraFilter, "Camera")
        Dim comOutPin As IPin = Nothing
        Try
            comOutPin = DsFindPin.ByDirection(DirectCast(CameraFilter, IBaseFilter), PinDirection.Output, 0)
            DirectCast(Me.comGraph, IGraphBuilder).Render(comOutPin)
        Finally
            If comOutPin IsNot Nothing Then
                Marshal.ReleaseComObject(comOutPin)
                comOutPin = Nothing
            End If
        End Try
    End Sub

    Private Sub SetupVideoWindow(ByVal hwnd As IntPtr)
        With DirectCast(Me.comGraph, IVideoWindow)
            .put_Owner(hwnd)
            .put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipSiblings Or WindowStyle.ClipChildren)
            .SetWindowPosition(0, 0, Me.ClientSize.Width, Me.ClientSize.Height)
        End With
    End Sub

    Private Function GetCameraDevice() As DsDevice
        Dim Devices() As DsDevice = Nothing
        Dim Device As DsDevice = Nothing
        Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
        If Devices.Length > 0 Then
            Device = Devices(0)
        Else
            Device = Nothing
        End If
        Return Device
    End Function

    Private Function GetCameraFilter(ByVal Device As DsDevice) As IBaseFilter
        Dim CameraFilter As Object = Nothing
        Device.Mon.BindToObject(Nothing, Nothing, GetType(IBaseFilter).GUID, CameraFilter)
        Return DirectCast(CameraFilter, IBaseFilter)
    End Function

End Class


VB&.net初心者  2010-12-12 03:43:50  No: 147255

オショウさん、YASさん ありがとうございます。
YASさんのソースで、表示はできましたが映像がコマ落ち状態でした。
付属のサンプルを動かすとFormat型式(60i、30p...)を選択するようなメニューがありましたので、どうやらその辺を作らないといけない事まで分かりました。
もう少しソースを追っかけた見ます。


YAS  2010-12-14 10:31:59  No: 147256

推奨フォーマットを取得し,ListBoxに列挙し,選択したフォーマットに設定するサンプルです。
COMの解放のあたりはこれでいいのか自信がなく,適当です。
参考程度にしてください。

Option Explicit On
Option Strict On

Imports DirectShowLib
Imports System.Runtime.InteropServices

Public Class Form1

    Dim comGraph As New FilterGraph

    Private Structure CameraSetting
        Dim Width As Integer
        Dim Height As Integer
        Dim AvgTimePerFrame As Long
    End Structure

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.SetupGraph()
        Me.SetupVideoWindow(Me.Handle)
        DirectCast(Me.comGraph, IMediaControl).Run()
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        DirectCast(Me.comGraph, IMediaControl).Stop()
        If Me.comGraph IsNot Nothing Then
            Marshal.ReleaseComObject(Me.comGraph)
            Me.comGraph = Nothing
        End If
    End Sub

    Private Sub SetupGraph()
        Dim CameraDevice As DsDevice = Nothing
        Dim CameraFilter As IBaseFilter = Nothing
        CameraDevice = GetCameraDevice()
        If CameraDevice Is Nothing Then
            Throw New Exception("カメラが接続されていません。")
        End If
        CameraFilter = GetCameraFilter(CameraDevice)
        DirectCast(Me.comGraph, IGraphBuilder).AddFilter(CameraFilter, "Camera")
        Dim comOutPin As IPin = Nothing
        Try
            comOutPin = DsFindPin.ByDirection(DirectCast(CameraFilter, IBaseFilter), PinDirection.Output, 0)
            SetupCameraSetting(comOutPin)
            DirectCast(Me.comGraph, IGraphBuilder).Render(comOutPin)
        Finally
            If comOutPin IsNot Nothing Then
                Marshal.ReleaseComObject(comOutPin)
                comOutPin = Nothing
            End If
        End Try
    End Sub

    Private Sub SetupVideoWindow(ByVal hwnd As IntPtr)
        With DirectCast(Me.comGraph, IVideoWindow)
            .put_Owner(hwnd)
            .put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipSiblings Or WindowStyle.ClipChildren)
            .SetWindowPosition(0, 0, Me.ClientSize.Width, Me.ClientSize.Height)
        End With
    End Sub

    Private Function GetCameraDevice() As DsDevice
        Dim Devices() As DsDevice = Nothing
        Dim Device As DsDevice = Nothing
        Devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
        If Devices.Length > 0 Then
            Device = Devices(0)
        Else
            Device = Nothing
        End If
        Return Device
    End Function

    Private Function GetCameraFilter(ByVal Device As DsDevice) As IBaseFilter
        Dim CameraFilter As Object = Nothing
        Device.Mon.BindToObject(Nothing, Nothing, GetType(IBaseFilter).GUID, CameraFilter)
        Return DirectCast(CameraFilter, IBaseFilter)
    End Function

    Private Sub SetupCameraSetting(ByVal CameraPin As IPin)
        Dim myCameraSetting As CameraSetting() = DumpCameraSetting(CameraPin)
        Dim Form2 As New Form2
        Form2.CameraSetting = myCameraSetting
        Form2.ShowDialog()
        SetupCameraOutPin(CameraPin, myCameraSetting(Form2.Index))
    End Sub

    Private Function DumpCameraSetting(ByVal CameraPin As IPin) As CameraSetting()
        Dim Config As IAMStreamConfig = DirectCast(CameraPin, IAMStreamConfig)
        Dim iCount As Integer, iSize As Integer
        Config.GetNumberOfCapabilities(iCount, iSize)
        Dim CameraSetting(iCount - 1) As CameraSetting
        Dim vih As New VideoInfoHeader
        Dim vsc As New VideoStreamConfigCaps
        Dim scc As IntPtr = Marshal.AllocHGlobal(iSize)
        Dim mt As AMMediaType = Nothing
        For i As Integer = 0 To iCount - 1
            Config.GetStreamCaps(i, mt, scc)
            Marshal.PtrToStructure(mt.formatPtr, vih)
            Marshal.PtrToStructure(scc, vsc)
            CameraSetting(i).Width = vih.BmiHeader.Width
            CameraSetting(i).Height = vih.BmiHeader.Height
            CameraSetting(i).AvgTimePerFrame = vih.AvgTimePerFrame
            Debug.Print("{0} x {1} Min:{2:0.00}fps Max:{3:0.00}fps", vih.BmiHeader.Width, vih.BmiHeader.Height, 10000000 / vsc.MaxFrameInterval, 10000000 / vsc.MinFrameInterval)
            DsUtils.FreeAMMediaType(mt)
        Next
        Marshal.FreeHGlobal(scc)
        Return CameraSetting
    End Function

    Private Sub SetupCameraOutPin(ByVal CameraOut As IPin, ByVal CameraSetting As CameraSetting)
        Dim Config As IAMStreamConfig = DirectCast(CameraOut, IAMStreamConfig)
        Dim mt As AMMediaType = New AMMediaType
        Dim vih As VideoInfoHeader = New VideoInfoHeader
        Config.GetFormat(mt)
        Marshal.PtrToStructure(mt.formatPtr, vih)
        vih.BmiHeader.Width = CameraSetting.Width
        vih.BmiHeader.Height = CameraSetting.Height
        vih.AvgTimePerFrame = CameraSetting.AvgTimePerFrame
        Marshal.StructureToPtr(vih, mt.formatPtr, True)
        Config.SetFormat(mt)
        DsUtils.FreeAMMediaType(mt)
    End Sub

    Private Class Form2
        Inherits Form

        Dim ListBox1 As New ListBox
        Dim WithEvents Button1 As New Button

        Public Property CameraSetting As CameraSetting()
        Public Property Index As Integer = -1

        Private Sub Form2_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            If Me._Index < 0 Then
                e.Cancel = True
            End If
        End Sub

        Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Me.ListBox1.ItemHeight = 12
            Me.ListBox1.Location = New Point(14, 33)
            Me.ListBox1.Size = New Size(247, 76)
            Me.ListBox1.TabIndex = 2
            Me.Button1.Size = New Size(67, 21)
            Me.Button1.Location = New Point(194, 110)
            Me.Button1.Text = "OK"
            Me.Text = "カメラの設定を選択してください"
            Me.ClientSize = New Size(275, 140)
            Me.Controls.AddRange({ListBox1, Button1})
            For i As Integer = 0 To Me._CameraSetting.Length - 1
                With Me._CameraSetting(i)
                    ListBox1.Items.Add(String.Format("{0} x {1} {2:0.00}fps", .Width, .Height, 10000000 / .AvgTimePerFrame))
                End With
            Next
        End Sub

        Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
            Me._Index = Me.ListBox1.SelectedIndex
            If Me._Index >= 0 Then
                Me.Close()
            End If
        End Sub

    End Class

End Class


VB&.net初心者  2010-12-16 03:06:19  No: 147257

YASさん、ありがとうございます。
メニュー一覧が出る様になりました。
なぜか、メニュー項目に60fpsや59.94fpsがありませんでした。
そこで、VideoInfoHeaderをVideoInfoHeader2にしてみたら59.94fpsの項目が表示されました。
VideoInfoHeaderとVideoInfoHeader2の違いは分かりませんが、コマ落ちは少し解消されたような気がします。
でも依然としてコマ落ち状態です。
もしかして、コマ落ちの原因がメニュー選択だけでは無く他にも有るのでしょうか。
ひき続き、ソースを追っかけてみます。


VB&.net初心者  2011-03-04 21:35:19  No: 147258

解決するの忘れていました。
コマ落ちは再起動で直りました。
返事が遅れてすみませんでした。
ご教授頂いた方々ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加