|
@@ -3,11 +3,13 @@ import 'dart:math';
|
|
|
import 'dart:typed_data';
|
|
|
import 'dart:ui' as ui;
|
|
|
|
|
|
+import 'package:fis_common/index.dart';
|
|
|
import 'package:fis_common/logger/logger.dart';
|
|
|
import 'package:fis_i18n/i18n.dart';
|
|
|
import 'package:fis_jsonrpc/rpc.dart';
|
|
|
import 'package:fis_measure/process/language/measure_language.dart';
|
|
|
import 'package:fis_measure/process/visual/visual.dart';
|
|
|
+import 'package:fis_measure/process/workspace/measure_data_controller.dart';
|
|
|
import 'package:fis_measure/process/workspace/rpc_helper.dart';
|
|
|
import 'package:fis_measure/process/workspace/visual_loader.dart';
|
|
|
import 'package:fis_measure/utils/prompt_box.dart';
|
|
@@ -25,12 +27,13 @@ import 'package:http/http.dart' as http;
|
|
|
|
|
|
class AiResultModifierController extends GetxController {
|
|
|
final rpcHelper = Get.find<RPCHelper>();
|
|
|
+ MeasureDataController get measureData => Get.find<MeasureDataController>();
|
|
|
|
|
|
/// 后台语言包控制器
|
|
|
// final languageService = Get.find<LanguageService>();
|
|
|
final state = AiResultModifierState();
|
|
|
|
|
|
- /// 传入参数 [图像code,图像帧下标,图像元数据]
|
|
|
+ /// 传入参数 [图像code,图像帧下标,图像元数据, 图像编辑过的code]
|
|
|
final String remedicalCode;
|
|
|
final int currFrameIndex;
|
|
|
final VidUsImage currFrame;
|
|
@@ -112,6 +115,12 @@ class AiResultModifierController extends GetxController {
|
|
|
List<AIDetectedObject> get aiDetectedObjectList =>
|
|
|
modifiedDataDTO.diagResultsForEachOrgan?.first.detectedObjects ?? [];
|
|
|
|
|
|
+ /// 当前病灶
|
|
|
+ AIDetectedObject? get aiDetectedObject => modifiedDataDTO
|
|
|
+ .diagResultsForEachOrgan
|
|
|
+ ?.first
|
|
|
+ .detectedObjects?[currentAiDetectedObjectIndex];
|
|
|
+
|
|
|
List<Offset> get aiPoints => _aiPoints;
|
|
|
|
|
|
List<Offset> get canvasAffectedKeyPoints => _canvasAffectedKeyPoints;
|
|
@@ -140,7 +149,10 @@ class AiResultModifierController extends GetxController {
|
|
|
|
|
|
/// 病灶横纵比
|
|
|
String get lesionRatio =>
|
|
|
- _verticalLengthInPixel / _horizontalLengthInPixel > 1 ? '> 1' : '< 1';
|
|
|
+ _verticalLengthInPixel / _horizontalLengthInPixel > 1 ||
|
|
|
+ _verticalLengthInPixel / _horizontalLengthInPixel == 1
|
|
|
+ ? '> 1'
|
|
|
+ : '< 1';
|
|
|
|
|
|
/// 切换操作模式
|
|
|
void changeModifierMode(AiResultModifierMode newMode) {
|
|
@@ -229,12 +241,12 @@ class AiResultModifierController extends GetxController {
|
|
|
await orginalFileImage.toByteData(format: ui.ImageByteFormat.png);
|
|
|
final orginalFileByteDataBuffer =
|
|
|
orginalFileByteData!.buffer.asUint8List();
|
|
|
- final String originFileUrl = await rpcHelper.rpc.storage.uploadUint8List(
|
|
|
+ final String aiFileToken = await rpcHelper.rpc.storage.uploadUint8List(
|
|
|
orginalFileByteDataBuffer,
|
|
|
"ai_modified_orginal_${remedicalCode}_$currFrameIndex.png",
|
|
|
rpcHelper.userToken) ??
|
|
|
'';
|
|
|
- print('coverUrl: $originFileUrl');
|
|
|
+ print('coverUrl: $aiFileToken');
|
|
|
|
|
|
/// 生成缩略图
|
|
|
final double scale = _calcScale(
|
|
@@ -266,11 +278,10 @@ class AiResultModifierController extends GetxController {
|
|
|
'';
|
|
|
print('previewFileUrl: $previewFileUrl');
|
|
|
return ImageUrls(
|
|
|
- originFileUrl: originFileUrl, previewFileUrl: previewFileUrl);
|
|
|
+ aiFileToken: aiFileToken, previewFileUrl: previewFileUrl);
|
|
|
} on Exception catch (e) {
|
|
|
logger.e('get screenshot failed', e);
|
|
|
- return ImageUrls(
|
|
|
- originFileUrl: '', previewFileUrl: '', isUploaded: false);
|
|
|
+ return ImageUrls(aiFileToken: '', previewFileUrl: '', isUploaded: false);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -402,8 +413,9 @@ class AiResultModifierController extends GetxController {
|
|
|
}
|
|
|
|
|
|
/// 重置AI结果
|
|
|
- void resetAIResult() {
|
|
|
- _initAIResult();
|
|
|
+ void resetAIResult() async {
|
|
|
+ await _initAIResult();
|
|
|
+ update(['ai_conclusion_result', 'ai_result_sleek_circular_slider']);
|
|
|
}
|
|
|
|
|
|
@override
|
|
@@ -413,8 +425,9 @@ class AiResultModifierController extends GetxController {
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
- void onInit() {
|
|
|
+ void onInit() async {
|
|
|
super.onInit();
|
|
|
+ await _getDiagnosisEnumItemsAsync();
|
|
|
_updateModifierInteractiveLayerSize();
|
|
|
_updateImagePhysicalSize();
|
|
|
_initAIResult();
|
|
@@ -530,21 +543,26 @@ class AiResultModifierController extends GetxController {
|
|
|
PromptBox.toast(i18nBook.user.saveFailed.t);
|
|
|
return;
|
|
|
}
|
|
|
+ bool hasRemedicalAISelectedInfoCode = measureData
|
|
|
+ .measureImageData.remedicalAISelectedInfoCode.isNotNullOrEmpty;
|
|
|
final result =
|
|
|
await rpcHelper.rpc.remedical.saveRemedicalAISelectedInfoAsync(
|
|
|
SaveRemedicalAISelectedInfoRequest(
|
|
|
token: rpcHelper.userToken,
|
|
|
- remedicalCode: remedicalCode,
|
|
|
- code: code,
|
|
|
+ remedicalCode: hasRemedicalAISelectedInfoCode ? null : remedicalCode,
|
|
|
+ code: hasRemedicalAISelectedInfoCode
|
|
|
+ ? measureData.measureImageData.remedicalAISelectedInfoCode
|
|
|
+ : null,
|
|
|
frameIndex: currFrameIndex,
|
|
|
+ // diagnosisConclusion: diagnosisOrgan,
|
|
|
previewFileToken: imageUrls.previewFileUrl,
|
|
|
- orginalFileToken: imageUrls.originFileUrl,
|
|
|
+ aIFileToken: imageUrls.aiFileToken,
|
|
|
diagnosisData: jsonEncode(modifiedDataDTO),
|
|
|
),
|
|
|
);
|
|
|
if (result) {
|
|
|
PromptBox.toast(
|
|
|
- "${i18nBook.user.saveSuccess.t} ${i18nBook.measure.saveLocation.t + ' > ' + i18nBook.measure.aiImage.t}");
|
|
|
+ "${i18nBook.user.saveSuccess.t} \r\n ${i18nBook.measure.saveLocation.t + ' > ' + i18nBook.measure.aiImage.t}");
|
|
|
Get.back();
|
|
|
} else {
|
|
|
PromptBox.toast(i18nBook.user.saveFailed.t);
|
|
@@ -557,15 +575,22 @@ class AiResultModifierController extends GetxController {
|
|
|
/// 加载AI结果并调用绘制
|
|
|
Future<void> _initAIResult() async {
|
|
|
try {
|
|
|
- final result =
|
|
|
- await rpcHelper.rpc.remedical.getRemedicalDiagnosisDataAsync(
|
|
|
- GetRemedicalDiagnosisDataRequest(
|
|
|
- token: rpcHelper.userToken,
|
|
|
- remedicalCode: remedicalCode,
|
|
|
- frameIndex: currFrameIndex,
|
|
|
- ),
|
|
|
- );
|
|
|
- resultDTO = AIDiagnosisPerImageDTO.fromJson(jsonDecode(result));
|
|
|
+ if (measureData
|
|
|
+ .measureImageData.remedicalAISelectedInfoCode.isNotNullOrEmpty) {
|
|
|
+ resultDTO = AIDiagnosisPerImageDTO.fromJson(
|
|
|
+ jsonDecode(measureData.aiResults)[0]);
|
|
|
+ } else {
|
|
|
+ final result =
|
|
|
+ await rpcHelper.rpc.remedical.getRemedicalDiagnosisDataAsync(
|
|
|
+ GetRemedicalDiagnosisDataRequest(
|
|
|
+ token: rpcHelper.userToken,
|
|
|
+ remedicalCode: remedicalCode,
|
|
|
+ frameIndex: currFrameIndex,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ resultDTO = AIDiagnosisPerImageDTO.fromJson(jsonDecode(result));
|
|
|
+ }
|
|
|
+
|
|
|
modifiedDataDTO = resultDTO;
|
|
|
contours = resultDTO.diagResultsForEachOrgan![0]
|
|
|
.detectedObjects![currentAiDetectedObjectIndex].contours ??
|
|
@@ -585,7 +610,6 @@ class AiResultModifierController extends GetxController {
|
|
|
_canvasAffectedKeyPoints.clear();
|
|
|
_updateCurrContoursPoints();
|
|
|
_updateCurrKeyPoints();
|
|
|
- await _getDiagnosisEnumItemsAsync();
|
|
|
update(['ai_result_canvas', 'ai_result_panel', 'ai_index_tag']);
|
|
|
} catch (e) {
|
|
|
logger.e('load ai result failed', e);
|
|
@@ -980,7 +1004,7 @@ extension StorageServiceExt on StorageService {
|
|
|
|
|
|
class ImageUrls {
|
|
|
/// 原始图像地址
|
|
|
- String originFileUrl;
|
|
|
+ String aiFileToken;
|
|
|
|
|
|
/// 缩略图地址
|
|
|
String previewFileUrl;
|
|
@@ -989,7 +1013,7 @@ class ImageUrls {
|
|
|
bool isUploaded = true;
|
|
|
|
|
|
ImageUrls({
|
|
|
- required this.originFileUrl,
|
|
|
+ required this.aiFileToken,
|
|
|
required this.previewFileUrl,
|
|
|
this.isUploaded = true,
|
|
|
});
|