You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Kotlin中实现类似Snapchat、Instagram的实时人脸滤镜?

Android Kotlin 实时AR人脸滤镜实现指南

一、核心技术选型

不用从零造轮子,优先选择Android生态成熟工具组合:

  • CameraX:Google官方相机库,简化相机预览、帧捕获的设备适配工作
  • ML Kit 人脸检测:轻量级人脸关键点检测工具,可快速获取人脸轮廓、眼睛、鼻子等200+关键点坐标,是AR滤镜定位的核心
  • OpenGL ES:负责实时帧的滤镜渲染(颜色滤镜、贴纸叠加),性能优于RenderScript更适合实时场景
  • 可选:若需复杂3D AR效果,可使用ARCore,它内置人脸追踪与3D渲染能力

二、项目基础搭建

1. 权限配置

在AndroidManifest.xml中添加相机权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

在Activity中动态申请相机权限:

private fun requestCameraPermission() {
    ActivityResultContracts.RequestPermission().launch(this, Manifest.permission.CAMERA)
}

// 初始化时检查权限
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        requestCameraPermission()
    } else {
        startCamera()
    }
}

2. 集成CameraX预览

在build.gradle(Module)添加依赖:

dependencies {
    def camerax_version = "1.3.0"
    implementation "androidx.camera:camera-core:$camerax_version"
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
    implementation "androidx.camera:camera-view:$camerax_version"
}

布局中添加PreviewView用于相机预览:

<androidx.camera.view.PreviewView
    android:id="@+id/previewView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

初始化CameraX并启动预览:

private fun startCamera() {
    val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
    cameraProviderFuture.addListener({
        val cameraProvider = cameraProviderFuture.get()
        val preview = Preview.Builder().build().also {
            it.setSurfaceProvider(previewView.surfaceProvider)
        }
        val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
        try {
            cameraProvider.unbindAll()
            cameraProvider.bindToLifecycle(this, cameraSelector, preview)
        } catch(exc: Exception) {
            // 处理相机绑定异常
        }
    }, ContextCompat.getMainExecutor(this))
}

三、人脸检测集成

1. 添加ML Kit依赖

dependencies {
    implementation "com.google.mlkit:face-detection:16.1.5"
}

2. 实现人脸检测分析器

创建ImageAnalysis.Analyzer处理相机帧,提取人脸关键点:

class FaceDetectionAnalyzer(private val onFacesDetected: (List<Face>) -> Unit) : ImageAnalysis.Analyzer {
    private val detectorOptions = FaceDetectorOptions.Builder()
        .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
        .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
        .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
        .build()
    private val faceDetector = FaceDetection.getClient(detectorOptions)

    @SuppressLint("UnsafeOptInUsageError")
    override fun analyze(imageProxy: ImageProxy) {
        val mediaImage = imageProxy.image ?: run {
            imageProxy.close()
            return
        }
        val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
        faceDetector.process(inputImage)
            .addOnSuccessListener { faces ->
                onFacesDetected(faces)
                imageProxy.close()
            }
            .addOnFailureListener {
                imageProxy.close()
            }
    }
}

将分析器绑定到CameraX:

val imageAnalysis = ImageAnalysis.Builder()
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .build()
    .also {
        it.setAnalyzer(ContextCompat.getMainExecutor(this), FaceDetectionAnalyzer { faces ->
            // 实时更新人脸关键点数据
            updateFaceLandmarks(faces)
        })
    }

// 绑定到相机生命周期
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis)

四、实时滤镜渲染

1. 基础颜色滤镜(以灰度为例)

用OpenGL ES编写片段着色器实现颜色转换:

// 灰度滤镜片段着色器
precision mediump float;
varying vec2 v_TexCoord;
uniform sampler2D u_Texture;

void main() {
    vec4 color = texture2D(u_Texture, v_TexCoord);
    float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
    gl_FragColor = vec4(gray, gray, gray, color.a);
}

自定义GLSurfaceView或TextureView,将CameraX帧纹理传入OpenGL渲染器,应用着色器效果。

2. AR贴纸滤镜实现

根据ML Kit检测到的人脸关键点,计算贴纸的位置与缩放比例:

// 示例:基于左眼关键点定位眼镜贴纸
fun attachGlassesSticker(face: Face) {
    val leftEye = face.landmarks[FaceLandmark.LEFT_EYE] ?: return
    val leftEyePos = leftEye.position
    // 根据人脸宽度计算贴纸缩放比例
    val faceWidth = face.boundingBox.width()
    val stickerScale = faceWidth / glassesBitmap.width.toFloat()
    // 将计算后的参数传入OpenGL,在对应位置绘制贴纸
}

通过OpenGL纹理混合,将贴纸叠加到相机预览帧上。

五、滤镜切换UI实现

用RecyclerView实现底部滤镜选择栏:

// 滤镜数据类
data class Filter(val name: String, val thumbnailRes: Int, val shaderId: Int)

// 滤镜选择适配器
class FilterAdapter(private val filters: List<Filter>, private val onFilterSelected: (Filter) -> Unit) :
    RecyclerView.Adapter<FilterAdapter.ViewHolder>() {
    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val thumbnail: ImageView = itemView.findViewById(R.id.filter_thumbnail)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_filter, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val filter = filters[position]
        holder.thumbnail.setImageResource(filter.thumbnailRes)
        holder.itemView.setOnClickListener { onFilterSelected(filter) }
    }

    override fun getItemCount() = filters.size
}

点击滤镜Item时,切换OpenGL渲染器使用的着色器或贴纸资源。

关键优化点

  • 降低人脸检测频率:比如每3帧检测一次,减少CPU占用
  • 开启硬件加速:确保CameraX与OpenGL均启用硬件加速
  • 适配相机分辨率:选择与屏幕匹配的预览分辨率,减少缩放损耗

内容的提问来源于stack exchange,提问作者Dev Dhande

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:53:25