void RaiseOnUpdated(GestureCameraData data) { if (OnUpdated != null) { OnUpdated(this, new OnUpdatedEventArgs(data)); } }
////////////////////////////////////////////// #region Private Methods Mesh extractHandMesh(GestureCameraData data) { var mesh = new Mesh(); mesh.TextureWidth = data.TextureWidth; mesh.TextureHeight = data.TextureHeight; mesh.Texture = data.Texture; //頂点の追加 var indexMap = new int[data.Width, data.Height]; var depthMap = new float[data.Width, data.Height]; int index = 0; for (int y = 0; y < data.Height; y += Skip) { for (int x = 0; x < data.Width; x += Skip) { //背景領域は無視 if (data.Blob[data.Width * y + x] == data.BlobBackground) { indexMap[x, y] = -1; continue; } Point point; if (data.TryGet(x, y, out point)) { //遠いところにあるものは無視 if (MaxDepth < point.Z) { indexMap[x, y] = -1; continue; } indexMap[x, y] = index; depthMap[x, y] = point.Z; mesh.AddPoint(point); ++index; } else { indexMap[x, y] = -1; } } } //メッシュインデックスの作成 //メッシュを構成する頂点が密であることが前提 for (int y = Skip; y < data.Height - Skip; y += Skip) { for (int x = Skip; x < data.Width - Skip; x += Skip) { //頂点が存在する場合は左上と右下に三角形をつくろうとする if (indexMap[x, y] != -1) { int center = indexMap[x, y]; if (indexMap[x - Skip, y] != -1 && Math.Abs(depthMap[x - Skip, y] - depthMap[x, y]) < MaxDepthGap && indexMap[x, y - Skip] != -1 && Math.Abs(depthMap[x, y - Skip] - depthMap[x, y]) < MaxDepthGap && Math.Abs(depthMap[x - Skip, y] - depthMap[x, y - Skip]) < MaxDepthGap) { mesh.AddIndices(new int[] { indexMap[x - Skip, y], indexMap[x, y - Skip], center }); } if (indexMap[x + Skip, y] != -1 && Math.Abs(depthMap[x + Skip, y] - depthMap[x, y]) < MaxDepthGap && indexMap[x, y + Skip] != -1 && Math.Abs(depthMap[x, y + Skip] - depthMap[x, y]) < MaxDepthGap && Math.Abs(depthMap[x + Skip, y] - depthMap[x, y + Skip]) < MaxDepthGap) { mesh.AddIndices(new int[] { center, indexMap[x + Skip, y], indexMap[x, y + Skip] }); } } //頂点が存在しない場合は1マスあけた左下と右上に三角形をつくろうとする else { if (indexMap[x - Skip, y] != -1 && Math.Abs(depthMap[x - Skip, y] - depthMap[x, y + Skip]) < MaxDepthGap && indexMap[x, y + Skip] != -1 && Math.Abs(depthMap[x, y + Skip] - depthMap[x - Skip, y + Skip]) < MaxDepthGap && indexMap[x - Skip, y + Skip] != -1 && Math.Abs(depthMap[x - Skip, y + Skip] - depthMap[x - Skip, y]) < MaxDepthGap) { mesh.AddIndices(new int[] { indexMap[x - Skip, y], indexMap[x, y + Skip], indexMap[x - Skip, y + Skip] }); } if (indexMap[x + Skip, y] != -1 && Math.Abs(depthMap[x + Skip, y] - depthMap[x, y - Skip]) < MaxDepthGap && indexMap[x, y - Skip] != -1 && Math.Abs(depthMap[x, y - Skip] - depthMap[x + Skip, y - Skip]) < MaxDepthGap && indexMap[x + Skip, y - Skip] != -1 && Math.Abs(depthMap[x + Skip, y - Skip] - depthMap[x + Skip, y]) < MaxDepthGap) { mesh.AddIndices(new int[] { indexMap[x + Skip, y], indexMap[x, y - Skip], indexMap[x + Skip, y - Skip] }); } } } } return(mesh); }
/// <summary> /// 手の領域のメッシュを再構成します。 /// </summary> public void UpdateMesh(GestureCameraData data) { Mesh = extractHandMesh(data); }
internal OnUpdatedEventArgs(GestureCameraData data) { Data = data; }
void update() { if (!_pipeline.AcquireFrame(true)) { throw new GestureCameraException("Failed to aquire frame."); } if (_pipeline.IsDisconnected()) { return; } var color = _pipeline.QueryImage(PXCMImage.ImageType.IMAGE_TYPE_COLOR); var depth = _pipeline.QueryImage(PXCMImage.ImageType.IMAGE_TYPE_DEPTH); var gesture = _pipeline.QueryGesture(); PXCMGesture.Blob blobInfo; GestureCameraUtil.Assert(gesture.QueryBlobData(PXCMGesture.Blob.Label.LABEL_SCENE, 0, out blobInfo), "Failed to query blob data."); PXCMImage blob; GestureCameraUtil.Assert(gesture.QueryBlobImage(PXCMGesture.Blob.Label.LABEL_SCENE, 0, out blob), "Failed to query blob image."); PXCMGesture.Gesture gestureData; var gestureDataList = new List <PXCMGesture.Gesture>(); for (uint i = 0; ; ++i) { if (gesture.QueryGestureData(0, PXCMGesture.GeoNode.Label.LABEL_ANY, i, out gestureData) == pxcmStatus.PXCM_STATUS_ITEM_UNAVAILABLE) { break; } gestureDataList.Add(gestureData); } PXCMImage.ImageData colorData; GestureCameraUtil.Assert( color.AcquireAccess(PXCMImage.Access.ACCESS_READ, out colorData), "Failed to acquire access on color image."); PXCMImage.ImageData depthData; GestureCameraUtil.Assert( depth.AcquireAccess(PXCMImage.Access.ACCESS_READ, out depthData), "Failed to acquire access on depth image."); PXCMImage.ImageData blobData; GestureCameraUtil.Assert( blob.AcquireAccess(PXCMImage.Access.ACCESS_READ, out blobData), "Failed to acquire access on blob image."); int colorWidth = (int)color.info.width; int colorHeight = (int)color.info.height; var colorImage = colorData.ToByteArray(0, 3 * colorWidth * colorHeight); int depthWidth = (int)depth.info.width; int depthHeight = (int)depth.info.height; var verticies = depthData.ToShortArray(0, 3 * depthWidth * depthHeight); var uv = depthData.ToFloatArray(2, 2 * depthWidth * depthHeight); int blobWidth = (int)blob.info.width; int blobHeight = (int)blob.info.height; var blobImage = blobData.ToByteArray(0, blobWidth * blobHeight); var data = new GestureCameraData(depthWidth, depthHeight, colorWidth, colorHeight, colorImage, blobImage, blobInfo.labelBackground, gestureDataList); for (int j = 0; j < depthHeight; ++j) { for (int i = 0; i < depthWidth; ++i) { float u = uv[2 * (j * depthWidth + i) + 0]; float v = uv[2 * (j * depthWidth + i) + 1]; int colorX = (int)(u * (colorWidth - 1)); int colorY = (int)(v * (colorHeight - 1)); if (0 > colorX || colorX > colorWidth || 0 > colorY || colorY > colorHeight) { continue; } float x = verticies[3 * (j * depthWidth + i) + 0]; float y = verticies[3 * (j * depthWidth + i) + 1]; float z = verticies[3 * (j * depthWidth + i) + 2]; if (z == _depthLowConf || z == _depthSaturation) { continue; } x *= _unit_m; y *= _unit_m; z *= _unit_m; data.Set(i, j, new Point(u, v, x, y, z)); } } GestureCameraUtil.Assert( color.ReleaseAccess(ref colorData), "Failed to release access on color image."); GestureCameraUtil.Assert( depth.ReleaseAccess(ref depthData), "Failed to release access on depth image."); GestureCameraUtil.Assert( blob.ReleaseAccess(ref blobData), "Failed to release access to blob data)"); _pipeline.ReleaseFrame(); RaiseOnUpdated(data); }