Untitled
unknown
plain_text
4 years ago
10 kB
5
Indexable
// Copyright 2021 The MediaPipe Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.mediapipe.examples.hands; import android.graphics.Path; import android.opengl.GLES20; import com.google.mediapipe.formats.proto.LandmarkProto.NormalizedLandmark; import com.google.mediapipe.solutioncore.ResultGlRenderer; import com.google.mediapipe.solutions.hands.Hands; import com.google.mediapipe.solutions.hands.HandsResult; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** A custom implementation of {@link ResultGlRenderer} to render {@link HandsResult}. */ public class HandsResultGlRenderer implements ResultGlRenderer<HandsResult> { private static final String TAG = "HandsResultGlRenderer"; private static LinkedList<Float> x_middle = new LinkedList<Float>(); private static LinkedList<Float> y_middle = new LinkedList<Float>(); private static final float[] LEFT_HAND_CONNECTION_COLOR = new float[] {0.2f, 1f, 0.2f, 1f}; private static final float[] RIGHT_HAND_CONNECTION_COLOR = new float[] {1f, 0.2f, 0.2f, 1f}; private static final float CONNECTION_THICKNESS = 25.0f; private static final float[] LEFT_HAND_HOLLOW_CIRCLE_COLOR = new float[] {0.2f, 1f, 0.2f, 1f}; private static final float[] RIGHT_HAND_HOLLOW_CIRCLE_COLOR = new float[] {1f, 0.2f, 0.2f, 1f}; private static final float HOLLOW_CIRCLE_RADIUS = 0.01f; private static final float[] LEFT_HAND_LANDMARK_COLOR = new float[] {1f, 0.2f, 0.2f, 1f}; private static final float[] RIGHT_HAND_LANDMARK_COLOR = new float[] {0.2f, 1f, 0.2f, 1f}; private static final float LANDMARK_RADIUS = 0.008f; private static final int NUM_SEGMENTS = 120; private static final String VERTEX_SHADER = "uniform mat4 uProjectionMatrix;\n" + "attribute vec4 vPosition;\n" + "void main() {\n" + " gl_Position = uProjectionMatrix * vPosition;\n" + "}"; private static final String FRAGMENT_SHADER = "precision mediump float;\n" + "uniform vec4 uColor;\n" + "void main() {\n" + " gl_FragColor = uColor;\n" + "}"; private int program; private int positionHandle; private int projectionMatrixHandle; private int colorHandle; private int loadShader(int type, String shaderCode) { int shader = GLES20.glCreateShader(type); GLES20.glShaderSource(shader, shaderCode); GLES20.glCompileShader(shader); return shader; } @Override public void setupRendering() { program = GLES20.glCreateProgram(); int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER); int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER); GLES20.glAttachShader(program, vertexShader); GLES20.glAttachShader(program, fragmentShader); GLES20.glLinkProgram(program); positionHandle = GLES20.glGetAttribLocation(program, "vPosition"); projectionMatrixHandle = GLES20.glGetUniformLocation(program, "uProjectionMatrix"); colorHandle = GLES20.glGetUniformLocation(program, "uColor"); } @Override public void renderResult(HandsResult result, float[] projectionMatrix) { if (result == null) { return; } GLES20.glUseProgram(program); GLES20.glUniformMatrix4fv(projectionMatrixHandle, 1, false, projectionMatrix, 0); GLES20.glLineWidth(CONNECTION_THICKNESS); int numHands = result.multiHandLandmarks().size(); for (int i = 0; i < numHands; ++i) { boolean isLeftHand = result.multiHandedness().get(i).getLabel().equals("Left"); NormalizedLandmark thumb_tip = result.multiHandLandmarks().get(i).getLandmark(4); NormalizedLandmark index_finger_tip = result.multiHandLandmarks().get(i).getLandmark(8); //Compute the middle points ' s coordinates float middle_point_x = (thumb_tip.getX()+index_finger_tip.getX())/2; float middle_point_y = (thumb_tip.getY()+index_finger_tip.getY())/2; //Add them to two different linked lists. x_middle.addLast(middle_point_x); y_middle.addLast(middle_point_y); //Draw middlePoint for (int k = 0; k < y_middle.size();k++) { drawCircle( x_middle.get(k), y_middle.get(k), isLeftHand ? RIGHT_HAND_LANDMARK_COLOR : LEFT_HAND_LANDMARK_COLOR ); } drawConnections( result.multiHandLandmarks().get(i).getLandmarkList(), isLeftHand ? LEFT_HAND_CONNECTION_COLOR : RIGHT_HAND_CONNECTION_COLOR); drawSignature( result.multiHandLandmarks().get(i).getLandmarkList(), isLeftHand ? LEFT_HAND_CONNECTION_COLOR : RIGHT_HAND_CONNECTION_COLOR,result,x_middle,y_middle); for (NormalizedLandmark landmark : result.multiHandLandmarks().get(i).getLandmarkList()) { // Draws the landmark. drawCircle( landmark.getX(), landmark.getY(), isLeftHand ? LEFT_HAND_LANDMARK_COLOR : RIGHT_HAND_LANDMARK_COLOR); // Draws a hollow circle around the landmark. drawHollowCircle( landmark.getX(), landmark.getY(), isLeftHand ? LEFT_HAND_HOLLOW_CIRCLE_COLOR : RIGHT_HAND_HOLLOW_CIRCLE_COLOR); } //drawConnections_middlePoints(x_middle,y_middle,isLeftHand ? LEFT_HAND_CONNECTION_COLOR : RIGHT_HAND_CONNECTION_COLOR); } } /** * Deletes the shader program. * * <p>This is only necessary if one wants to release the program while keeping the context around. */ public void release() { GLES20.glDeleteProgram(program); } private void drawSignature(List<NormalizedLandmark> handLandmarkList, float[] colorArray,HandsResult result,LinkedList<Float> x_middlePoints,LinkedList<Float> y_middlePoints) { GLES20.glUniform4fv(colorHandle, 1, colorArray, 0); for (Hands.Connection c : Hands.HAND_CONNECTIONS) { NormalizedLandmark start = handLandmarkList.get(c.start()); NormalizedLandmark end = handLandmarkList.get(c.end()); NormalizedLandmark thumb_tip = result.multiHandLandmarks().get(0).getLandmark(4); NormalizedLandmark index_finger_tip = result.multiHandLandmarks().get(0).getLandmark(8); if(y_middle.size()>2){ for (int k = 1; k < y_middle.size();k++) { float[] vertex = {x_middlePoints.get(k),y_middlePoints.get(k) , x_middlePoints.get(k-1), y_middlePoints.get(k-1)}; //float[] vertex = {(thumb_tip.getX()+index_finger_tip.getX())/2, (thumb_tip.getY()+index_finger_tip.getY())/2, end.getX(), end.getY()}; FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertex.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertex); vertexBuffer.position(0); GLES20.glEnableVertexAttribArray(positionHandle); GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2);}} } } private void drawConnections(List<NormalizedLandmark> handLandmarkList, float[] colorArray) { GLES20.glUniform4fv(colorHandle, 1, colorArray, 0); for (Hands.Connection c : Hands.HAND_CONNECTIONS) { NormalizedLandmark start = handLandmarkList.get(c.start()); NormalizedLandmark end = handLandmarkList.get(c.end()); float[] vertex = {start.getX(), start.getY(), end.getX(), end.getY()}; FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertex.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertex); vertexBuffer.position(0); GLES20.glEnableVertexAttribArray(positionHandle); GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2); } } private void drawCircle(float x, float y, float[] colorArray) { GLES20.glUniform4fv(colorHandle, 1, colorArray, 0); int vertexCount = NUM_SEGMENTS + 2; float[] vertices = new float[vertexCount * 3]; vertices[0] = x; vertices[1] = y; vertices[2] = 0; for (int i = 1; i < vertexCount; i++) { float angle = 2.0f * i * (float) Math.PI / NUM_SEGMENTS; int currentIndex = 3 * i; vertices[currentIndex] = x + (float) (LANDMARK_RADIUS * Math.cos(angle)); vertices[currentIndex + 1] = y + (float) (LANDMARK_RADIUS * Math.sin(angle)); vertices[currentIndex + 2] = 0; } FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertices); vertexBuffer.position(0); GLES20.glEnableVertexAttribArray(positionHandle); GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, vertexCount); } private void drawHollowCircle(float x, float y, float[] colorArray) { GLES20.glUniform4fv(colorHandle, 1, colorArray, 0); int vertexCount = NUM_SEGMENTS + 1; float[] vertices = new float[vertexCount * 3]; for (int i = 0; i < vertexCount; i++) { float angle = 2.0f * i * (float) Math.PI / NUM_SEGMENTS; int currentIndex = 3 * i; vertices[currentIndex] = x + (float) (HOLLOW_CIRCLE_RADIUS * Math.cos(angle)); vertices[currentIndex + 1] = y + (float) (HOLLOW_CIRCLE_RADIUS * Math.sin(angle)); vertices[currentIndex + 2] = 0; } FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() .put(vertices); vertexBuffer.position(0); GLES20.glEnableVertexAttribArray(positionHandle); GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, vertexCount); } }
Editor is loading...