[转载]Silverlight 4 中摄像头的运用—part1 – 我和未来有约会 – 博客园.
输入的视频
摄像头经过一个Video对象就能让你看到视频,而这个对象是一个显示对象,所以显示对象能做得事情,它都能做,比如滤镜,变形,混合模式等 等。当然最强大的还是使用WriteableBitmap画出视频内容。这样,通过图像分析、 比较等等,对于图像处理来说就有着无限可能。
这里来看看如何引用摄像头并看到拍摄的视频。
===================================
01 |
public partial class MainPage : UserControl |
03 |
CaptureSource _captureSource; |
04 |
VideoCaptureDevice _video; |
07 |
InitializeComponent(); |
08 |
_captureSource = new CaptureSource(); |
09 |
_video = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(); |
11 |
_captureSource.VideoCaptureDevice = _video; |
13 |
btnStart.Click += new RoutedEventHandler(btnStart_Click); |
18 |
void btnStart_Click( object sender, RoutedEventArgs e) |
20 |
if (CaptureDeviceConfiguration.AllowedDeviceAccess || |
21 |
CaptureDeviceConfiguration.RequestDeviceAccess()) |
23 |
_captureSource.Start(); |
===================================
有了摄像头,就该输出视频了。把摄像头的数据作为视频刷子赋值到Rectangle对象上即可,再把Rectangle加入到场景中。
===================================
01 |
public partial class MainPage : UserControl |
03 |
CaptureSource _captureSource; |
04 |
VideoCaptureDevice _video; |
05 |
VideoBrush _videoBrush; |
09 |
InitializeComponent(); |
10 |
_captureSource = new CaptureSource(); |
11 |
_video = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(); |
13 |
_captureSource.VideoCaptureDevice = _video; |
14 |
_videoBrush = new VideoBrush(); |
15 |
_videoBrush.SetSource(_captureSource); |
17 |
btnStart.Click += new RoutedEventHandler(btnStart_Click); |
22 |
void btnStart_Click( object sender, RoutedEventArgs e) |
24 |
if (CaptureDeviceConfiguration.AllowedDeviceAccess || |
25 |
CaptureDeviceConfiguration.RequestDeviceAccess()) |
27 |
_rect = new Rectangle(); |
33 |
_rect.Fill = _videoBrush; |
37 |
LayoutRoot.Children.Add(_rect); |
41 |
_captureSource.Start(); |
===================================
视频尺寸和质量
场景上出现了摄像头拍摄的内容。但画面不够大,也不像其它看到的视频那样清晰。 这不是因为Silverlight不行,而是由于默认的设置不好。视频可以在创建时设置其大小,默认是640×480。我们可以查看Video对象。
这里可知他一共支持了21种格式。通过简单的设置便可以更改摄像头的清晰度。
_video.DesiredFormat = _video.SupportedFormats[3];
要 知道,越高的fps,机器在处理视频时越费劲。对于类似视频会议这种东西,视频的质量和尺寸并不是非常重要,所以不要为此花太大精力。
视频和位图
正如之前说的,摄像头最强大的应用是混合
WriteableBitmap。所以,通过Render把视频绘 制在一个
WriteableBitmap对象里,就能以像素级来控制整个东西了。当然,对于动画,就需要不停的绘制。
===================================
01 |
void btnStart_Click( object sender, RoutedEventArgs e) |
03 |
if (CaptureDeviceConfiguration.AllowedDeviceAccess || |
04 |
CaptureDeviceConfiguration.RequestDeviceAccess()) |
06 |
_rect = new Rectangle(); |
12 |
_rect.Fill = _videoBrush; |
13 |
_rect.Visibility = Visibility.Collapsed; |
14 |
LayoutRoot.Children.Add(_rect); |
18 |
_wb = new WriteableBitmap(_rect, null ); |
19 |
_wb_image = new Image(); |
20 |
_wb_image.Width = 320; |
21 |
_wb_image.Height = 240; |
22 |
_wb_image.Source = _wb; |
26 |
LayoutRoot.Children.Add(_wb_image); |
31 |
_captureSource.Start(); |
32 |
_isEnableCamera = true ; |
35 |
void OnRender( object sender, EventArgs e) |
39 |
_wb.Render(_rect, null ); |
===================================
反转图像
要知道,用户在摄像头前所做的反应,总希望和镜子中一样,人往左,视频中人也往左,人 往右,其也往右。但事实并不是这样,所以需要我们来为之做反转图像。
===================================
01 |
void OnRender( object sender, EventArgs e) |
08 |
MatrixTransform transform = new MatrixTransform(); |
09 |
transform.Matrix = new Matrix(-1, 0, 0, 1, 320, 0); |
13 |
_wb.Render(_rect, transform); |
===================================
对象的绘制以传入的变形矩阵为依据。通过矩阵能做很多事情,虽然只有很简单的前四个参数,它们却控制着缩放,旋转和形变。这里让图形的x轴缩放率等 于 -1,意味着水平反转它。接着,0的意思是指图形没有旋转和形变,最后一个1是说y轴保持100%不变。但仅仅如此,还看不到任何东西。因为此时的矩阵是 从右向左扩展的,而最后两个参数是把矩阵移到图形的右上角,这样就保证落入了可视范围。
分析像素
现在你拥有了像素的控制权,该如何处置?记得我之前说过不要高质量、高分辨率的视频嘛?我 现在要更进一步的说,越低分辨率、越低质量越好。就算只有320×240大小的视频图像,每一帧要处理的像素也有76800个啊。所以不要搞太大的视频来 玩。事实上,你将会发现我要做的第一件事情,是设计如何除掉这么多像素带来的巨大信息。一般来说,我们只对视频的某个颜色区域,或者对比度之类的感兴趣。
分析颜色
首先我们尝试着跟踪一个具体颜色。假如用户拿一个颜色(红色)比较突出的东西在摄像头前面晃动,我们能跟踪其位置就算成功。
首先了解一下像素数组的排列方式。
int pixel = bmSource.Pixels[y * imageWidth + x]
接下来根据pixel 反向算回颜色
1 |
Color color = Color.FromArgb( |
2 |
( byte )((pixel >> 24) & 0xff), |
3 |
( byte )((pixel >> 16) & 0xff), |
4 |
( byte )((pixel >> 8) & 0xff), |
5 |
( byte )((pixel) & 0xff)); |
有了以上的原理就可以分析WriteableBitmap的颜色了。