違うVB2-6専用掲示板に書いてしまったので、こちらでもう一度お願いします。
キャプチャーボードを使用して、カメラのライブ映像を画面に表示させたいのですが上手くいきません。
DirectShow.NETを使用するを教えてもらい、とりあえず「DirectShowLib-2005.dll」ダウンロードして参照しただけで、この後が分かりません。
どんな手順でキャプチャーボードにアクセスすればいいのでしょうか。
それと、graphedt.exeを使って映像が出るのかやってみましたが出ませんでした。(付属ソフトでは画像が表示されています。)
何か環境が悪いのでしょうか?
環境は
WIN7
VS2010
よろしくお願いします。
キャプチャボードとは、どこのメーカーの型式は何?
付属ソフトは、ボード特有の機能を使っている場合もありますが
OSが認識できる一般的な方法では・・・
Video for Windows
や、
TWAIN
にてアクセスし画像を取得できます。
上記機能を使って画像を表示するソフトウェアは検索すれば
いろいろありますし、.NETでもサンプルは見つかるはずです
OSが標準的に認識しているのであればVideo for Windows
でも撮れますので、当然、DirectShowでも撮れます。
※ 私は昔、そうやって作りました・・・
以上。参考まで
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
オショウさん、YASさん ありがとうございます。
YASさんのソースで、表示はできましたが映像がコマ落ち状態でした。
付属のサンプルを動かすとFormat型式(60i、30p...)を選択するようなメニューがありましたので、どうやらその辺を作らないといけない事まで分かりました。
もう少しソースを追っかけた見ます。
推奨フォーマットを取得し,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
YASさん、ありがとうございます。
メニュー一覧が出る様になりました。
なぜか、メニュー項目に60fpsや59.94fpsがありませんでした。
そこで、VideoInfoHeaderをVideoInfoHeader2にしてみたら59.94fpsの項目が表示されました。
VideoInfoHeaderとVideoInfoHeader2の違いは分かりませんが、コマ落ちは少し解消されたような気がします。
でも依然としてコマ落ち状態です。
もしかして、コマ落ちの原因がメニュー選択だけでは無く他にも有るのでしょうか。
ひき続き、ソースを追っかけてみます。
解決するの忘れていました。
コマ落ちは再起動で直りました。
返事が遅れてすみませんでした。
ご教授頂いた方々ありがとうございました。