NDK OpenGL与OpenCV实现大眼萌特效
发布人:shili8
发布时间:2024-12-27 11:38
阅读次数:0
**NDK OpenGL 与 OpenCV 实现大眼萌特效**
在本文中,我们将使用 NDK (Native Development Kit) 的 OpenGL 和 OpenCV 库来实现一个大眼萌特效。这个特效会让眼睛变得更加突出和萌萌的。
### **环境准备**
首先,我们需要准备好我们的开发环境。我们需要安装 Android Studio、NDK、OpenCV 和 CMake 等工具。
* 安装 Android Studio* 下载 NDK 并配置环境变量* 下载 OpenCV 库并配置环境变量* 安装 CMake### **项目结构**
下面是我们的项目结构:
project/ src/ main/ cpp/ MyGLSurfaceView.cppMyGLRenderer.cppOpenCVUtil.cppjni/ Android.mkApplication.mkCMakeLists.txtres/ layout/ activity_main.xmlvalues/ strings.xml...
### **MyGLSurfaceView.java**
javapackage com.example.ndk_opengl; import android.content.Context; import android.opengl.GLSurfaceView; import android.util.AttributeSet; public class MyGLSurfaceView extends GLSurfaceView { public MyGLSurfaceView(Context context) { super(context); } public MyGLSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); } }
### **MyGLRenderer.java**
javapackage com.example.ndk_opengl; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import javax.microedition.khronos.opengles.GL10; public class MyGLRenderer implements GLSurfaceView.Renderer { private float[] mvpMatrix = new float[16]; private float[] projectionMatrix = new float[16]; @Override public void onSurfaceCreated(GL10 gl, int width, int height) { // Set up the camera. Matrix.setLookAtM(projectionMatrix,0,0,0,0f,0f, -5f,0f,0f,1.0f,0.0f,0.0f); // Create a texture and set the texture wrapping parameters. gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); } @Override public void onDrawFrame(GL10 gl) { // Draw a triangle. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // Set the camera. gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadMatrixf(projectionMatrix,0); // Create a vertex buffer object (VBO) and copy the data to it. float[] vertices = new float[]{ -1.0f, -1.0f, 1.0f, -1.0f, 0.0f,1.0f }; // Create a vertex buffer object (VBO) and copy the data to it. int[] vbo = new int[1]; gl.glGenBuffers(1, vbo,0); gl.glBindBuffer(GL10.GL_ARRAY_BUFFER, vbo[0]); gl.glBufferData(GL10.GL_ARRAY_BUFFER, vertices.length *4, vertices, GL10.GL_STATIC_DRAW); // Create a vertex shader and set the vertex attributes. int[] vs = new int[1]; gl.glGenVertexShaders(vs.length, vs,0); gl.glBindVertexShader(vs[0]); gl.glShaderOp(GL10.GL_VERTEX_SHADER, GL10.GL_FALSE, vertices.length *4, vertices,2); // Create a fragment shader and set the fragment attributes. int[] fs = new int[1]; gl.glGenFragmentShaders(fs.length, fs,0); gl.glBindFragmentShader(fs[0]); gl.glShaderOp(GL10.GL_FRAGMENT_SHADER, GL10.GL_FALSE, vertices.length *4, vertices,2); // Link the shaders. gl.glLinkProgram(vs[0], fs[0]); // Draw a triangle using the VBO and shader program. gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(2, GL10.GL_FLOAT,4 *4, vbo[0]); gl.glDrawArrays(GL10.GL_TRIANGLES,0, vertices.length /2); // Disable the client state. gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // Set up the camera. Matrix.setLookAtM(projectionMatrix,0,0,0,0f,0f, -5f,0f,0f,1.0f,0.0f,0.0f); // Create a texture and set the texture wrapping parameters. gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); } }
### **OpenCVUtil.cpp**
cpp#includevoid OpenCVUtil::cvMatToTexture(cv::Mat mat, int* textureId) { // Create a texture and set the texture wrapping parameters. gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); // Copy the data to a texture buffer object (TBO). int[] tbo = new int[1]; gl.glGenBuffers(1, tbo,0); gl.glBindBuffer(GL10.GL_TEXTURE_BUFFER, tbo[0]); gl.glBufferData(GL10.GL_TEXTURE_BUFFER, mat.total() * mat.channels(), mat.data, GL10.GL_STATIC_DRAW); // Create a texture and bind it to the TBO. int[] tex = new int[1]; gl.glGenTextures(1, tex,0); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex[0]); gl.glTexImage2D(GL10.GL_TEXTURE_2D,0, GL10.GL_RGBA, mat.cols(), mat.rows(),0, GL10.GL_BGRA, GL10.GL_UNSIGNED_BYTE, null); // Copy the data from the TBO to the texture. gl.glCopyTexSubImage2D(GL10.GL_TEXTURE_2D,0,0,0, tbo[0],0, mat.cols(), mat.rows()); // Unbind the TBO and texture. gl.glBindBuffer(GL10.GL_TEXTURE_BUFFER,0); gl.glBindTexture(GL10.GL_TEXTURE_2D,0); // Store the texture ID. *textureId = tex[0]; }
### **Android.mk**
makefileLOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := MyGLSurfaceViewLOCAL_SRC_FILES := MyGLSurfaceView.cppLOCAL_LDLIBS := -lloginclude $(BUILD_SHARED_LIBRARY)
### **Application.mk**
makefileAPP_ABI := armeabi-v7a
### **CMakeLists.txt**
cmakecmake_minimum_required(VERSION3.10) project(MyGLSurfaceView) find_package(OpenCV REQUIRED) add_library(MyGLSurfaceView SHARED MyGLSurfaceView.cpp) target_link_libraries(MyGLSurfaceView ${OpenCV_LIBS})
### **activity_main.xml**
xml
### **strings.xml**
xml<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">MyGLSurfaceView</string> </resources>
### **AndroidManifest.xml**
xml<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" /> package="com.example.ndk_opengl"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
### **MainActivity.java