|
-
Jun 12th, 2018, 07:58 AM
#1
Webcam control via .NET
Hey all, I'm working on an interesting project for our shop floor.
Basically, line operator puts a box into a loading station that has a webcam pointed down into it. Operator fills the box with an order. Operator then scans the barcode at the top of his sales order. Program then takes sales order, snaps some stills of the box with the webcam, and saves the data to a database.
I have not even started looking for a webcam control library yet (I'm betting there are a couple out there on CodeProject and/or StackOverflow; maybe even on here) but I was wondering if anyone else has had to use .NET to control or just take stills from a webcam before and what you used. I want to know if there's some "popular library" out there others have used.
Thanks in advance!
-
Jun 12th, 2018, 08:24 AM
#2
Re: Webcam control via .NET
I remember using media player back on windows 7. But that was a long time ago.
https://github.com/Microsoft/Windows.../SimpleCapture
-
Jun 12th, 2018, 09:00 AM
#3
Re: Webcam control via .NET
Huh, thanks, I'll check that out and see if it still works. Could save me a lot of headache
Trying to figure out Windows Image Acquisition (WIA) now.
-
Jun 12th, 2018, 12:06 PM
#4
Re: Webcam control via .NET
below is a class taken out of a project of mine that does a stream webcam capture using API.
if you wanna take a still image, i recall that you can use some other WM_CAP message to get that in better quality than stream, but i guess at least the api declarations should be helpful.
Code:
Imports System.Runtime.InteropServices
Imports System.Threading
Public Class WebCam
Implements PicProcessor.IPicProvider
#Region "API Stuff"
Private Declare Auto Function SendMessage _
Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal wMsg As Int32, ByVal wParam As IntPtr, _
ByVal lParam As IntPtr) As IntPtr
Private Declare Auto Function capCreateCaptureWindow _
Lib "avicap32.dll" (ByVal lpszWindowName As String, ByVal dwStyle As Int32, ByVal x As Int32, _
ByVal y As Int32, ByVal nWidth As Int32, ByVal nHeight As Int32, ByVal hWndParent As IntPtr, _
ByVal nID As Int32) As IntPtr
Private Declare Function DestroyWindow _
Lib "user32.dll" (ByVal hWnd As IntPtr) As Int32
<StructLayout(LayoutKind.Sequential)> _
Private Structure VIDEOHDR
Public lpData As IntPtr
Public dwBufferLength As Int32
Public dwBytesUsed As Int32
Public dwTimeCaptured As Int32
Public dwUser As Int32
Public dwFlags As Int32
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> Public dwReserved() As Int32
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure CAPTUREPARMS
Public dwRequestMicroSecPerFrame As Int32
Public fMakeUserHitOKToCapture As Int32
Public wPercentDropForError As Int32
Public fYield As Int32
Public dwIndexSize As Int32
Public wChunkGranularity As Int32
Public fUsingDOSMemory As Int32
Public wNumVideoRequested As Int32
Public fCaptureAudio As Int32
Public wNumAudioRequested As Int32
Public vKeyAbort As Int32
Public fAbortLeftMouse As Int32
Public fAbortRightMouse As Int32
Public fLimitEnabled As Int32
Public wTimeLimit As Int32
Public fMCIControl As Int32
Public fStepMCIDevice As Int32
Public dwMCIStartTime As Int32
Public dwMCIStopTime As Int32
Public fStepCaptureAt2x As Int32
Public wStepCaptureAverageFrames As Int32
Public dwAudioBufferSize As Int32
Public fDisableWriteCache As Int32
Public AVStreamMaster As Int32
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure BITMAPINFO
Public bmiHeader As BITMAPINFOHEADER
Public bmiColors() As RGBQUAD
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure BITMAPINFOHEADER
Public biSize As Int32
Public biWidth As Int32
Public biHeight As Int32
Public biPlanes As Int16
Public biBitCount As Int16
Public biCompression As Int32
Public biSizeImage As Int32
Public biXPelsPerMeter As Int16
Public biYPelsPerMeter As Int16
Public biClrUsed As Int32
Public biClrImportant As Int32
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure RGBQUAD
Public rgbBlue As Byte
Public rgbGreen As Byte
Public rgbRed As Byte
Public rgbReserved As Byte
End Structure
Private Const WS_CHILD As Int32 = &H40000000
Private Const WS_VISIBLE As Int32 = &H10000000
Private Const INVALID_HANDLE_VALUE As Int32 = -1
Private Const WM_USER As Int32 = &H400
Private Const WM_CAP_SET_CALLBACK_VIDEOSTREAM As Int32 = WM_USER + 6
Private Const WM_CAP_DRIVER_CONNECT As Int32 = WM_USER + 10
Private Const WM_CAP_DRIVER_DISCONNECT As Int32 = WM_USER + 11
Private Const WM_CAP_DLG_VIDEOFORMAT As Int32 = WM_USER + 41
Private Const WM_CAP_DLG_VIDEODISPLAY As Int32 = WM_USER + 43
Private Const WM_CAP_GET_VIDEOFORMAT As Int32 = WM_USER + 44
Private Const WM_CAP_SET_VIDEOFORMAT As Int32 = WM_USER + 45
Private Const WM_CAP_DLG_VIDEOCOMPRESSION As Int32 = WM_USER + 46
Private Const WM_CAP_SET_PREVIEW As Int32 = WM_USER + 50
Private Const WM_CAP_SET_PREVIEWRATE As Int32 = WM_USER + 52
Private Const WM_CAP_SET_SCALE As Int32 = WM_USER + 53
Private Const WM_CAP_SEQUENCE As Int32 = WM_USER + 62
Private Const WM_CAP_SEQUENCE_NOFILE As Int32 = WM_USER + 63
Private Const WM_CAP_SET_SEQUENCE_SETUP As Int32 = WM_USER + 64
Private Const WM_CAP_GET_SEQUENCE_SETUP As Int32 = WM_USER + 65
Private Const WM_CAP_STOP As Int32 = WM_USER + 68
#End Region
Private Delegate Function VideoStreamCallback(ByVal hwnd As IntPtr, ByRef lpVHdr As VIDEOHDR) As Int32
Private CallBack As New VideoStreamCallback(AddressOf HandleVideoStreamCallback)
Public Event FrameCompleted()
Private oCapParams As New CAPTUREPARMS
Private oCapVideoFormat As BITMAPINFO
Private hPreviewWindow As IntPtr
<MarshalAs(UnmanagedType.ByValArray)> Public btPicData() As Byte
Private cFrame As Int32
Private isRunning As Boolean
Private Structure YCbCrPixel
Public Y As Int32
Public Cb As Int32
Public Cr As Int32
End Structure
Public ReadOnly Property FrameNumber() As Int32 Implements PicProcessor.IPicProvider.FrameNumber
Get
Return cFrame
End Get
End Property
Public ReadOnly Property PicData() As Byte() Implements PicProcessor.IPicProvider.PicData
Get
PicData = btPicData
End Get
End Property
Public ReadOnly Property Width() As Int32 Implements PicProcessor.IPicProvider.Width
Get
Return oCapVideoFormat.bmiHeader.biWidth
End Get
End Property
Public ReadOnly Property Height() As Int32 Implements PicProcessor.IPicProvider.Height
Get
Return oCapVideoFormat.bmiHeader.biHeight
End Get
End Property
Public Sub initCam(ByRef Preview As Panel)
Cleanup()
hPreviewWindow = capCreateCaptureWindow("name", WS_VISIBLE Or WS_CHILD, 0, 0, Preview.Width, Preview.Height, Preview.Handle, 0)
SendMessage(hPreviewWindow, WM_CAP_DRIVER_CONNECT, 0, 0) 'schon jetzt ist die cam offen
SendMessage(hPreviewWindow, WM_CAP_SET_PREVIEWRATE, 100, 0) 'ohne dem hier sieht man solange keinen preview bis WM_CAP_SEQUENCE aufgerufen wird
SendMessage(hPreviewWindow, WM_CAP_SET_PREVIEW, 1, 0)
SendMessage(hPreviewWindow, WM_CAP_SET_SCALE, 1, 0)
Dim lpData As IntPtr
'Get aktuelle Params, fYield ändern und Set, damit das Fenster sicher angezeigt wird:
lpData = Marshal.AllocHGlobal(Marshal.SizeOf(oCapParams))
If SendMessage(hPreviewWindow, WM_CAP_GET_SEQUENCE_SETUP, Marshal.SizeOf(oCapParams), lpData) <> 0 Then
oCapParams = CType(Marshal.PtrToStructure(lpData, GetType(CAPTUREPARMS)), CAPTUREPARMS)
With oCapParams
.fYield = 1
.fAbortLeftMouse = 0
.fAbortRightMouse = 0
End With
Marshal.StructureToPtr(oCapParams, lpData, True)
If SendMessage(hPreviewWindow, WM_CAP_SET_SEQUENCE_SETUP, Marshal.SizeOf(oCapParams), lpData) <> 0 Then
'good
Else
'Stop
End If
End If
Marshal.FreeHGlobal(lpData)
'user das format wählen lassen:
'SendMessage(hPreviewWindow, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0)
'SendMessage(hPreviewWindow, WM_CAP_DLG_VIDEOFORMAT, 0, 0)
'SendMessage(hPreviewWindow, WM_CAP_DLG_VIDEODISPLAY, 0, 0) <- does not display a dialog for me
'Get video format
lpData = Marshal.AllocHGlobal(Marshal.SizeOf(oCapVideoFormat))
If SendMessage(hPreviewWindow, WM_CAP_GET_VIDEOFORMAT, Marshal.SizeOf(oCapVideoFormat), lpData.ToInt32) <> 0 Then
'oCapVideoFormat = CType(Marshal.PtrToStructure(lpData, GetType(BITMAPINFO)), BITMAPINFO) 'vorsicht! das kann offenbar in die hose gehen!
oCapVideoFormat.bmiHeader = CType(Marshal.PtrToStructure(lpData, GetType(BITMAPINFOHEADER)), BITMAPINFOHEADER)
'Modify und Set
'oCapVideoFormat.bmiHeader.biCompression = BI_RGB '<-diese settings hat meine cam nicht akzeptiert
'oCapVideoFormat.bmiHeader.biBitCount = 32
'oCapVideoFormat.bmiHeader.biWidth = 320
'oCapVideoFormat.bmiHeader.biHeight = 240
'Marshal.StructureToPtr(oCapVideoFormat.bmiHeader, lpData, True)
'If SendMessage(hPreviewWindow, WM_CAP_SET_VIDEOFORMAT, Marshal.SizeOf(oCapVideoFormat), lpData.ToInt32) <> 0 Then
'good
'Else
'Stop
'End If
End If
Marshal.FreeHGlobal(lpData)
'Arrays die für die Verarbeitung des Bildes notwendig sind vorbereiten
With oCapVideoFormat.bmiHeader
ReDim btPicData(.biSizeImage - 1I)
End With
End Sub
Public Sub StartCapture()
'Callback installieren & und capturing starten
SendMessage(hPreviewWindow, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, Marshal.GetFunctionPointerForDelegate(CallBack))
'SendMessage(hPreviewWindow, WM_CAP_SEQUENCE, 0, 0) 'geht auch, aber speichert zus. C:\CAPTURE.AVI
SendMessage(hPreviewWindow, WM_CAP_SEQUENCE_NOFILE, 0, 0) 'nicht in C:\CAPTURE.AVI speichern
isRunning = True
cFrame = 0
End Sub
Public Sub StopCapture()
If isRunning Then
SendMessage(hPreviewWindow, WM_CAP_STOP, 0, 0)
isRunning = False
End If
End Sub
Public Sub Cleanup()
StopCapture()
If hPreviewWindow = 0 Then
'derzt. nicht initialisiert
ElseIf hPreviewWindow <> INVALID_HANDLE_VALUE Then
SendMessage(hPreviewWindow, WM_CAP_DRIVER_DISCONNECT, 0, 0)
DestroyWindow(hPreviewWindow)
hPreviewWindow = INVALID_HANDLE_VALUE
End If
End Sub
Protected Overrides Sub Finalize()
Cleanup()
MyBase.Finalize()
End Sub
Private Function HandleVideoStreamCallback(ByVal hwnd As IntPtr, ByRef lpVHdr As VIDEOHDR) As Int32
'Debug.Print(String.Format("time ms captured: {0}, Used: {1}, of total {2} ", lpVHdr.dwTimeCaptured, lpVHdr.dwBytesUsed, lpVHdr.dwBufferLength.ToString))
cFrame += 1
'Debug.WriteLine(Thread.CurrentThread.ManagedThreadId & " " & pCallback)
'Debug.Print(cFrame.ToString)
Marshal.Copy(lpVHdr.lpData, btPicData, 0, lpVHdr.dwBytesUsed)
RaiseEvent FrameCompleted()
End Function
End Class
-
Jun 12th, 2018, 02:25 PM
#5
Re: Webcam control via .NET
Do yourself a favor and get WebEye.Controls.Winforms.WebCameraControl from NuGet
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|