Commit a6cc253b authored by 姜天宇's avatar 姜天宇

feat:移除了目标检测阈值限制;增加本地图片学习;增加LOGO;修复安装APK后出现两个图标的问题;

parent 5bc4a8c6
...@@ -3,16 +3,35 @@ plugins { ...@@ -3,16 +3,35 @@ plugins {
id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.android'
} }
def APP_VERSION_CODE = 1000201
def APP_VERSION_NAME = "1.0.2.1"
android { android {
namespace 'com.wmdigit.cateringdetect' namespace 'com.wmdigit.cateringdetect'
compileSdk 33 compileSdk 33
signingConfigs {
debug {
storeFile file(Keystore)
storePassword 'wmdigit'
keyAlias 'wm'
keyPassword 'wmdigit'
}
release {
storeFile file(Keystore)
storePassword 'wmdigit'
keyAlias 'wm'
keyPassword 'wmdigit'
}
}
defaultConfig { defaultConfig {
applicationId "com.wmdigit.cateringdetect" applicationId "com.wmdigit.cateringdetect"
minSdk 26 minSdk 24
targetSdk 33 targetSdk 33
versionCode 1000201 versionCode APP_VERSION_CODE
versionName "v1.0.2.1" versionName APP_VERSION_NAME
signingConfig signingConfigs.release
ndk { ndk {
abiFilters 'armeabi-v7a' abiFilters 'armeabi-v7a'
...@@ -29,7 +48,7 @@ android { ...@@ -29,7 +48,7 @@ android {
buildTypes { buildTypes {
debug { debug {
buildConfigField 'String', 'POS_URL', '"https://se-test.frp.wmdigit.com/"' buildConfigField 'String', 'POS_URL', '"https://se.wmdigit.com/"'
resValue "string", "app_name", "餐饮服务-debug" resValue "string", "app_name", "餐饮服务-debug"
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
...@@ -48,6 +67,11 @@ android { ...@@ -48,6 +67,11 @@ android {
kotlinOptions { kotlinOptions {
jvmTarget = '17' jvmTarget = '17'
} }
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = 'WmCateringService-v' + APP_VERSION_NAME + '-' + variant.buildType.name + '.apk'
}
}
buildFeatures { buildFeatures {
viewBinding true viewBinding true
dataBinding true dataBinding true
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
android:largeHeap="true" android:largeHeap="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_wm_catering"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
......
...@@ -18,6 +18,10 @@ android { ...@@ -18,6 +18,10 @@ android {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
......
...@@ -25,6 +25,10 @@ android { ...@@ -25,6 +25,10 @@ android {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility JavaVersion.VERSION_17
......
...@@ -34,6 +34,10 @@ android { ...@@ -34,6 +34,10 @@ android {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
} }
compileOptions { compileOptions {
......
...@@ -36,14 +36,8 @@ Java_com_wmdigit_core_catering_dish_DishDetection_process(JNIEnv *env, jobject t ...@@ -36,14 +36,8 @@ Java_com_wmdigit_core_catering_dish_DishDetection_process(JNIEnv *env, jobject t
} }
// std::string labels; // std::string labels;
// 有效框的数量 // 有效框的数量
int rows = 0; int rows = output.output_list.size();
int cols = 4; int cols = 4;
// 统计符合阈值的框数量
for (size_t i = 0; i < output.output_list.size(); ++i) {
if (output.output_list[i].prob >= 0.8){
rows ++;
}
}
if (rows == 0){ if (rows == 0){
mat.release(); mat.release();
mat_bgr.release(); mat_bgr.release();
...@@ -60,16 +54,13 @@ Java_com_wmdigit_core_catering_dish_DishDetection_process(JNIEnv *env, jobject t ...@@ -60,16 +54,13 @@ Java_com_wmdigit_core_catering_dish_DishDetection_process(JNIEnv *env, jobject t
LOGD("size: %d", output.output_list.size()); LOGD("size: %d", output.output_list.size());
int size = output.output_list.size(); int size = output.output_list.size();
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
// 根据阈值,筛选出有效的框 // 记录框的左上、右下点坐标
if (output.output_list[i].prob >= 0.8){ rect_array[i][0] = (int)output.output_list[i].x1;
// 记录框的左上、右下点坐标 rect_array[i][1] = (int)output.output_list[i].y1;
rect_array[i][0] = (int)output.output_list[i].x1; rect_array[i][2] = (int)output.output_list[i].x2;
rect_array[i][1] = (int)output.output_list[i].y1; rect_array[i][3] = (int)output.output_list[i].y2;
rect_array[i][2] = (int)output.output_list[i].x2; // 记录框的特征值
rect_array[i][3] = (int)output.output_list[i].y2; feature_array[i] = output.output_list[i].feat;
// 记录框的特征值
feature_array[i] = output.output_list[i].feat;
}
LOGD("%f, %f, %f, %f, %f", LOGD("%f, %f, %f, %f, %f",
output.output_list[i].x1, output.output_list[i].x1,
output.output_list[i].y1, output.output_list[i].y1,
......
...@@ -31,14 +31,8 @@ Java_com_wmdigit_core_catering_plate_PlateDetection_process(JNIEnv *env, jobject ...@@ -31,14 +31,8 @@ Java_com_wmdigit_core_catering_plate_PlateDetection_process(JNIEnv *env, jobject
} }
// std::string labels; // std::string labels;
// 有效框的数量 // 有效框的数量
int rows = 0; int rows = output.output_list.size();
int cols = 4; int cols = 4;
// 统计符合阈值的框数量
for (size_t i = 0; i < output.output_list.size(); ++i) {
if (output.output_list[i].prob >= 0.7){
rows ++;
}
}
if (rows == 0){ if (rows == 0){
mat.release(); mat.release();
mat_bgr.release(); mat_bgr.release();
...@@ -53,16 +47,13 @@ Java_com_wmdigit_core_catering_plate_PlateDetection_process(JNIEnv *env, jobject ...@@ -53,16 +47,13 @@ Java_com_wmdigit_core_catering_plate_PlateDetection_process(JNIEnv *env, jobject
auto** feature_array = (float **) malloc(rows * sizeof (float *)); auto** feature_array = (float **) malloc(rows * sizeof (float *));
// 遍历识别结果 // 遍历识别结果
for (size_t i = 0; i < output.output_list.size(); ++i) { for (size_t i = 0; i < output.output_list.size(); ++i) {
// 根据阈值,筛选出有效的框 // 记录框的左上、右下点坐标
if (output.output_list[i].prob >= 0.75){ rect_array[i][0] = (int)output.output_list[i].x1;
// 记录框的左上、右下点坐标 rect_array[i][1] = (int)output.output_list[i].y1;
rect_array[i][0] = (int)output.output_list[i].x1; rect_array[i][2] = (int)output.output_list[i].x2;
rect_array[i][1] = (int)output.output_list[i].y1; rect_array[i][3] = (int)output.output_list[i].y2;
rect_array[i][2] = (int)output.output_list[i].x2; // 记录框的特征值
rect_array[i][3] = (int)output.output_list[i].y2; feature_array[i] = output.output_list[i].feat;
// 记录框的特征值
feature_array[i] = output.output_list[i].feat;
}
LOGD("%f, %f, %f, %f, %f", LOGD("%f, %f, %f, %f, %f",
output.output_list[i].x1, output.output_list[i].x1,
output.output_list[i].y1, output.output_list[i].y1,
......
package com.wmdigit.core.catering; package com.wmdigit.core.catering;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import com.wmdigit.common.model.CropValueDTO; import com.wmdigit.common.model.CropValueDTO;
import com.wmdigit.core.catering.dish.DishDetection; import com.wmdigit.core.catering.dish.DishDetection;
...@@ -9,6 +12,13 @@ import com.wmdigit.core.catering.plate.PlateDetection; ...@@ -9,6 +12,13 @@ import com.wmdigit.core.catering.plate.PlateDetection;
import com.wmdigit.data.mmkv.repository.AiLocalRepository; import com.wmdigit.data.mmkv.repository.AiLocalRepository;
import com.wmdigit.data.mmkv.repository.CropLocalRepository; import com.wmdigit.data.mmkv.repository.CropLocalRepository;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/** /**
* 目标检测管理类 * 目标检测管理类
* @author dizi * @author dizi
...@@ -89,6 +99,41 @@ public class TargetDetectionRepository { ...@@ -89,6 +99,41 @@ public class TargetDetectionRepository {
return result; return result;
} }
/**
* 推理目标检测处理后的图片
* 该方法用于处理在目标检测后对图片进行进一步推理,以获取图片的特征向量
* 主要步骤包括:获取裁剪参数、创建背景画布、将原图居中绘制在背景上、进行目标检测推理、返回特征向量
*
* @param bitmap 待处理的图片位图
* @return 返回图片的特征向量,如果没有检测到目标或发生错误,则返回null
*/
public float[] processImageAfterTargetDetection(Bitmap bitmap){
// 获取裁剪参数,用于确定最终图片的尺寸
CropValueDTO cropValueDTO = CropLocalRepository.getInstance().getCropValue();
// 确定最终图片的宽度和高度,取原图和裁剪参数中的最大值
int width = Math.max(bitmap.getWidth(), cropValueDTO.getWidth());
int height = Math.max(bitmap.getHeight(), cropValueDTO.getHeight());
// 创建一个空图背景
Bitmap background = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas backgroundCanvas = new Canvas(background);
// 填充背景颜色为灰色
backgroundCanvas.drawColor(Color.rgb(127, 127, 127));
// 计算原图在背景上的居中位置
int left = (width - bitmap.getWidth()) / 2;
int top = (height - bitmap.getHeight()) / 2;
// 在背景上创建最终的画布,并将原图居中绘制上去
Canvas finalCanvas = new Canvas(background);
finalCanvas.drawBitmap(bitmap, left, top, new Paint());
// 使用目标检测模型对处理后的图片进行推理
TargetDetectResult result = targetDetection.processImage(background);
// 如果检测到目标并且存在特征向量,则返回第一个特征向量
if (result != null && result.getFeatures() != null && result.getFeatures().length > 0){
return result.getFeatures()[0];
}
// 如果没有检测到目标或没有特征向量,则返回null
return null;
}
/** /**
* 释放资源 * 释放资源
*/ */
......
...@@ -7,7 +7,7 @@ android { ...@@ -7,7 +7,7 @@ android {
compileSdk 33 compileSdk 33
defaultConfig { defaultConfig {
minSdk 26 minSdk 24
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro" consumerProguardFiles "consumer-rules.pro"
......
...@@ -107,33 +107,6 @@ public class DiskRepository { ...@@ -107,33 +107,6 @@ public class DiskRepository {
} }
} }
/* public void cleanOrphanedImages(){
String folderPath = LocalDataModule.getAppContext().getExternalFilesDir(FOLDER_NAME_PRODUCT_LEARNING_RECORDS).getAbsolutePath();
File rootImageDir = new File(folderPath);
if (!rootImageDir.exists()){
return;
}
long startTime = System.currentTimeMillis();
Set<String> dbImgPaths = new ConcurrentSkipListSet<>(FeaturesRepository.getInstance().getAllImgPath());
try (Stream<Path> pathStream = Files.walk(rootImageDir.toPath())){
pathStream
.parallel()
.filter(Files::isRegularFile)
.forEach(filePath -> {
String absPath = filePath.toString();
if (!dbImgPaths.contains(absPath)) {
try {
Files.delete(filePath);
} catch (IOException e) {
XLog.e(e);
}
}
});
}
catch (Exception e){
XLog.e(e);
}
}*/
/** /**
* 将产品的学习记录打包成zip文件 * 将产品的学习记录打包成zip文件
...@@ -187,4 +160,60 @@ public class DiskRepository { ...@@ -187,4 +160,60 @@ public class DiskRepository {
} }
} }
/**
* 查询本地学习图片
*
* 本方法用于扫描应用外部文件目录下特定文件夹中的所有jpg图片,并返回这些图片的绝对路径列表
* 主要步骤包括:
* 1. 获取应用外部文件目录下的特定文件夹(产品学习记录文件夹)
* 2. 检查该文件夹是否存在,以及是否包含子文件夹
* 3. 遍历每个子文件夹,寻找jpg格式的图片
* 4. 将找到的图片的绝对路径添加到列表中并返回
*
* @return 包含所有找到的学习图片绝对路径的列表
*/
public List<String> searchLocalLearnedImages(){
// 初始化图片路径列表
List<String> paths = new ArrayList<>();
// 获取产品学习记录文件夹的绝对路径
String productLearningRecordsRootPath = LocalDataModule.getAppContext().getExternalFilesDir(FOLDER_NAME_PRODUCT_LEARNING_RECORDS).getAbsolutePath();
// 创建根文件夹对象
File rootFolder = new File(productLearningRecordsRootPath);
// 获取根文件夹下的所有子文件夹
File[] subFolders = rootFolder.listFiles();
// 如果根文件夹不存在或没有子文件夹,则直接返回空的路径列表
if (!rootFolder.exists() || subFolders == null || subFolders.length == 0){
return paths;
}
// 遍历所有子文件夹
for (File subFolder : subFolders){
// 如果当前子文件夹不是目录,则跳过
if (!subFolder.isDirectory()){
continue;
}
// 获取当前子文件夹下的所有文件
File[] images = subFolder.listFiles();
// 遍历所有文件,寻找jpg格式的图片
for (File image : images){
// 如果文件不是jpg格式,则跳过
if (!image.getName().endsWith(".jpg")){
continue;
}
// 将找到的jpg图片的绝对路径添加到路径列表中
paths.add(image.getAbsolutePath());
}
}
// 返回包含所有找到的学习图片绝对路径的列表
return paths;
}
} }
...@@ -15,14 +15,14 @@ android { ...@@ -15,14 +15,14 @@ android {
buildTypes { buildTypes {
debug { debug {
buildConfigField 'String', 'POS_URL', '"https://se-test.frp.wmdigit.com/"' buildConfigField 'String', 'POS_URL', '"https://se.wmdigit.com/"'
buildConfigField 'String', 'VERSION_CODE', '"1000200"' buildConfigField 'String', 'VERSION_CODE', '"1000201"'
minifyEnabled true minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
release { release {
buildConfigField 'String', 'POS_URL', '"https://se.wmdigit.com/"' buildConfigField 'String', 'POS_URL', '"https://se.wmdigit.com/"'
buildConfigField 'String', 'VERSION_CODE', '"1000200"' buildConfigField 'String', 'VERSION_CODE', '"1000201"'
minifyEnabled true minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
......
...@@ -22,4 +22,9 @@ kotlin.code.style=official ...@@ -22,4 +22,9 @@ kotlin.code.style=official
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.enableJetifier=true android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true android.defaults.buildfeatures.buildconfig=true
\ No newline at end of file
Keystore=../keystore.jks
StorePassword=wmdigit
KeyAlias=wm
KeyPassword=wmdigit
\ No newline at end of file
...@@ -17,6 +17,10 @@ v1.0.2 2024/08/06 1.增加系统信息页 ...@@ -17,6 +17,10 @@ v1.0.2 2024/08/06 1.增加系统信息页
14.摄像头改为UvcCamera 14.摄像头改为UvcCamera
v1.0.2.1 2025/04/22 1.特征表增加字段记录图片地址,数据库版本升级1=>2 v1.0.2.1 2025/04/22 1.特征表增加字段记录图片地址,数据库版本升级1=>2
2.增加本地导入导出功能 2.增加本地导入导出功能
3.移除了目标检测阈值限制
4.增加本地图片学习
5.增加LOGO
6.修复安装APK后出现两个图标的问题
todo 增加学习记录管理模块 todo 增加学习记录管理模块
todo 替换LOGO todo 替换LOGO
......
...@@ -3,9 +3,7 @@ ...@@ -3,9 +3,7 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.CateringDetect"> android:theme="@style/Theme.CateringDetect">
<activity <activity
......
...@@ -3,19 +3,17 @@ ...@@ -3,19 +3,17 @@
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.CateringDetect"> android:theme="@style/Theme.CateringDetect">
<activity <activity
android:name=".SettingActivity" android:name=".SettingActivity"
android:exported="true" android:exported="true"
android:windowSoftInputMode="stateVisible|adjustPan"> android:windowSoftInputMode="stateVisible|adjustPan">
<intent-filter> <!-- <intent-filter>-->
<action android:name="android.intent.action.MAIN" /> <!-- <action android:name="android.intent.action.MAIN" />-->
<category android:name="android.intent.category.LAUNCHER" /> <!-- <category android:name="android.intent.category.LAUNCHER" />-->
</intent-filter> <!-- </intent-filter>-->
</activity> </activity>
</application> </application>
......
...@@ -62,11 +62,16 @@ public class DataManagerFragment extends BaseMvvmFragment<DataManagerViewModel, ...@@ -62,11 +62,16 @@ public class DataManagerFragment extends BaseMvvmFragment<DataManagerViewModel,
break; break;
case 4: case 4:
// 学习本地图片
learnLocalImages();
break;
case 5:
// 解绑POS // 解绑POS
unbindPos(); unbindPos();
break; break;
case 5: case 6:
// 下载远程工具 // 下载远程工具
downloadRemoteTool(); downloadRemoteTool();
break; break;
...@@ -77,6 +82,18 @@ public class DataManagerFragment extends BaseMvvmFragment<DataManagerViewModel, ...@@ -77,6 +82,18 @@ public class DataManagerFragment extends BaseMvvmFragment<DataManagerViewModel,
}); });
} }
/**
* 学习本地图片
*/
private void learnLocalImages(){
mSecondConfirmWindow.setTitle(getString(com.wmdigit.common.R.string.prompt))
.setContent(getString(R.string.confirm_learn_local_images))
.setClickListener(() -> {
mViewModel.learnLocalImages();
})
.showWindow();
}
/** /**
* 导入学习数据 * 导入学习数据
*/ */
......
package com.wmdigit.setting.viewmodel; package com.wmdigit.setting.viewmodel;
import android.app.Application; import android.app.Application;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.elvishew.xlog.XLog; import com.elvishew.xlog.XLog;
import com.wmdigit.common.base.mvvm.BaseViewModel; import com.wmdigit.common.base.mvvm.BaseViewModel;
import com.wmdigit.common.base.mvvm.SingleLiveEvent; import com.wmdigit.common.base.mvvm.SingleLiveEvent;
import com.wmdigit.core.catering.TargetDetectionRepository;
import com.wmdigit.core.hnsw.HnswRepository; import com.wmdigit.core.hnsw.HnswRepository;
import com.wmdigit.data.database.repository.ExportFeaturesRepository; import com.wmdigit.data.database.repository.ExportFeaturesRepository;
import com.wmdigit.data.database.repository.FeaturesRepository; import com.wmdigit.data.database.repository.FeaturesRepository;
import com.wmdigit.data.database.repository.ProductsRepository; import com.wmdigit.data.database.repository.ProductsRepository;
import com.wmdigit.data.disk.repository.DiskRepository;
import com.wmdigit.data.mmkv.repository.CropLocalRepository;
import com.wmdigit.network.repository.UserRemoteRepository; import com.wmdigit.network.repository.UserRemoteRepository;
import com.wmdigit.setting.R; import com.wmdigit.setting.R;
import com.wmdigit.setting.model.FuncButton; import com.wmdigit.setting.model.FuncButton;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
/** /**
* 数据管理页ViewModel * 数据管理页ViewModel
...@@ -40,10 +52,60 @@ public class DataManagerViewModel extends BaseViewModel { ...@@ -40,10 +52,60 @@ public class DataManagerViewModel extends BaseViewModel {
funcButtons.add(new FuncButton(getApplication().getString(R.string.import_learning_data), R.drawable.ic_download_learning_data)); funcButtons.add(new FuncButton(getApplication().getString(R.string.import_learning_data), R.drawable.ic_download_learning_data));
funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_clear_learning_data), R.drawable.ic_clear_data_red)); funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_clear_learning_data), R.drawable.ic_clear_data_red));
funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_clear_products), R.drawable.ic_clean_learning_data)); funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_clear_products), R.drawable.ic_clean_learning_data));
funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_learn_local_images), R.drawable.ic_learn_local_images));
funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_unbind), R.drawable.ic_unbind)); funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_unbind), R.drawable.ic_unbind));
funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_download_remote_tool), R.drawable.ic_download_remote)); funcButtons.add(new FuncButton(getApplication().getString(R.string.module_setting_download_remote_tool), R.drawable.ic_download_remote));
} }
/**
* 学习本地图像功能
* 该方法用于处理本地图像学习过程,包括检查是否已裁剪图像、是否有图像可供学习,
* 以及实际的学习过程和结果处理
*/
public void learnLocalImages(){
// 检查是否已裁剪图像,如果没有则提示用户先进行裁剪
if(!CropLocalRepository.getInstance().getHasCropped()){
toastMessage.postValue(getApplication().getString(R.string.module_setting_please_crop_first));
return;
}
// 判断是否有数据
List<String> imagePaths = DiskRepository.getInstance().searchLocalLearnedImages();
// 如果没有图像可供学习,则提示用户
if (imagePaths.size() == 0){
toastMessage.postValue(getApplication().getString(R.string.no_learning_local_image));
return;
}
// 开始学习图像,显示加载中信息
loadingProgressText.postValue(getApplication().getString(R.string.learning_local_images));
compositeDisposable.add(
Observable.create(emitter -> {
// 遍历所有图像,进行学习处理
for (String path : imagePaths){
XLog.d("正在学习" + path);
Bitmap bitmap = BitmapFactory.decodeFile(path);
float[] features = TargetDetectionRepository.getInstance().processImageAfterTargetDetection(bitmap);
if (features != null){
String productCode = new File(path).getParentFile().getName();
FeaturesRepository.getInstance().insert(productCode, features, path);
}
}
emitter.onNext(true);
}).flatMap(obj->HnswRepository.getInstance().initializeHnswData())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(success->{
// 学习成功,隐藏加载中信息并提示用户成功
loadingProgressText.postValue("");
toastMessage.postValue(getApplication().getString(R.string.learn_local_image_success));
}, error->{
// 学习失败,隐藏加载中信息并提示用户失败
loadingProgressText.postValue("");
toastMessage.postValue(getApplication().getString(R.string.learn_local_image_fail));
})
);
}
/** /**
* 导出学习数据 * 导出学习数据
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
<string name="module_setting_confirm_clear_learning_data">请确认是否清空学习数据?</string> <string name="module_setting_confirm_clear_learning_data">请确认是否清空学习数据?</string>
<string name="module_setting_confirm_clear_product_data">请确认是否清空商品数据?</string> <string name="module_setting_confirm_clear_product_data">请确认是否清空商品数据?</string>
<string name="module_setting_clear_products">清空商品数据</string> <string name="module_setting_clear_products">清空商品数据</string>
<string name="module_setting_learn_local_images">学习本地图片</string>
<string name="module_setting_unbind">SN解绑</string> <string name="module_setting_unbind">SN解绑</string>
<string name="module_setting_download_remote_tool">下载远程工具</string> <string name="module_setting_download_remote_tool">下载远程工具</string>
<string name="module_setting_ai_config">AI配置</string> <string name="module_setting_ai_config">AI配置</string>
...@@ -52,12 +53,17 @@ ...@@ -52,12 +53,17 @@
<string name="import_learning_data">导入学习数据</string> <string name="import_learning_data">导入学习数据</string>
<string name="confirm_export_learning_data">请确认是否导出学习数据?</string> <string name="confirm_export_learning_data">请确认是否导出学习数据?</string>
<string name="confirm_import_learning_data">请确认是否导入学习数据?</string> <string name="confirm_import_learning_data">请确认是否导入学习数据?</string>
<string name="confirm_learn_local_images">请确认是否将本地图片加入学习库?</string>
<string name="learning_local_images">正在学习本地图片,请勿中断操作</string>
<string name="exporting_learning_data">正在导出学习数据,请勿中断操作</string> <string name="exporting_learning_data">正在导出学习数据,请勿中断操作</string>
<string name="importing_learning_data">正在导入学习数据,请勿中断操作</string> <string name="importing_learning_data">正在导入学习数据,请勿中断操作</string>
<string name="export_learning_data_no_data">本地没有学习数据,导出终止</string> <string name="export_learning_data_no_data">本地没有学习数据,导出终止</string>
<string name="no_learning_local_image">本地没有可学习的图片,学习终止</string>
<string name="export_success">学习数据导出成功</string> <string name="export_success">学习数据导出成功</string>
<string name="export_failed">学习数据导出失败,请联系运维人员</string> <string name="export_failed">学习数据导出失败,请联系运维人员</string>
<string name="import_database_file_not_exits">待导入的数据库文件不存在</string> <string name="import_database_file_not_exits">待导入的数据库文件不存在</string>
<string name="import_success">导入成功</string> <string name="import_success">导入成功</string>
<string name="import_failed">导入失败</string> <string name="import_failed">导入失败</string>
<string name="learn_local_image_success">学习本地图片成功</string>
<string name="learn_local_image_fail">学习本地图片失败</string>
</resources> </resources>
\ No newline at end of file
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.CateringDetect"> android:theme="@style/Theme.CateringDetect">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment