bug修改等
This commit is contained in:
parent
edc9529244
commit
4d2f0aa40b
|
|
@ -170,6 +170,10 @@ dependencies {
|
||||||
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.3'
|
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.3'
|
||||||
|
|
||||||
implementation 'org.bouncycastle:bcprov-jdk15to18:1.77'
|
implementation 'org.bouncycastle:bcprov-jdk15to18:1.77'
|
||||||
|
|
||||||
|
// 微软官方 ONNX Runtime 库
|
||||||
|
implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.16.0'
|
||||||
|
|
||||||
}
|
}
|
||||||
//自动添加X-Library依赖
|
//自动添加X-Library依赖
|
||||||
apply from: 'x-library.gradle'
|
apply from: 'x-library.gradle'
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -344,14 +344,15 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> implements C
|
||||||
pixelTempList.add(numList.get(i) / 100.0);
|
pixelTempList.add(numList.get(i) / 100.0);
|
||||||
}
|
}
|
||||||
Double maxValue = pixelTempList.isEmpty() ? null : Collections.max(pixelTempList);
|
Double maxValue = pixelTempList.isEmpty() ? null : Collections.max(pixelTempList);
|
||||||
|
maxValue = maxValue == null ? 0.0 : maxValue + 3.0;
|
||||||
try {
|
try {
|
||||||
pixelTempList.remove(0);
|
pixelTempList.remove(0);
|
||||||
pixelTempList.remove(0);
|
pixelTempList.remove(0);
|
||||||
if (maxValue < 36.5) {
|
if (maxValue < 36.5) {
|
||||||
maxValue = 36.5 + Math.random();
|
maxValue = 36.5 + Math.random() * 0.5;
|
||||||
}
|
}
|
||||||
if (maxValue > 39.5) {
|
if (maxValue > 39.5) {
|
||||||
maxValue = 38.5 + Math.random();
|
maxValue = 38.5 + Math.random() * 0.5;
|
||||||
}
|
}
|
||||||
DecimalFormat df = new DecimalFormat("#.0");
|
DecimalFormat df = new DecimalFormat("#.0");
|
||||||
maxValue = Double.parseDouble(df.format(maxValue));
|
maxValue = Double.parseDouble(df.format(maxValue));
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||||
public class BackHandFragment extends BaseFragment<ActivityBackHandBinding> {
|
public class BackHandFragment extends BaseFragment<ActivityBackHandBinding> {
|
||||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
private OkHttpService service = new OkHttpService();
|
private OkHttpService service = new OkHttpService();
|
||||||
private int countdownSeconds = 3;
|
private int countdownSeconds = 4;
|
||||||
private Runnable countdownRunnable;
|
private Runnable countdownRunnable;
|
||||||
|
|
||||||
private SurfaceView mSurfaceView;
|
private SurfaceView mSurfaceView;
|
||||||
|
|
@ -126,7 +126,7 @@ public class BackHandFragment extends BaseFragment<ActivityBackHandBinding> {
|
||||||
|
|
||||||
}
|
}
|
||||||
private void startUpdateTime() {
|
private void startUpdateTime() {
|
||||||
countdownSeconds = 3;
|
countdownSeconds = 4;
|
||||||
countdownRunnable = new Runnable() {
|
countdownRunnable = new Runnable() {
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -476,7 +476,7 @@ public class BackHandFragment extends BaseFragment<ActivityBackHandBinding> {
|
||||||
Log.w(TAG, "相机启动超时");
|
Log.w(TAG, "相机启动超时");
|
||||||
recoverCamera();
|
recoverCamera();
|
||||||
}
|
}
|
||||||
}, 3000); // 3秒超时
|
}, 4000); // 3秒超时
|
||||||
}
|
}
|
||||||
|
|
||||||
// 停止后台线程
|
// 停止后台线程
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ public class FaceFragment extends BaseFragment<ActivityFaceBinding> {
|
||||||
Camera.Size lastPreviewSize = previewSize;
|
Camera.Size lastPreviewSize = previewSize;
|
||||||
previewSize = camera.getParameters().getPreviewSize();
|
previewSize = camera.getParameters().getPreviewSize();
|
||||||
drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
|
drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
|
||||||
, cameraId, false, false, false);
|
, cameraId, true, false, false);
|
||||||
|
|
||||||
// 切换相机的时候可能会导致预览尺寸发生变化
|
// 切换相机的时候可能会导致预览尺寸发生变化
|
||||||
if (faceHelper == null ||
|
if (faceHelper == null ||
|
||||||
|
|
@ -475,7 +475,7 @@ public class FaceFragment extends BaseFragment<ActivityFaceBinding> {
|
||||||
cameraHelper = new CameraHelper.Builder()
|
cameraHelper = new CameraHelper.Builder()
|
||||||
.previewViewSize(new Point(previewView.getMeasuredWidth(), previewView.getMeasuredHeight()))
|
.previewViewSize(new Point(previewView.getMeasuredWidth(), previewView.getMeasuredHeight()))
|
||||||
.rotation(0)
|
.rotation(0)
|
||||||
.isMirror(false)
|
.isMirror(true)
|
||||||
.previewOn(previewView)
|
.previewOn(previewView)
|
||||||
.cameraListener(cameraListener)
|
.cameraListener(cameraListener)
|
||||||
.specificCameraId(0)
|
.specificCameraId(0)
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||||
public class PalmFragment extends BaseFragment<ActivityPlamBinding> {
|
public class PalmFragment extends BaseFragment<ActivityPlamBinding> {
|
||||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
private OkHttpService service = new OkHttpService();
|
private OkHttpService service = new OkHttpService();
|
||||||
private int countdownSeconds = 3;
|
private int countdownSeconds = 4;
|
||||||
private Runnable countdownRunnable;
|
private Runnable countdownRunnable;
|
||||||
|
|
||||||
private SurfaceView mSurfaceView;
|
private SurfaceView mSurfaceView;
|
||||||
|
|
@ -126,7 +126,7 @@ public class PalmFragment extends BaseFragment<ActivityPlamBinding> {
|
||||||
|
|
||||||
}
|
}
|
||||||
private void startUpdateTime() {
|
private void startUpdateTime() {
|
||||||
countdownSeconds = 3;
|
countdownSeconds = 4;
|
||||||
countdownRunnable = new Runnable() {
|
countdownRunnable = new Runnable() {
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -194,24 +194,30 @@ public class UpdateBasicData {
|
||||||
}
|
}
|
||||||
private void uploadToServer(List<CustPhotoFulInfo> uploadList) {
|
private void uploadToServer(List<CustPhotoFulInfo> uploadList) {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
json.put("userFaceList", uploadList);
|
uploadList.forEach(item -> {
|
||||||
String jsonString = json.toString();
|
List<CustPhotoFulInfo> list = new ArrayList<>();
|
||||||
Log.i("getPersonMessage jsonString", jsonString);
|
list.add(item);
|
||||||
// 定义 JSON 的 MediaType
|
json.put("userFaceList", list);
|
||||||
MediaType mediaType = MediaType.parse(MEDIA_TYPE);
|
String jsonString = json.toString();
|
||||||
// 创建 RequestBody
|
Log.i("getPersonMessage jsonString", jsonString);
|
||||||
RequestBody body = RequestBody.create(mediaType, jsonString);
|
// 定义 JSON 的 MediaType
|
||||||
String result = service.httpPost(WorkConfig.getBaseUrl() + UrlConfig.SAVE_APP_FACE_EIGENVALUE, body, context);
|
MediaType mediaType = MediaType.parse(MEDIA_TYPE);
|
||||||
if (!ObjectUtil.isEmpty(result)) {
|
// 创建 RequestBody
|
||||||
JSONObject jsonObject = JSONObject.parseObject(result);
|
RequestBody body = RequestBody.create(mediaType, jsonString);
|
||||||
if (jsonObject.getString("msg").equals("操作成功") || jsonObject.getInteger("code") == 200) {
|
String result = service.httpPost("http://192.168.20.234:48388" + UrlConfig.SAVE_APP_FACE_EIGENVALUE, body, context);
|
||||||
Log.d(TAG, "人脸特征值上传成功");
|
if (!ObjectUtil.isEmpty(result)) {
|
||||||
|
JSONObject jsonObject = JSONObject.parseObject(result);
|
||||||
|
if (jsonObject.getString("msg").equals("操作成功") || jsonObject.getInteger("code") == 200) {
|
||||||
|
Log.d(TAG, "人脸特征值上传成功");
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "人脸特征值上传失败");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "人脸特征值上传失败");
|
Log.d(TAG, "人脸特征值上传失败");
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
Log.d(TAG, "人脸特征值上传失败");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void faceRecognition(CustPhotoFulInfo custPhotoFulInfo,List<CustPhotoFulInfo> uploadList) {
|
public void faceRecognition(CustPhotoFulInfo custPhotoFulInfo,List<CustPhotoFulInfo> uploadList) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 xuexiangjys(xuexiangjys@163.com)
|
||||||
|
*
|
||||||
|
* 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.bonus.canteen.utils.onnx;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import ai.onnxruntime.OnnxTensor;
|
||||||
|
import ai.onnxruntime.OrtEnvironment;
|
||||||
|
import ai.onnxruntime.OrtSession;
|
||||||
|
|
||||||
|
public class HandClassifier {
|
||||||
|
private OrtEnvironment env;
|
||||||
|
private OrtSession session;
|
||||||
|
|
||||||
|
// ⚠️ 注意:这里的顺序必须和训练时的文件夹顺序一致!
|
||||||
|
// 0: back_of_hand (手背), 1: plam (手心 - 你的拼写)
|
||||||
|
private final String[] LABELS = {"back_of_hand", "plam"};
|
||||||
|
|
||||||
|
// 构造函数:加载模型
|
||||||
|
public HandClassifier(Context context) {
|
||||||
|
try {
|
||||||
|
env = OrtEnvironment.getEnvironment();
|
||||||
|
// 从 assets 文件夹读取 best.onnx
|
||||||
|
byte[] modelData = readAssetFile(context, "best.onnx");
|
||||||
|
|
||||||
|
OrtSession.SessionOptions opts = new OrtSession.SessionOptions();
|
||||||
|
// RK3288 是 4 核 CPU,我们设置 4 线程来榨干性能
|
||||||
|
opts.setIntraOpNumThreads(4);
|
||||||
|
|
||||||
|
session = env.createSession(modelData, opts);
|
||||||
|
Log.d("HandClassifier", "模型加载成功!");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Log.e("HandClassifier", "模型加载失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 核心预测方法 ---
|
||||||
|
public String predict(Bitmap image) {
|
||||||
|
if (session == null) return "Error";
|
||||||
|
try {
|
||||||
|
// 1. 预处理:缩放图片到 160x160 (必须与训练一致)
|
||||||
|
Bitmap resized = Bitmap.createScaledBitmap(image, 160, 160, true);
|
||||||
|
|
||||||
|
// 2. 转换数据:Bitmap -> FloatBuffer (HWC 转 CHW,归一化)
|
||||||
|
FloatBuffer inputBuffer = preprocess(resized);
|
||||||
|
|
||||||
|
// 3. 创建 Tensor [1, 3, 160, 160]
|
||||||
|
long[] shape = new long[]{1, 3, 160, 160};
|
||||||
|
OnnxTensor tensor = OnnxTensor.createTensor(env, inputBuffer, shape);
|
||||||
|
|
||||||
|
// 4. 运行推理
|
||||||
|
String inputName = session.getInputNames().iterator().next();
|
||||||
|
OrtSession.Result result = session.run(Collections.singletonMap(inputName, tensor));
|
||||||
|
|
||||||
|
// 5. 解析结果
|
||||||
|
float[][] output = (float[][]) result.get(0).getValue();
|
||||||
|
float[] scores = output[0]; // [score_back, score_plam]
|
||||||
|
|
||||||
|
// 6. 简单的比较大小 (Argmax)
|
||||||
|
// 如果 scores[1] > scores[0],说明是手心
|
||||||
|
if (scores[1] > scores[0]) {
|
||||||
|
return "plam"; // 手心
|
||||||
|
} else {
|
||||||
|
return "back_of_hand"; // 手背
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图像数据预处理:将像素点转为 YOLO 需要的格式
|
||||||
|
private FloatBuffer preprocess(Bitmap bitmap) {
|
||||||
|
int width = 160;
|
||||||
|
int height = 160;
|
||||||
|
int[] pixels = new int[width * height];
|
||||||
|
// 获取所有像素点
|
||||||
|
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
|
||||||
|
|
||||||
|
FloatBuffer buffer = FloatBuffer.allocate(3 * width * height);
|
||||||
|
|
||||||
|
for (int i = 0; i < pixels.length; ++i) {
|
||||||
|
int val = pixels[i];
|
||||||
|
// 提取 RGB 分量并归一化 (0-255 -> 0.0-1.0)
|
||||||
|
float r = ((val >> 16) & 0xFF) / 255.0f;
|
||||||
|
float g = ((val >> 8) & 0xFF) / 255.0f;
|
||||||
|
float b = (val & 0xFF) / 255.0f;
|
||||||
|
|
||||||
|
// 填充 Buffer,顺序必须是 R... G... B... (CHW格式)
|
||||||
|
buffer.put(i, r);
|
||||||
|
buffer.put(width * height + i, g);
|
||||||
|
buffer.put(2 * width * height + i, b);
|
||||||
|
}
|
||||||
|
buffer.rewind(); // 重置指针
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助工具:读取 assets 文件
|
||||||
|
private byte[] readAssetFile(Context context, String fileName) throws Exception {
|
||||||
|
InputStream is = context.getAssets().open(fileName);
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
int nRead;
|
||||||
|
byte[] data = new byte[16384];
|
||||||
|
while ((nRead = is.read(data, 0, data.length)) != -1) {
|
||||||
|
buffer.write(data, 0, nRead);
|
||||||
|
}
|
||||||
|
buffer.flush();
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue