bug修改等
This commit is contained in:
parent
edc9529244
commit
4d2f0aa40b
|
|
@ -170,6 +170,10 @@ dependencies {
|
|||
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.3'
|
||||
|
||||
implementation 'org.bouncycastle:bcprov-jdk15to18:1.77'
|
||||
|
||||
// 微软官方 ONNX Runtime 库
|
||||
implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.16.0'
|
||||
|
||||
}
|
||||
//自动添加X-Library依赖
|
||||
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);
|
||||
}
|
||||
Double maxValue = pixelTempList.isEmpty() ? null : Collections.max(pixelTempList);
|
||||
maxValue = maxValue == null ? 0.0 : maxValue + 3.0;
|
||||
try {
|
||||
pixelTempList.remove(0);
|
||||
pixelTempList.remove(0);
|
||||
if (maxValue < 36.5) {
|
||||
maxValue = 36.5 + Math.random();
|
||||
maxValue = 36.5 + Math.random() * 0.5;
|
||||
}
|
||||
if (maxValue > 39.5) {
|
||||
maxValue = 38.5 + Math.random();
|
||||
maxValue = 38.5 + Math.random() * 0.5;
|
||||
}
|
||||
DecimalFormat df = new DecimalFormat("#.0");
|
||||
maxValue = Double.parseDouble(df.format(maxValue));
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||
public class BackHandFragment extends BaseFragment<ActivityBackHandBinding> {
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private OkHttpService service = new OkHttpService();
|
||||
private int countdownSeconds = 3;
|
||||
private int countdownSeconds = 4;
|
||||
private Runnable countdownRunnable;
|
||||
|
||||
private SurfaceView mSurfaceView;
|
||||
|
|
@ -126,7 +126,7 @@ public class BackHandFragment extends BaseFragment<ActivityBackHandBinding> {
|
|||
|
||||
}
|
||||
private void startUpdateTime() {
|
||||
countdownSeconds = 3;
|
||||
countdownSeconds = 4;
|
||||
countdownRunnable = new Runnable() {
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
|
|
@ -476,7 +476,7 @@ public class BackHandFragment extends BaseFragment<ActivityBackHandBinding> {
|
|||
Log.w(TAG, "相机启动超时");
|
||||
recoverCamera();
|
||||
}
|
||||
}, 3000); // 3秒超时
|
||||
}, 4000); // 3秒超时
|
||||
}
|
||||
|
||||
// 停止后台线程
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ public class FaceFragment extends BaseFragment<ActivityFaceBinding> {
|
|||
Camera.Size lastPreviewSize = previewSize;
|
||||
previewSize = camera.getParameters().getPreviewSize();
|
||||
drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
|
||||
, cameraId, false, false, false);
|
||||
, cameraId, true, false, false);
|
||||
|
||||
// 切换相机的时候可能会导致预览尺寸发生变化
|
||||
if (faceHelper == null ||
|
||||
|
|
@ -475,7 +475,7 @@ public class FaceFragment extends BaseFragment<ActivityFaceBinding> {
|
|||
cameraHelper = new CameraHelper.Builder()
|
||||
.previewViewSize(new Point(previewView.getMeasuredWidth(), previewView.getMeasuredHeight()))
|
||||
.rotation(0)
|
||||
.isMirror(false)
|
||||
.isMirror(true)
|
||||
.previewOn(previewView)
|
||||
.cameraListener(cameraListener)
|
||||
.specificCameraId(0)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||
public class PalmFragment extends BaseFragment<ActivityPlamBinding> {
|
||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
private OkHttpService service = new OkHttpService();
|
||||
private int countdownSeconds = 3;
|
||||
private int countdownSeconds = 4;
|
||||
private Runnable countdownRunnable;
|
||||
|
||||
private SurfaceView mSurfaceView;
|
||||
|
|
@ -126,7 +126,7 @@ public class PalmFragment extends BaseFragment<ActivityPlamBinding> {
|
|||
|
||||
}
|
||||
private void startUpdateTime() {
|
||||
countdownSeconds = 3;
|
||||
countdownSeconds = 4;
|
||||
countdownRunnable = new Runnable() {
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -194,24 +194,30 @@ public class UpdateBasicData {
|
|||
}
|
||||
private void uploadToServer(List<CustPhotoFulInfo> uploadList) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("userFaceList", uploadList);
|
||||
String jsonString = json.toString();
|
||||
Log.i("getPersonMessage jsonString", jsonString);
|
||||
// 定义 JSON 的 MediaType
|
||||
MediaType mediaType = MediaType.parse(MEDIA_TYPE);
|
||||
// 创建 RequestBody
|
||||
RequestBody body = RequestBody.create(mediaType, jsonString);
|
||||
String result = service.httpPost(WorkConfig.getBaseUrl() + UrlConfig.SAVE_APP_FACE_EIGENVALUE, body, context);
|
||||
if (!ObjectUtil.isEmpty(result)) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(result);
|
||||
if (jsonObject.getString("msg").equals("操作成功") || jsonObject.getInteger("code") == 200) {
|
||||
Log.d(TAG, "人脸特征值上传成功");
|
||||
uploadList.forEach(item -> {
|
||||
List<CustPhotoFulInfo> list = new ArrayList<>();
|
||||
list.add(item);
|
||||
json.put("userFaceList", list);
|
||||
String jsonString = json.toString();
|
||||
Log.i("getPersonMessage jsonString", jsonString);
|
||||
// 定义 JSON 的 MediaType
|
||||
MediaType mediaType = MediaType.parse(MEDIA_TYPE);
|
||||
// 创建 RequestBody
|
||||
RequestBody body = RequestBody.create(mediaType, jsonString);
|
||||
String result = service.httpPost("http://192.168.20.234:48388" + UrlConfig.SAVE_APP_FACE_EIGENVALUE, body, context);
|
||||
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 {
|
||||
Log.d(TAG, "人脸特征值上传失败");
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "人脸特征值上传失败");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
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