效果:
在这里插入图片描述在这里插入图片描述

安卓方法代码

package com.piya;

import static com.taobao.weex.WXEnvironment.getApplication;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.objdetect.CascadeClassifier;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;

public class FaceDetectionHelper extends UniModule {

    private static final String TAG = "FaceDetectionHelper";

    // 异步检测
    @UniJSMethod(uiThread = true)
    public void testAsyncFunc(JSONObject options, final UniJSCallback callback) {
        // 加载OpenCV库
        if (!OpenCVLoader.initDebug()) {
            Log.e(TAG, "OpenCV initialization failed");
            if (callback != null) {
                JSONObject errorData = new JSONObject();
                errorData.put("error", "OpenCV initialization failed");
                callback.invoke(errorData);
            }
            return;
        }

        // 加载人脸检测器模型
        CascadeClassifier cascadeClassifier = loadCascadeClassifier();

        if (cascadeClassifier == null) {
            Log.e(TAG, "Cascade classifier loading failed");
            if (callback != null) {
                JSONObject errorData = new JSONObject();
                errorData.put("error", "Cascade classifier loading failed");
                callback.invoke(errorData);
            }
            return;
        }

        // 获取图片URL
        String imageUrl = options.getString("imgUrl");

        // 下载并处理图片
        new AsyncTask<String, Void, Bitmap>() {
            @Override
            protected Bitmap doInBackground(String... params) {
                try {
                    URL url = new URL(params[0]);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setDoInput(true);
                    connection.connect();
                    InputStream input = connection.getInputStream();
                    return BitmapFactory.decodeStream(input);
                } catch (Exception e) {
                    Log.e(TAG, "Error downloading image: " + e.getMessage());
                    return null;
                }
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (bitmap != null) {
                    // 在图像上执行人脸检测
                    JSONObject resultData = detectFaces(bitmap, cascadeClassifier);

                    // 调用回调函数返回检测结果
                    if (callback != null) {
                        callback.invoke(resultData);
                    }
                } else {
                    Log.e(TAG, "Failed to download image");
                    if (callback != null) {
                        JSONObject errorData = new JSONObject();
                        errorData.put("error", "Failed to download image");
                        callback.invoke(errorData);
                    }
                }
            }
        }.execute(imageUrl);
    }

    // 加载人脸检测器模型
    private CascadeClassifier loadCascadeClassifier() {
        try {
            InputStream is = getApplication().getApplicationContext().getAssets().open("haarcascade_frontalface_alt.xml");
            File cascadeFile = new File(getApplication().getApplicationContext().getCacheDir(), "haarcascade_frontalface_alt.xml");
            FileOutputStream os = new FileOutputStream(cascadeFile);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            is.close();
            os.close();

            CascadeClassifier cascadeClassifier = new CascadeClassifier(cascadeFile.getAbsolutePath());
            if (cascadeClassifier.empty()) {
                return null;
            }

            return cascadeClassifier;
        } catch (Exception e) {
            Log.e(TAG, "Error loading cascade classifier: " + e.getMessage());
            return null;
        }
    }

    // 在图像上执行人脸检测
    private JSONObject detectFaces(Bitmap bitmap, CascadeClassifier cascadeClassifier) {
        Mat mat = new Mat();
        MatOfRect faces = new MatOfRect();

        // 将Bitmap转换为OpenCV的Mat对象
        org.opencv.android.Utils.bitmapToMat(bitmap, mat);

        // 执行人脸检测
        cascadeClassifier.detectMultiScale(mat, faces);

        // 构建JSON对象来保存检测结果
        JSONObject resultData = new JSONObject();
        JSONArray facesArray = new JSONArray();
        resultData.put("数量", faces.toArray().length);
        Rect[] rectsArray = faces.toArray();
        for (Rect rect : rectsArray) {
            JSONObject faceData = new JSONObject();
            faceData.put("height", rect.height);
            faceData.put("x", rect.x);
            faceData.put("width", rect.width);
            faceData.put("y", rect.y);
            facesArray.add(faceData);
        }
        resultData.put("位置",facesArray);

        JSONObject res = new JSONObject();
        res.put("code","success");
        res.put("data",resultData);
        return res;
    }
}

uniapp代码

