65.9K
CodeProject 正在变化。 阅读更多。
Home

尖端技术 - 动态、纹理和 3D 形式作为交互式服务(第一部分)

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2012 年 9 月 8 日

MIT

7分钟阅读

viewsIcon

29392

downloadIcon

971

本文是开发一个框架以在本地和网络上提供动态、触摸和 3D 形式作为交互式服务的初步尝试。

引言

这是该系列文章的第一部分,旨在介绍一个框架的概念和软件,该框架通过普通的网络摄像头在本地和互联网上提供动态和触摸作为服务。是的,你没听错(或看错),动态和触摸作为服务。实际上,还有更多;借助这项技术,在不久的将来,您将能够开发出能够在网络上传输 3D 形式的应用程序!
所有软件都将是开源的,并且具有非常宽松的许可,但有几个核心库是正在申请专利的免费软件(知识产权归我所有)。核心库目前包含图像分析的代码,但也将包含模拟纹理和复制 3D 形式的代码。

计算机几乎可以变成有生命的物体。


那是什么,乔?
“先生,这是 Kinect、Wii 和索尼 Move……但它们被强化了!它将震撼你的世界,这是一个很棒的概念!我无语了,它把我的舌头切成了碎片!”


照片来源:Smoobs;http://www.flickr.com/photos/smoo/
来源;http://www.flickr.com/photos/43541636@N00/237975844


开始吧!关于可能实现的功能的一些说明

该框架将允许您发明自己的手势、效果和命令来控制设备,它还将足够灵活,可以适应现有的游戏,而无需修改您的代码。

借助简单的日常网络摄像头和计算设备(平板电脑等),新框架将开辟各种激动人心的前景,将人机交互扩展到增强的感官交换生态系统中。例如;想象一下,软件让您能够自由地创建疯狂的东西,让您可以指向一台计算机将数据传输到另一台计算机。我个人一直梦想着在网络上进行拳击或跆拳道比赛(任何精彩的对决),也许我们可以实现某种程度的模拟,但这主要受限于连接速度和往返时间;可惜的是,这将需要一款高端网络摄像头,能够捕捉快速移动物体的清晰画面。

在坐在办公桌前,在网上订购之前,有没有可能感受到你新沙发的织物质感?增强的电影体验怎么样,当你坐在客厅最喜欢的椅子里时,可以感受到恐怖片中令人毛骨悚然的东西?想象一下,让您的网站联系和支持页面、论坛、Flash、Silverlight、HTML5 内容等以新颖的方式与手势进行交互的可能性……甚至还可以与执行器、电机、机器人和其他机械设备进行交互!

可能性!可能性!!可能性!!!

该技术开发的每一个方面都将有您的参与,有些东西我可以展示给您,有些东西您也可以教我;随着代码在此处发布,实际的框架和服务器正在构建中。请留意大约每两周发布一次的增量代码和新的解释性文章。本文档处理的是框架最基本概念。

不必要的历史

我一直对实时对象识别很感兴趣,甚至在 2006 年在 www.Codeplex.com 上启动了一个开源项目。自 2010 年以来,我一直认真致力于解决实时对象识别问题,并在 www.KC36.com 上开始了艰苦的旅程,充满了汗水、失败、偶尔的成功和痛苦的重启。学到的教训很多。

方法论和支持平台一瞥

第一个也是最重要的教训是,笛卡尔坐标系是一种非常不自然且令人困惑的图像分析选择。首先,它对角度和长度的表示不准确;其次,大自然偏爱圆形和其他圆锥曲线。例如,我们眼睛的瞳孔是圆形的,而我们的视野是圆锥形的(我跑题了;确实,在整个可观察的大自然中,直线总是作为曲线的局部近似值,直线仅仅是我们方便的数学概念之一)。
咳咳!你如何用一堆方块来表示圆锥曲线?不行,先生!
我们通过将图像分解为多边形来解决这个问题。为了将图像分解为多边形,我们找到边缘(或深度)并将曲线近似为折线,从而使图像中的每个对象都成为一个多边形。这样做可以简化计算并提高执行速度。
本系列后续文章将提供有关此区域的更多详细信息。

