private void OnLoadModel(object sender, RoutedEventArgs e) { PoseNet posenet = new PoseNet(); using (var graph = new TFGraph()) { graph.Import(File.ReadAllBytes("Resources\\frozen_model.bytes")); var session = new TFSession(graph); string input = "photo.jpg"; var tensor = ImageUtil.CreateTensorFromImageFile(input); var runner = session.GetRunner(); runner.AddInput(graph["image"][0], tensor); runner.Fetch( graph["heatmap"][0], graph["offset_2"][0], graph["displacement_fwd_2"][0], graph["displacement_bwd_2"][0] ); var result = runner.Run(); var heatmap = (float[, , , ])result[0].GetValue(jagged: false); var offsets = (float[, , , ])result[1].GetValue(jagged: false); var displacementsFwd = (float[, , , ])result[2].GetValue(jagged: false); var displacementsBwd = (float[, , , ])result[3].GetValue(jagged: false); var poses = posenet.DecodeMultiplePoses( heatmap, offsets, displacementsFwd, displacementsBwd, outputStride: 16, maxPoseDetections: 15, scoreThreshold: 0.001f, nmsRadius: 20); } }
// Use this for initialization void Start() { var heatmap = GetResourcesToFloats("heatmaps", 33, 33, 17); var offsets = GetResourcesToFloats("offsets", 33, 33, 34); var displacementsFwd = GetResourcesToFloats("displacementsFwd", 33, 33, 32); var displacementsBwd = GetResourcesToFloats("displacementsBwd", 33, 33, 32); poses = posenet.DecodeMultiplePoses( heatmap, offsets, displacementsFwd, displacementsBwd, outputStride: 16, maxPoseDetections: 15, scoreThreshold: 0.5f, nmsRadius: 20); gl = glgo.GetComponent <GLRenderer>(); }
/// <summary> /// Receive a frame from camera. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Camera_ImageGrabbed(object sender, EventArgs e) { if (camera.Retrieve(frame)) { CvInvoke.Flip(frame, frame, Emgu.CV.CvEnum.FlipType.Horizontal); CvInvoke.Resize(frame, resizedFrame, new System.Drawing.Size(detectionSize, detectionSize), 0, 0); TFTensor tensor = TransformInput(resizedFrame.Bitmap); TFSession.Runner runner = session.GetRunner(); runner.AddInput(graph["image"][0], tensor); runner.Fetch( graph["heatmap"][0], graph["offset_2"][0], graph["displacement_fwd_2"][0], graph["displacement_bwd_2"][0] ); var result = runner.Run(); var heatmap = (float[, , , ])result[0].GetValue(jagged: false); var offsets = (float[, , , ])result[1].GetValue(jagged: false); var displacementsFwd = (float[, , , ])result[2].GetValue(jagged: false); var displacementsBwd = (float[, , , ])result[3].GetValue(jagged: false); Pose[] poses = posenet.DecodeMultiplePoses( heatmap, offsets, displacementsFwd, displacementsBwd, outputStride: 16, maxPoseDetections: 100, scoreThreshold: 0.5f, nmsRadius: 20); Drawing(frame, poses); Dispatcher.Invoke(new Action(() => { img.Source = frame.Bitmap.BitmapToBitmapSource(); })); } }
void Start() { TextAsset graphModel = Resources.Load("frozen_model") as TextAsset; var graph = new TFGraph(); graph.Import(graphModel.bytes); var session = new TFSession(graph); Texture2D image = Resources.Load("tennis_in_crowd") as Texture2D; image = scaled(image, ImageSize, ImageSize); var tensor = TransformInput(image.GetPixels32(), ImageSize, ImageSize); var runner = session.GetRunner(); runner.AddInput(graph ["image"] [0], tensor); runner.Fetch( graph ["heatmap"] [0], graph ["offset_2"] [0], graph ["displacement_fwd_2"] [0], graph ["displacement_bwd_2"] [0] ); var result = runner.Run(); var heatmap = (float [, , , ])result [0].GetValue(jagged: false); var offsets = (float [, , , ])result [1].GetValue(jagged: false); var displacementsFwd = (float [, , , ])result [2].GetValue(jagged: false); var displacementsBwd = (float [, , , ])result [3].GetValue(jagged: false); //Debug.Log(mean(heatmap)); poses = posenet.DecodeMultiplePoses( heatmap, offsets, displacementsFwd, displacementsBwd, outputStride: 16, maxPoseDetections: 15, scoreThreshold: 0.5f, nmsRadius: 20); gl = glgo.GetComponent <GLRenderer>(); }
IEnumerator PoseUpdate(Texture2D texture) { texture = scaled(texture, ImageSize, ImageSize); var tensor = TransformInput(texture.GetPixels32(), ImageSize, ImageSize); var runner = session.GetRunner(); runner.AddInput(graph["image"][0], tensor); runner.Fetch( graph["heatmap"][0], graph["offset_2"][0], graph["displacement_fwd_2"][0], graph["displacement_bwd_2"][0] ); var result = runner.Run(); var heatmap = (float[, , , ])result[0].GetValue(jagged: false); var offsets = (float[, , , ])result[1].GetValue(jagged: false); var displacementsFwd = (float[, , , ])result[2].GetValue(jagged: false); var displacementsBwd = (float[, , , ])result[3].GetValue(jagged: false); // Debug.Log(PoseNet.mean(heatmap)); poses = posenet.DecodeMultiplePoses( heatmap, offsets, displacementsFwd, displacementsBwd, outputStride: 16, maxPoseDetections: 15, scoreThreshold: 0.5f, nmsRadius: 20); isPosing = false; texture = null; Resources.UnloadUnusedAssets(); yield return(null); }
IEnumerator PoseUpdate(Texture2D texture) { if (texture.width != detectWidth || texture.height != detectHeight) { texture = scaled(texture, detectWidth, detectHeight); } var tensor = TransformInput(texture.GetPixels32()); var runner = session.GetRunner(); runner.AddInput(graph["image"][0], tensor); runner.Fetch( graph["heatmap"][0], graph["offset_2"][0], graph["displacement_fwd_2"][0], graph["displacement_bwd_2"][0] ); var result = runner.Run(); var heatmap = (float[, , , ])result[0].GetValue(jagged: false); var offsets = (float[, , , ])result[1].GetValue(jagged: false); var displacementsFwd = (float[, , , ])result[2].GetValue(jagged: false); var displacementsBwd = (float[, , , ])result[3].GetValue(jagged: false); // Debug.Log(PoseNet.mean(heatmap)); poses = posenet.DecodeMultiplePoses( heatmap, offsets, displacementsFwd, displacementsBwd, outputStride: 16, maxPoseDetections: 1, scoreThreshold: 0.5f, nmsRadius: 20); isPosing = false; /*/ここからtakasakaのコード * if(poses.Length > 0 && poses[0].score >= minPoseConfidence){ * var pose = poses[0]; * * src.Clear(); * src["nose"] = pose.keypoints[0]; * src["eyeL"] = pose.keypoints[1]; src["eyeR"] = pose.keypoints[2]; * src["earL"] = pose.keypoints[3]; src["earR"] = pose.keypoints[4]; * src["upperArmL"] = pose.keypoints[5]; src["upperArmR"] = pose.keypoints[6]; * src["lowerArmL"] = pose.keypoints[7]; src["lowerArmR"] = pose.keypoints[8]; * src["handL"] = pose.keypoints[9]; src["handR"] = pose.keypoints[10]; * src["upperLegL"] = pose.keypoints[11]; src["upperLegR"] = pose.keypoints[12]; * src["lowerLegL"] = pose.keypoints[13]; src["lowerLegR"] = pose.keypoints[14]; * src["footL"] = pose.keypoints[15]; src["footR"] = pose.keypoints[16]; * * joint.Clear(); * foreach(KeyValuePair<string, PoseNet.Keypoint> pair in src){ * if(pair.Value.score < minPartConfidence){ continue; } * * //PoseNetの機能強化あるいは他の姿勢推定ライブラリに切り替えられるようVector3で作っておく * joint[pair.Key] = new Vector3(pair.Value.position.x, videoHeight - pair.Value.position.y, 0); * } * * //前フレームのジョイント位置と平均を取る * if(jointsAvg.Count == 0){ * for(int i = 0; i < jointsCount; i++){ * jointsAvg[i] = new Dictionary<string, Vector3>(joint); * } * } * jointsAvg[jointsIndex++ % jointsCount] = new Dictionary<string, Vector3>(joint); * * foreach(string key in src.Keys){ * if(!joint.ContainsKey(key)){ continue; } * joint[key] = Vector3.zero; * * int hit = 0; * for(int i = 0; i < jointsCount; i++){ * if(!jointsAvg[i].ContainsKey(key)){ continue; } * * joint[key] += jointsAvg[i][key]; ++hit; * } * if(hit > 0){ joint[key] /= hit; } * } * * //左腕 * if(joint.ContainsKey("upperArmL")){ * if(joint.ContainsKey("lowerArmL")){ * if(joint.ContainsKey("upperArmR")){ * UpdateJoint(joint, "upperArmR", "upperArmL", "lowerArmL", dst["upperArmL"]); * AdjJoint(0, -40, 0, dst["upperArmL"]); //ダミー * } * * if(joint.ContainsKey("handL")){ * UpdateJoint(joint, "upperArmL", "lowerArmL", "handL", dst["lowerArmL"]); * * //常に手のひらを向けるよう補正 * var armLow2Hand = (joint["handL"] - joint["lowerArmL"]); * armLow2Hand.Normalize(); * var angleX = Rad2Deg(armLow2Hand.y) + 90; * var angleY = Mathf.Min(0, Rad2Deg(armLow2Hand.x)); * AdjJoint(angleX, angleY, 0, dst["lowerArmL"]); * * dst["handL"].transform.localRotation = new Quaternion(); * AdjJoint(0, 0, -20, dst["handL"]); //ダミー * } * } * } * * //右腕 * if(joint.ContainsKey("upperArmR")){ * if(joint.ContainsKey("lowerArmR")){ * if(joint.ContainsKey("upperArmL")){ * UpdateJoint(joint, "upperArmL", "upperArmR", "lowerArmR", dst["upperArmR"]); * AdjJoint(0, 40, 0, dst["upperArmR"]); //ダミー * } * if(joint.ContainsKey("handR")){ * UpdateJoint(joint, "upperArmR", "lowerArmR", "handR", dst["lowerArmR"]); * * //常に手のひらを向けるよう補正 * var armLow2Hand = joint["handR"]- joint["lowerArmR"]; * armLow2Hand.Normalize(); * var angleX = Rad2Deg(armLow2Hand.y) + 90; * var angleY = Mathf.Max(0, Rad2Deg(armLow2Hand.x)); * AdjJoint(angleX, angleY, 0, dst["lowerArmR"]); * * dst["handR"].transform.localRotation = new Quaternion(); * AdjJoint(0, 0, 20, dst["handR"]); //ダミー * } * } * } * //胸 * if(joint.ContainsKey("upperArmL") && joint.ContainsKey("upperArmR")){ * joint["upperArmLL"] = joint["upperArmL"] + vecX; * UpdateJoint(joint, "upperArmLL", "upperArmL", "upperArmR", dst["upperChest"], -20, 20); * } * //腰 * if(joint.ContainsKey("upperLegL") && joint.ContainsKey("upperLegR")){ * //基準点が無いので左肩の左水平方向に仮のジョイントを作る * joint["upperLegLL"] = joint["upperLegL"] + vecX; * UpdateJoint(joint, "upperLegLL", "upperLegL", "upperLegR", dst["spine"], -10, 10); * * float addX = -3.0f; * float mulX = 10.0f; * * var pos = joint["upperLegL"] + joint["upperLegR"]; * pos /= 2; * var x = -(pos.x - (videoWidth / 2)) / videoWidth; * * Vector3 tmp = dst["hips"].transform.position; * dst["hips"].transform.position = new Vector3(x * mulX + addX, tmp.y, tmp.z); * * //AdjJoint(-20, 0, 0, dst["spine"]); //ダミー * } * //左脚 * if(joint.ContainsKey("upperLegL")){ * if(joint.ContainsKey("lowerLegL")){ * if(joint.ContainsKey("upperLegR")){ * //基準点が無いので左脚付け根の上方向に仮のジョイントを作る * joint["upperLegLUp"] = joint["upperLegR"] - joint["upperLegL"]; * joint["upperLegLUp"].Normalize(); * joint["upperLegLUp"] = Quaternion.AngleAxis(Rad2Deg(-halfPi), vecZ) * joint["upperLegLUp"]; * joint["upperLegLUp"] += joint["upperLegL"]; * UpdateJoint(joint, "upperLegLUp", "upperLegL", "lowerLegL", dst["upperLegL"], -20, 20); * } * if(joint.ContainsKey("footL")){ * UpdateJoint(joint, "upperLegL", "lowerLegL", "footL", dst["lowerLegL"], -20, 20); * * //基準点が無いので左足首の下垂直方向に仮のジョイントを作る * joint["footLDown"] = joint["footL"] - vecY; * UpdateJoint(joint, "lowerLegL", "footL", "footLDown", dst["footL"]); * }else{ * //基準点が無いので左膝の下垂直方向に仮のジョイントを作る * joint["lowerLegLDown"] = joint["lowerLegL"] - vecY; * UpdateJoint(joint, "upperLegL", "lowerLegL", "lowerLegLDown", dst["lowerLegL"]); * UpdateJoint(joint, "lowerLegL", "lowerLegLDown", "lowerLegLDown", dst["footL"]); * } * AdjJoint(0, 10, 0, dst["footL"]); //ダミー * } * } * //右脚 * if(joint.ContainsKey("upperLegR")){ * if(joint.ContainsKey("lowerLegR")){ * if(joint.ContainsKey("upperLegL")){ * //基準点が無いので右脚付け根の上方向に仮のジョイントを作る * joint["upperLegRUp"] = joint["upperLegL"] - joint["upperLegR"]; * joint["upperLegRUp"].Normalize(); * joint["upperLegRUp"] = Quaternion.AngleAxis(Rad2Deg(halfPi), vecZ) * joint["upperLegRUp"]; * joint["upperLegRUp"] += joint["upperLegR"]; * UpdateJoint(joint, "upperLegRUp", "upperLegR", "lowerLegR", dst["upperLegR"], -20, 20); * } * if(joint.ContainsKey("footR")){ * UpdateJoint(joint, "upperLegR", "lowerLegR", "footR", dst["lowerLegR"], -20, 20); * * //基準点が無いので右足首の下垂直方向に仮のジョイントを作る * joint["footRDown"] = joint["footR"] - vecY; * UpdateJoint(joint, "lowerLegR", "footR", "footRDown", dst["footR"]); * }else{ * //基準点が無いので右膝の下垂直方向に仮のジョイントを作る * joint["lowerLegRDown"] = joint["lowerLegR"] - vecY; * UpdateJoint(joint, "upperLegR", "lowerLegR", "lowerLegRDown", dst["lowerLegR"]); * UpdateJoint(joint, "lowerLegR", "lowerLegRDown", "lowerLegRDown", dst["footR"]); * } * AdjJoint(0, -10, 0, dst["footR"]); //ダミー * } * } * } * //ここまでtakasakaのコード*/ Debug.Log("pose update:" + Time.time + ", time:" + (Time.time - nowTime) + ", FPS:" + 1 / (Time.time - nowTime)); nowTime = Time.time; yield return(null); }