微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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;             });                  } 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