AFORGE的进一步挖掘--用摄像头驱动3D模型运动

作者:穆容

转自:http://www.cnblogs.com/yriyr/archive/2010/07/01/1769478.html


效果:在摄像头前面移动,屏幕上显示一个3D的人头,跟着你的移动转动。

原理:项目由两个程序完成,一个程序用来监控摄像头。一个用WPF实现3D模型的驱动。

   aforge在监控摄像头的时候,一旦有人在摄像头前面移动,移动物体周围会有一片红色。我们利用aforge的过滤和跟踪功能。发现红色位于画面的什么位置,再将位置信息通过网络传递给WPF程序。由WPF根据位置信息转动3D模型。

 

主要代码

1.摄像头监控

private void videoSourcePlayer_NewFrame(object sender,ref Bitmap image)
        {
            NowImg = (Bitmap)image.Clone();
            if (detector != null)
            {
                Bitmap objectimage = colorFilter.Apply(image);
                // lock image for further processing
                BitmapData objectData = objectimage.LockBits(new Rectangle(0,image.Width,image.Height),
                    ImageLockMode.ReadOnly,image.PixelFormat);

                // grayscaling
                UnmanagedImage grayImage = grayFilter.Apply(new UnmanagedImage(objectData));

                // unlock image
                objectimage.UnlockBits(objectData);

                // locate blobs
                blobCounter1.ProcessImage(grayImage);
                Rectangle[] rects = blobCounter1.GetobjectsRectangles();
                if (rects.Length > 0)
                {
                    for (int i = 0; i < rects.Length; i++)
                    {
                        Rectangle objectRect = rects[i];
                        int area = 0;
                        if (objectRect.Right > 0 && objectRect.Right < 100) area = 1;
                        if (objectRect.Right > 100 && objectRect.Right < 200) area = 2;
                        if (objectRect.Right > 200 && objectRect.Right < 300) area = 3;
                        if (objectRect.Right > 300 && objectRect.Right < 400) area = 4;
                        if (objectRect.Right > 400 && objectRect.Right < 500) area = 5;
                        if (objectRect.Right > 500 && objectRect.Right < 600) area = 6;
                        if (objectRect.Right > 600 && objectRect.Right < 700) area = 7;

                        this.listBox1.Items.Insert(0,"Right -- " + area.ToString());

                        ASCIIEncoding asen = new ASCIIEncoding();
                        Stream stm = Tcpsend.GetStream();
                        byte[] ba = asen.GetBytes(area.ToString());
                        stm.Write(ba,ba.Length);

                        // draw rectangle around derected object
                        Graphics g = Graphics.FromImage(image);

                        using (Pen pen = new Pen(Color.FromA#a0ffa0,3))
                        {
                            g.DrawRectangle(pen,objectRect);
                        }

                        g.dispose();
                    }

                 } 

      ...

}

2. wpf贴图问题

其实这也不算什么技术点,只不过我在这里浪费了很多时间,所以特地记录下来:

定义画刷资源

    <Window.Resources>
        <ImageBrush x:Key="ImageBrush1" ImageSource="D:\c#项目\wxd_wpf_3d\test\WpfApplication1\WpfApplication1\157860.jpg"/>
        <ImageBrush x:Key="ImageBrush_body" ImageSource="D:\c#项目\wxd_wpf_3d\test\WpfApplication1\WpfApplication1\body.jpg"/>
        <ImageBrush x:Key="ImageBrush_face" ImageSource="D:\c#项目\wxd_wpf_3d\test\WpfApplication1\WpfApplication1\face.jpg"/>
        <ImageBrush x:Key="ImageBrush_eye" ImageSource="D:\c#项目\wxd_wpf_3d\test\WpfApplication1\WpfApplication1\eye.jpg"/>
        <ImageBrush x:Key="ImageBrush_fq" ImageSource="D:\c#项目\wxd_wpf_3d\test\WpfApplication1\WpfApplication1\fq.jpg"/>
        <ImageBrush x:Key="ImageBrush_hair" ImageSource="hair.jpg"/>
    </Window.Resources>

使用画刷:

<GeometryModel3D.Material>
       <DiffuseMaterial Brush="{DynamicResource ImageBrush_fq}"/>
</GeometryModel3D.Material> 

 

3.3D旋转

前台

                    <ModelVisual3D x:Name="____">
                        <ModelVisual3D.Transform>
                        <Transform3DGroup>
                            
                            <RotateTransform3D >
                                <RotateTransform3D.Rotation>
                                    <AxisAngleRotation3D Axis="0,1,0" x:Name="body"></AxisAngleRotation3D> //定义旋转器
                                </RotateTransform3D.Rotation>
                            </RotateTransform3D>
                        </Transform3DGroup>
                        </ModelVisual3D.Transform> 

 后台

this.body.Angle += i/2;

 

4.跨线程访问

一个新的线程来监控网络端口,有位置数据上来之后,通知主线程来旋转3D模型

        void update(int i)         {             this.dispatcher.Invoke(dispatcherPriority.normal,(ThreadStart)delegate             {                 this.body.Angle += i/2;             });                  } 

相关文章

自1998年我国取消了福利分房的政策后,房地产市场迅速开展蓬...
文章目录获取数据查看数据结构获取数据下载数据可以直接通过...
网上商城系统MySql数据库设计
26个来源的气象数据获取代码
在进入21世纪以来,中国电信业告别了20世纪最后阶段的高速发...