最终将支持的平台是:

  • Windows (C++, C#)
  • Android (通过 C++ 和 C#/Mono)
  • Linux (通过 C++ 和 C#/Mono)
  • iOS (通过 C++)
  • Mac (通过 C++)

目前仅支持 Windows 和 Pbgra32 图像格式。但是,该库是用 ANSI-C++ 编写的,没有任何依赖项,因此一旦支持其他图像格式,将其编译到其他平台几乎不会有任何问题。

通过构建在 C++ 和 C# API 之上的层,将支持与 HTML5、JavaScript 和 Webinos (http://webinos.org/) 的浏览器交互。一图胜千言,所以这里有一个图片概述

边缘检测代码简介

边缘检测代码执行多项任务,主要包括:

  • 边缘检测
  • 边缘分类
  • 边缘索引和排序
  • 折线段角度近似
  • 用折线近似曲线

首先,必须强调的是,下面显示的应用程序和库没有 GPU 加速,并且未经优化(除了 Visual C++ 中的 SSE 开关),但执行时间非常具有竞争力,即使在我那台运行着原始 BIOS 极度排斥的、运行高级操作系统的、年老体衰的“奶奶”电脑上。以下是我那台好“老”工作马的配置:

操作系统:Windows Server 2008 标准版 Service Pack 2 (32 位)
品牌:华硕 Pundit P4S8L
处理器:Intel Celeron 2.40GHz
内存:1.5 GB

下面的图片显示了对一张 615 x 407 图片进行查找、分类、索引、排序边缘(以及本节开头提到的所有其他优点)的结果。

14 毫秒,不错吧?!

本文随附了该应用程序的代码和库,因此您可以进行自己的测试。您的结果可能会有所不同,并且您会发现测试图片的复杂性也会影响执行时间。
注意:我们还没有使用网络摄像头,目前不需要它来展示可行性。网络摄像头将在后续文章中介绍。


图 1 边缘分类


图 2. 曲线近似



图 3. 线段角度近似

出于某种原因,在 64 位机器上速度较慢,我将对其进行研究,并在稍后提供 64 位版本。
注意:为避免 System.IO.FileNotFoundException,64 位用户需要安装 Microsoft Visual C++ 2010 SP1 可再发行组件包 (x86) http://www.microsoft.com/en-gb/download/details.aspx?id=8328

代码组织

本文的软件包含两个项目:KC36.Client 和 KC36.NET。KC36.Client 是 GUI,而 KC36.NET 封装了本地库 KC36.Native。本地库包含核心分析功能。

此代码发布的内容

简而言之,它将图像组织成多边形,然后可以对其进行模式搜索。相当简单明了。下面的代码块解释了如何使用当前文件,它与 GUI 文件 ClientMainUI.cs 中的 Execute() 方法中的代码非常相似。
本地库中的代码正在申请专利,因此我在细节方面受到一些限制;将来有一天,它可能会开源,但就目前而言,对反创新苹果/三星之战的恐惧是智慧的开端。

使用代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using KC36.Interop;
using System.Diagnostics;
using System.Drawing.Imaging;

namespace KC36.Client
{
    internal class Class1
    {
        internal unsafe void TestIt(Image image)
        {
            // this should come in as a parameter or property from the webcam driver.
            int bitsPerPixel = 4;

            // Sets the brightness datum for edge selection, experiment
            // with this value to see its effect.
            // It is controlled by the slider in the GUI. 
            int trkBarMinBrightnessDiffTolerance = 177;

            // Sets the tolerance angle for the polyline approximation,
            // experiment with numbers from 1 to 8 and see the result.
            int cmbEdgeAngleTolerance = 1;

            // The image to be analysed.
            Bitmap bitmap = (Bitmap)image;
                
            // Get the byte array data of the loaded image.
            byte[] pixelArray = Tools.GetBytes(bitmap);

            // Set the properties that would be used to communicate with
            // the native library.
            int pixelArrayCount = pixelArray.Length;
            int stride = bitmap.Width * bitsPerPixel;
            int width = bitmap.Width;
            int height = bitmap.Height;

            // Initialise the native library (skipping this step will
            // result in unpredictable behaviour).
            // Initialisation needs to be carried out only once, or if
            // a resize of the GUI occurs.
            Wrapper.InitialiseCore(width, height, stride,
                        trkBarMinBrightnessDiffTolerance, cmbEdgeAngleTolerance);

            //---------------------------------------------------
            // Call the native library (KC36.Native) to analyse the pixel data.
            Wrapper.GetFeaturedList(pixelArray);

            // Use returned data the native library (KC36.Native)
            // to populate local variables.
            // Wrapper.DirectionIndices is key to understanding how the
            // the data below fits together.
            // Wrapper.DirectionIndices holds the indices Wrapper.Directions
            // and Wrapper.EdgeMetrics, for example
            // Wrapper.EdgeMetrics[0] holds the data for
            // Wrapper.DirectionIndices[Wrapper.DirectionIndices[0]].

            // polyline segment angles.
            int* polylineAngles = Wrapper.Directions;
 
            // indices of Wrapper.Directions and Wrapper.EdgeMetrics.
            int* indices = Wrapper.DirectionIndices;

            // edge quality indicator (used to discriminate between
            // and group polyline segments).
            int* edgeMetrics = Wrapper.EdgeMetrics; 

            // total count of Wrapper.DirectionIndices.
            int featurePointCount = Wrapper.FeaturePointCount;
 
            // Get the polyline segments (recall that polyline segments
            // represent curve  approximations.
            // This is a large array with every 10 elements holding the
            // definition of a segment. The order is as follows:
            // 0 index, 1 start x, 2 start y, 3 end x, 4 end y, 5 start depth,
            // 6 end depth, 7 pixel count, 8 octant (darkest pixel in 3x3
            // neighbourhood that holds the normal to orientation of segment),
            // 9 angle

            // total number of segments.
            int segmentPropertyCount = Wrapper.SegmentPropertyCount;

            // initialise segment array.
            int[] segments = new int[segmentPropertyCount];

            // populate segment array.
            int* segmentsNative = Wrapper.SegmentProperties;

            /*
             * Code for your functions goes here.
             * See ClientMainUI.cs for inspiration.
             * ...And they all lived happily ever after! :)
             */
        }
    }
}

尝试各种设置,熟悉它们,看看您能得到什么。这些控件是改写互联网和计算机交互定义方式的激动人心且划时代的旅程的开端。

要使用下载的文件,请将其解压缩到合适的目录。您会发现另一个名为 KC36.Native.zip 的 zip 文件和一个名为“License (for KC36.Native).txt”的许可证文件。阅读许可证,然后将代码解压缩到同一目录。对于介绍性发布,该许可证相当严格,但那只是因为其中一些代码将在大约一周内过时;后续的许可证将更加宽松。顺便说一句,KC36.Client 和 KC36.NET 都获得了 MIT 许可,像空气一样自由。

这就是今天的全部内容,各位!下一篇文章将介绍对象识别代码,它将与本文的介绍链接,并填补任何技术空白。预计将在大约一周后发布。

关注点

代码在 64 位机器上运行缓慢,这个问题正在解决中。另外,为避免 System.IO.FileNotFoundException,64 位用户需要安装 Microsoft Visual C++ 2010 SP1 可再发行组件包 (x86) http://www.microsoft.com/en-gb/download/details.aspx?id=8328

© . All rights reserved.