<template>
	<div style="text-align: center;">
		<view v-for="(i,index) in imgUrls" style="margin-bottom: 20px;">
			<image :src="i.url" style="height: 250px;width: 60%;"></image>
			<button type="primary" @click="testAsyncFunc(i.url, index)" style="width: 50%;margin-top: 20px;">人脸检测异步</button>
			<view style="text-align: center;" v-if="i.data != null">
				{{i.data}}
			</view>
		</view>
		<!-- <button type="primary" @click="testSyncFunc" style="width: 50%;margin-top: 20px;">人脸检测同步</button> -->
	</div>
</template>

<script>
	// 获取 module 
	var testModule = uni.requireNativePlugin("FaceDetectionHelper")
	const modal = uni.requireNativePlugin('modal');
	export default {
		data(){
			return{
				imgUrls: [
					{
						url: "https://img0.baidu.com/it/u=3389607,2584865022&fm=253&fmt=auto&app=138&f=PNG?w=449&h=645",
						data: null,
					},
					{
						url: "https://img1.baidu.com/it/u=1751886178,1535140781&fm=253&fmt=auto&app=138&f=JPEG?w=297&h=384",
						data: null,
					},
					{
						url: "https://img0.baidu.com/it/u=1112951416,2217244278&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=304",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Ffe639b21-0cde-4fdf-9818-b2442c3e023b%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902258&t=4028f29e7697388d94c3f72470cd5ef7",
						data: null,
					},
					{
						url: "https://img0.baidu.com/it/u=2353660487,2578268887&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=666",
						data: null,
					},
					{
						url: "https://img1.baidu.com/it/u=1241956916,3681734452&fm=253&fmt=auto&app=120&f=JPEG?w=400&h=560",
						data: null,
					},
					{
						url: "https://n.sinaimg.cn/sinacn/w640h727/20180131/4c66-fyrcsrv9928989.jpg",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fc28a348f-6030-489e-bf16-3ba2995c80c0%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902571&t=95286d160dd05f21702a5f85c800edee",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F74d7df5d-8dfb-4a89-a12e-d433c4cc2473%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902571&t=7bf3f3944d14cc613582d80fa637698c",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fci.xiaohongshu.com%2Fc27943ba-fa83-42c9-b9e3-c901c532a750%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fci.xiaohongshu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902570&t=36ffeb79e4f5ce047356519495025ea8",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F177c50eb-ff1e-41ba-a4b5-cdbd06dd5bfd%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902595&t=d0ed2efcaef4ff1a56c68c35d196588f",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F4d8d1eb8-f89a-42b8-b6ae-6375678e5b63%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902595&t=7bdd025d948698ef65117355e137d038",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F6baf9aef-1a72-46f1-b976-cebb6861b43c%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902595&t=b8867d83df6208f34784d330b333d814",
						data: null,
					},
					{
						url: "https://img-user-qn.hudongba.com/upload/_oss/uePasteUpload/201809/1116/1536656165657.jpg",
						data: null,
					},
					{
						url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fc27fa638-a145-418e-95a8-61c397c104fe%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1710902632&t=f481b4f348fab8e15465efe30911b058",
						data: null,
					},
					{
						url: "https://img1.baidu.com/it/u=2631529228,2871676583&fm=253&fmt=auto&app=138&f=PNG?w=400&h=558",
						data: null,
					},
					{
						url: "https://img1.baidu.com/it/u=1740647370,3843349101&fm=253&fmt=auto&app=138&f=JPEG?w=499&h=333",
						data: null,
					},
				]
			}
		},
		methods: {
			testAsyncFunc(imgUrl, index) {
				// 调用异步方法
				testModule.testAsyncFunc({
						'imgUrl': imgUrl
					},
					(ret) => {
						this.imgUrls[index].data = JSON.stringify(ret)
						modal.toast({
							message: ret,
							duration: 1.5
						});
					})
			},
			// testSyncFunc() {
			// 	// 调用同步方法
			// 	var ret = testModule.testSyncFunc({
			// 		'imgUrl': this.imgUrl
			// 	})
			// 	modal.toast({
			// 		message: ret,
			// 		duration: 1.5
			// 	});
			// }
		}
	}
</script>

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