C# 使用摄像头拍照 支持Win7 64位
2020-12-13 02:06
标签:des style c class blog code
Once you download the source code that is attached to the article you should
have the following three projects: For a starting point I recommend a code view
of Demo\MainForm.cs. This form implements most of the operations
you can think of when it comes to WebCam access. First is the iteration through
the WebCams hooked up to the computer: The We start off by fetching the selected The first event, Now that all that is implemented, we
just When you grow tired of watching yourself, simply close the form. Once you are
back in Visual Studio, check out the Well, nothing too fancy – we unsubscribe from the two mentioned events, set
the Believe it or not – that’s it. There is nothing more critical to explain or
implement in order to use images from your WebCam in C#. The extra code that
exists in MainForm.cs is just there for saving the current
image: And bringing up the configuration dialog: As you can see from the code – the implementation is pretty easy and clean
(unlike some other approaches that use WIA, obscure DLLs, clipboard, or hard
disk for saving images, etc.), meaning that there are not many problems.
Actually, currently there is only one problem I can identify. You remember these
three lines? Well, it turns out that they are not working as advertised. First, let’s talk
about FPS. If we dive into the Even if you just glanced at the method, you probably saw that most of it is
dedicated to calculating the time between frames and ditching the frame if it
came too soon. Which is not too bad, I guess – controlling the frame rate on C#
level rather than on hardware level will probably not kill you. But what about finding out the other two lines, which influence the size of
the captured image, also not working (line 235 in Camera.cs)? As you can see, the image size is actually faked. Majority of cameras I’ve
tested out will tend to return images in the 640x480 size. Which is fine in most
cases – if you need a smaller
image, So, anyone from the C++ world is more than welcome to help with this. The
following links I’ve read gave me the impression that all that’s needed to be
done is somehow invoke the Video Format window in C++, the same way we are now
invoking the Video Source Configuration window (for setting Brightness,
Contracts, etc): 源码下载地址: Source C# 使用摄像头拍照 支持Win7 64位,搜素材,soscw.com C# 使用摄像头拍照 支持Win7 64位 标签:des style c class blog code 原文地址:http://www.cnblogs.com/lonelyxmas/p/3756674.htmlSo, how do we capture an
image from a WebCam?
private
void
MainForm_Load(
object
sender, EventArgs e)
{
if
(!DesignMode)
{
comboBoxCameras.Items.Clear();
foreach
(Camera cam
in
CameraService.AvailableCameras)
comboBoxCameras.Items.Add(cam);
if
(comboBoxCameras.Items.Count > 0)
comboBoxCameras.SelectedIndex = 0;
}
}
CameraService
class you see in the code is
contained in the WebCamWrapper project and is the main wrapper over the main
class CameraMethods
that is the only class implemented in
the C++ WebCamLib
project.CameraService
exposes AvailableCameras
as
a list of Camera
classes that contain the logic for a
certain WebCam. Once the user makes a choice of camera, you’ll obviously want to
start the capture:
private
CameraFrameSource _frameSource;
private
static
Bitmap _latestFrame;
private
void
btnStart_Click(
object
sender, EventArgs e)
{
if
(_frameSource !=
null
&& _frameSource.Camera == comboBoxCameras.SelectedItem)
return
;
thrashOldCamera();
startCapturing();
}
_frameSource
is the variable in which we’ll save the
currently selected Camera
. Touchless developers decided not to
tie their capture source exclusively to WebCam (good choice obviously) so they
made a generic IFrameSource
interface
that CameraFrameSource
implements… and that’s how this
class ended up as a container instead of theCamera
class
directly. The rest of the code is pretty self-explanatory – if we select the
same frame source, we’ll just exit; if not we will thrash the old camera and
start a new one. Onto the startCapturing
method:
private
void
startCapturing()
{
try
{
Camera c = (Camera)comboBoxCameras.SelectedItem;
setFrameSource(
new
CameraFrameSource(c));
_frameSource.Camera.CaptureWidth = 320;
_frameSource.Camera.CaptureHeight = 240;
_frameSource.Camera.Fps = 20;
_frameSource.NewFrame += OnImageCaptured;
pictureBoxDisplay.Paint +=
new
PaintEventHandler(drawLatestImage);
_frameSource.StartFrameCapture();
}
catch
(Exception ex)
{
comboBoxCameras.Text =
"Select A Camera"
;
MessageBox.Show(ex.Message);
}
}
private
void
setFrameSource(CameraFrameSource cameraFrameSource)
{
if
(_frameSource == cameraFrameSource)
return
;
_frameSource = cameraFrameSource;
}
private
void
drawLatestImage(
object
sender, PaintEventArgs e)
{
if
(_latestFrame !=
null
)
{
e.Graphics.DrawImage(_latestFrame, 0, 0, _latestFrame.Width, _latestFrame.Height);
}
}
public
void
OnImageCaptured(Touchless.Vision.Contracts.IFrameSource frameSource,
Touchless.Vision.Contracts.Frame frame,
double
fps)
{
_latestFrame = frame.Image;
pictureBoxDisplay.Invalidate();
}
Camera
from
the ComboBox
which we then use to create and set
theCameraFrameSource
. Lines after that influence the capture
parameters (be sure to remember these three lines as we will be getting back to
them later) and after that we have a subscription to two events.NewFrame
, is raised whenever WebCamLib
captures an image from the WebCam. As you can see, we save that image into a
local variable _latestFrame
and from there you can do any
additional image processing you like. The second event is just a fancy (and more
efficient) way of saying pictureBoxDisplay.Image =
frame.Image
. For some reason, setting
the Image
property on a PictureBox too often causes
flicker and we obviously do not want that – instead we resort to invalidating
the PictureBox
and then handling its paint event to draw
the current image from the WebCam.StartFrameCapture
and enjoy the view from our
WebCam. Try it out – press F5 and then click the ‘Start’ button once the Form
loads up.thrashOldCamera
method
(that is utilized from
the Form_Closing
and btnStop_Click
methods
also):
private
void
thrashOldCamera()
{
if
(_frameSource !=
null
)
{
_frameSource.NewFrame -= OnImageCaptured;
_frameSource.Camera.Dispose();
setFrameSource(
null
);
pictureBoxDisplay.Paint -=
new
PaintEventHandler(drawLatestImage);
}
}
_frameSource
variable to null
, and
call Dispose
on Camera
so that the
C++ WebCamLib can perform cleanup operations.
private
void
btnSave_Click(
object
sender, EventArgs e)
{
if
(_frameSource ==
null
)
return
;
Bitmap current = (Bitmap)_latestFrame.Clone();
using
(SaveFileDialog sfd =
new
SaveFileDialog())
{
sfd.Filter =
"*.bmp|*.bmp"
;
if
(sfd.ShowDialog() == DialogResult.OK)
{
current.Save(sfd.FileName);
}
}
current.Dispose();
}
private
void
btnConfig_Click(
object
sender, EventArgs e)
{
// snap camera
if
(_frameSource !=
null
)
_frameSource.Camera.ShowPropertiesDialog();
}
Problem(s)
_frameSource.Camera.CaptureWidth = 320;
_frameSource.Camera.CaptureHeight = 240;
_frameSource.Camera.Fps = 20;
Camera
class (line 254)
here is what we will see (the method that gets called after an image is captured
from the webcam):
private
void
ImageCaptured(Bitmap bitmap)
{
DateTime dtCap = DateTime.Now;
// Always save the bitmap
lock
(_bitmapLock)
{
_bitmap = bitmap;
}
// FPS affects the callbacks only
if
(_fpslimit != -1)
{
if
(_dtLastCap != DateTime.MinValue)
{
double
milliseconds = ((dtCap.Ticks - _dtLastCap.Ticks) / TimeSpan.TicksPerMillisecond) * 1.15;
if
(milliseconds + _timeBehind >= _timeBetweenFrames)
{
_timeBehind = (milliseconds - _timeBetweenFrames);
if
(_timeBehind
{
_timeBehind = 0.0;
}
}
else
{
_timeBehind = 0.0;
return
;
// ignore the frame
}
}
}
if
(OnImageCaptured !=
null
)
{
var
fps = (
int
)(1 / dtCap.Subtract(_dtLastCap).TotalSeconds);
OnImageCaptured.Invoke(
this
,
new
CameraEventArgs(bitmap, fps));
}
_dtLastCap = dtCap;
}
private
void
CaptureCallbackProc(
int
dataSize,
byte
[] data)
{
// Do the magic to create a bitmap
int
stride = _width * 3;
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
var
scan0 = (
int
)handle.AddrOfPinnedObject();
scan0 += (_height - 1) * stride;
var
b =
new
Bitmap(_width, _height, -stride, PixelFormat.Format24bppRgb, (IntPtr)scan0);
b.RotateFlip(_rotateFlip);
// Copy the image using the Thumbnail function to also resize if needed
var
copyBitmap = (Bitmap)b.GetThumbnailImage(_width, _height,
null
, IntPtr.Zero);
//var copyBitmap = (Bitmap)b.Clone();
// Now you can free the handle
handle.Free();
ImageCaptured(copyBitmap);
}
b.GetThumbnailImage
will allow you to easily
resize it. However, if you wish a higher resolution image, you are stuck and
that’s not a good thing.
CameraMethods
class.