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

