使用Kinect 进行图片浏览Word格式.docx
《使用Kinect 进行图片浏览Word格式.docx》由会员分享,可在线阅读,更多相关《使用Kinect 进行图片浏览Word格式.docx(14页珍藏版)》请在冰豆网上搜索。
![使用Kinect 进行图片浏览Word格式.docx](https://file1.bdocx.com/fileroot1/2022-11/28/74ebf8f5-5d67-4857-b424-2b2fc54d2552/74ebf8f5-5d67-4857-b424-2b2fc54d25521.gif)
internalTouchStateTouchState{get;
}publicKinectTouchDevice(intid,PresentationSourcesource):
base(id)
{
this.Position=newPoint();
this.TouchState=TouchState.Up;
this.SetActiveSource(source);
}publicvoidTouch(Pointposition)
//记录第一次触摸时间
if(!
this.firstTouch.HasValue)
this.firstTouch=DateTime.Now;
return;
}//如果不是第一次点击,但两次间隔小于100毫秒,则认为是一次点击,不做处理
elseif(DateTime.Now.Subtract(this.firstTouch.Value).TotalMilliseconds&
lt;
100)
this.Position=position;
this.IsActive)
this.Activate();
if(this.TouchState!
=TouchState.Down)
this.Dispatcher.Invoke(newFunc&
bool&
gt;
(this.ReportDown));
this.TouchState=TouchState.Down;
else
(this.ReportMove));
}publicvoidNoTouch()
this.firstTouch=null;
if(TouchState==TouchState.Down)
(this.ReportUp));
}publicoverrideTouchPointCollectionGetIntermediateTouchPoints(IInputElementrelativeTo)
returnnewTouchPointCollection();
}publicoverrideTouchPointGetTouchPoint(IInputElementrelativeTo)
varpoint=this.Position;
if(relativeTo!
=null)
//获取当前点击位置
point=this.ActiveSource.RootVisual.TransformToDescendant((Visual)relativeTo).Transform(point);
returnnewTouchPoint(this,point,newRect(point,newSize(1,1)),TouchAction.Move);
}publicvoidDispose()
if(this.IsActive)
this.Deactivate();
}
这是一个点,如何模拟一个面板呢,所以需要建立包含这一个点的集合的新类,名为KinectTouchDevice,详细代码如下
publicclassKinectMultiTouchDevice:
IDisposable
//触控数据源
privateHandDataSourcehandDataSource;
privatePresentationSourcepresentationSource;
//触控点集合,每一个点对应一个id
privateIDictionary&
int,KinectTouchDevice&
touchDevices;
publicSizeTargetSize{get;
set;
}publicKinectMultiTouchDevice(HandDataSourcehandDataSource,PresentationSourcepresentationSource,SizetargetSize)
this.presentationSource=presentationSource;
this.TargetSize=targetSize;
}publicKinectMultiTouchDevice(HandDataSourcehandDataSource,FrameworkElementarea)
this.touchDevices=newDictionary&
();
this.TargetSize=newSize(area.ActualWidth,area.ActualHeight);
this.presentationSource=PresentationSource.FromVisual(area);
this.handDataSource=handDataSource;
//当数据源有新数据时,触发处理事件
this.handDataSource.NewDataAvailable+=handDataSource_NewDataAvailable;
area.SizeChanged+=area_SizeChanged;
}privatevoidhandDataSource_NewDataAvailable(Objectsender,HandCollectionEventArgsdata)
if(data.IsEmpty)
ReportNoTouch(this.touchDevices.Values);
}vartouchedDevices=this.ReportTouches(data);
this.ReportNoTouch(this.touchDevices.Values.Except(touchedDevices));
}privatevoidarea_SizeChanged(objectsender,SizeChangedEventArgse)
this.TargetSize=e.NewSize;
}privateIList&
KinectTouchDevice&
ReportTouches(HandCollectionEventArgsdata)
vartouchedDevices=newList&
foreach(varhandindata.Hands)
vardevice=this.GetDevice(hand.Id);
varpointOnPresentationArea=this.MapToPresentationArea(hand,newSize(this.handDataSource.Width,this.handDataSource.Height));
device.Touch(pointOnPresentationArea);
touchedDevices.Add(device);
returntouchedDevices;
}privatevoidReportNoTouch(IEnumerable&
devices)
foreach(vardeviceindevices)
device.NoTouch();
}privateKinectTouchDeviceGetDevice(intindex)
this.touchDevices.ContainsKey(index))
this.presentationSource.Dispatcher.Invoke(newAction(()=&
this.touchDevices.Add(index,newKinectTouchDevice(index,this.presentationSource));
}));
returnthis.touchDevices[index];
}privatePointMapToPresentationArea(HandDatafingerPoint,SizeoriginalSize)
//returnnewPoint(fingerPoint.X/originalSize.Width*this.TargetSize.Width,fingerPoint.Y/originalSize.Height*this.TargetSize.Height);
returnnewPoint(fingerPoint.X,fingerPoint.Y);
this.handDataSource.NewDataAvailable-=handDataSource_NewDataAvailable;
foreach(vardeviceinthis.touchDevices.Values)
device.Dispose();
}
需要注意的是,上面代码中,touchDevices是一个IDictionary&
型的对象,表示所有触控点的集合,每一个触控点有一个int型的id。
代码中HandDataSource类型的handDataSource,表示触发触控的数据源,在KinectMultiTouchDevice类的构造函数中,我们注册了handDataSource的NewDataAvailable事件,该事件会在每当从Kinect中获取每一帧数据,且数据符合特定条件就会触发。
HandDataSource类如下:
publicclassHandDataSource
publicdelegatevoidNewDataHandler&
HandCollectionEventArgs&
(Objectsender,HandCollectionEventArgsdata);
publiceventNewDataHandler&
NewDataAvailable;
publicintWidth{get;
publicintHeight{get;
}protectedvirtualvoidOnNewDataAvailable(HandCollectionEventArgse)
NewDataHandler&
temp=NewDataAvailable;
if(temp!
temp(this,e);
}publicvoidRaiseNewDataEvent(List&
HandData&
handData){
HandCollectionEventArgse=newHandCollectionEventArgs(handData);
OnNewDataAvailable(e);
以上部分就是使用模拟多点触控的核心代码了。
(2)界面逻辑的编写
下面我们来看应用程序的前台代码。
为了在界面上显示手的位置,这里我们建立一个名为TouchControl的自定义控件,该控件很简单,里面包含一个椭圆形和一个label对象,用以表示当前手在屏幕上的位置,代码如下:
&
UserControlx:
Class="
KinectImageView.MultiTouch.TouchControl"
xmlns="
xmlns:
x="
mc="
http:
//schemas.openxmlformats.org/markup-compatibility/2006"
d="
mc:
Ignorable="
d"
d:
DesignHeight="
40"
DesignWidth="
&
GridWidth="
Height="
EllipseStroke="
White"
StrokeThickness="
3"
/&
LabelForeground="
Name="
Label"
HorizontalAlignment="
Center"
VerticalAlignment="
/Grid&
/UserControl&
后台逻辑代码也很简单,只有一个带参的构造函数。
publicpartialclassTouchControl:
UserControl
publicTouchControl()
InitializeComponent();
}publicTouchControl(intid):
this()
this.Label.Content=id;
接下来就是主界面了,为了简便,主界面上随意摆放了三张图片,用于我们使用Kinect来进行缩放平移旋转等操作,在页面的最底层添加了一个TouchControl自定义控件,用来显示手所在的位置。
整个界面前端代码如下:
Windowx:
KinectImageView.MainWindow"
Title="
MainWindow"
c="
clr-namespace:
KinectImageView"
Closing="
Window_Closing"
Loaded="
Window_Loaded"
SizeToContent="
WidthAndHeight"
Gridx:
Name="
LayoutRoot"
750"
Width="
1000"
CanvasName="
mainCanvas"
ImageName="
image"
Panel.ZIndex="
642"
IsManipulationEnabled="
True"
200"
Source="
Images/flower.jpg"
Image.RenderTransform&
MatrixTransformMatrix="
1.5929750047527,0.585411309251951,-0.585411309251951,1.5929750047527,564.691807426081,79.4658072348299"
/Image.RenderTransform&
/Image&
image1"
641"
Images/flower2.jpg"
1.79780224775912,-1.1136472330559,1.1136472330559,1.79780224775912,45.6962327448951,205.029554723656"
/&
image2"
644"
Images/flower3.jpg"
2.41806325085411,-0.0527474549128994,0.0527474549128994,2.41806325085411,280.737615796121,292.420001677231"
/Canvas&
fingerCanvas"
/Window&
下面来看看后台代码,WPF默认支持开发多点触控的程序,只需要从写下面三个方法即可:
protectedoverridevoidOnManipulationStarting(ManipulationStartingEventArgse)
base.OnManipulationStarting(e);
e.ManipulationContainer=mainCanvas;
e.Handled=true;
}protectedoverridevoidOnManipulationDelta(ManipulationDeltaEventArgse)
base.OnManipulationDelta(e);
varelement=e.SourceasFrameworkElement;
vartransformation=element.RenderTransformasMatrixTransform;
//获取缩放的中心点
Pointcenter=newPoint(element.ActualWidth/2,element.ActualHeight/2);
varmatrix=transformation==null?
Matrix.Identity:
transformation.Matrix;
center=matrix.Transform(center);
//缩放
if(e.DeltaManipulation.Scale.X&
0.5&
amp;
e.DeltaManipulation.Scale.Y&
0.5
e.DeltaManipulation.Scale.X&
2&
e.DeltaManipulation.Scale.Y&
2)
matrix.ScaleAt(e.DeltaManipulation.Scale.X,e.DeltaManipulation.Scale.Y,center.X,center.Y);
//旋转
matrix.RotateAt(e.DeltaManipulation.Rotation,center.X,center.Y);
//移动
if(center.X&
gt