|
@@ -1,11 +1,6 @@
|
|
|
-import 'dart:convert';
|
|
|
-
|
|
|
import 'package:fis_measure/interfaces/date_types/int_size.dart';
|
|
|
-import 'package:fis_measure/interfaces/process/player/play_controller.dart';
|
|
|
import 'package:fis_measure/interfaces/process/workspace/application.dart';
|
|
|
-import 'package:fis_measure/process/workspace/measure_data_controller.dart';
|
|
|
-import 'package:fis_measure/view/paint/date_structure.dart';
|
|
|
-import 'package:fis_measure/view/paint/parts/ai_result.dart';
|
|
|
+import 'package:fis_measure/view/paint/ai_patint_controller.dart';
|
|
|
import 'package:fis_measure/view/paint/parts/dash_line.dart';
|
|
|
import 'package:fis_measure/view/paint/parts/dots.dart';
|
|
|
import 'package:fis_measure/view/paint/parts/rectangle.dart';
|
|
@@ -33,74 +28,24 @@ class AIPaintInfo extends StatefulWidget {
|
|
|
}
|
|
|
|
|
|
class _AIPaintInfoState extends State<AIPaintInfo> {
|
|
|
- static const _HAS_VIEW_STATUS_ARR = [VidPlayStatus.play, VidPlayStatus.pause];
|
|
|
-
|
|
|
- late final application = Get.find<IApplication>();
|
|
|
-
|
|
|
- /// ai结果
|
|
|
- late final List<AIDiagnosisPerImageDTO> aiResult = [];
|
|
|
-
|
|
|
- /// 测量AI数据
|
|
|
- final measureData = Get.find<MeasureDataController>();
|
|
|
-
|
|
|
- /// 播放控制器
|
|
|
- final playerController = Get.find<IPlayerController>();
|
|
|
-
|
|
|
- /// ai结果图展示
|
|
|
- late List<Offset> aiResultsList = [];
|
|
|
-
|
|
|
- /// ai结果数据
|
|
|
- late List<AIDetectedObject> aiDetectedObject = [];
|
|
|
-
|
|
|
- /// ai部位
|
|
|
- late DiagnosisOrganEnum diagnosisOrgan = DiagnosisOrganEnum.Null;
|
|
|
-
|
|
|
- /// 是否是播放状态
|
|
|
- get isPlay => playerController.status == VidPlayStatus.play;
|
|
|
+ late final aiPatintController = Get.put(
|
|
|
+ AiPatintController(
|
|
|
+ widget.controller,
|
|
|
+ ),
|
|
|
+ );
|
|
|
|
|
|
- /// ai json 数据
|
|
|
- late String? aiResults = '';
|
|
|
-
|
|
|
- /// ai的横纵坐标 四个点
|
|
|
- late Offset p1 = Offset.zero;
|
|
|
- late Offset p2 = Offset.zero;
|
|
|
- late Offset p3 = Offset.zero;
|
|
|
- late Offset p4 = Offset.zero;
|
|
|
-
|
|
|
- /// 视频时的画面
|
|
|
- double left = -1;
|
|
|
- double top = -1;
|
|
|
- double width = -1;
|
|
|
- double height = -1;
|
|
|
-
|
|
|
- /// 当前帧数
|
|
|
- int? frameIndex;
|
|
|
-
|
|
|
- /// ai结果下标
|
|
|
- int aiResultIndex = 0;
|
|
|
+ @override
|
|
|
+ void initState() {
|
|
|
+ //监听Widget是否绘制完毕
|
|
|
+ super.initState();
|
|
|
+ widget.controller.eventHandler.addListener(onControllerEvent);
|
|
|
+ }
|
|
|
|
|
|
- void onMeasuredAIResultsInfoChanged(Object sender, String e) {
|
|
|
- if (e.isNotEmpty && e != "[]") {
|
|
|
- aiResults = e;
|
|
|
- final measureDataAIResults = jsonDecode(
|
|
|
- aiResults ?? '',
|
|
|
- );
|
|
|
- aiResult.clear();
|
|
|
- setState(() {
|
|
|
- for (int i = 0; i < (measureDataAIResults as List).length; i++) {
|
|
|
- aiResult.add(
|
|
|
- AIDiagnosisPerImageDTO.fromJson(
|
|
|
- measureDataAIResults[i],
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
- });
|
|
|
- } else {
|
|
|
- setState(() {
|
|
|
- aiResults = '';
|
|
|
- aiResult.clear();
|
|
|
- });
|
|
|
- }
|
|
|
+ @override
|
|
|
+ void dispose() {
|
|
|
+ super.dispose();
|
|
|
+ // widget.controller.eventHandler.removeListener(onControllerEvent);
|
|
|
+ // _removeListenrs();
|
|
|
}
|
|
|
|
|
|
void onControllerEvent(Object sender, VidPlayerEvent e) {
|
|
@@ -122,7 +67,7 @@ class _AIPaintInfoState extends State<AIPaintInfo> {
|
|
|
|
|
|
void onFrameChanged(VidPlayerFrameIndexChangeEvent e) {
|
|
|
setState(() {
|
|
|
- frameIndex = e.index;
|
|
|
+ aiPatintController.state.frameIndex = e.index;
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -130,110 +75,6 @@ class _AIPaintInfoState extends State<AIPaintInfo> {
|
|
|
setState(() {});
|
|
|
}
|
|
|
|
|
|
- /// 单帧图处理
|
|
|
- void onSingleFrameImage(
|
|
|
- List<AIDetectedObject>? detectedObjects,
|
|
|
- DiagnosisOrganEnum organ,
|
|
|
- double widthScale,
|
|
|
- ) {
|
|
|
- aiDetectedObject = detectedObjects ?? [];
|
|
|
- diagnosisOrgan = organ;
|
|
|
-
|
|
|
- for (int m = 0; m < detectedObjects!.length; m++) {
|
|
|
- final List<AIDiagnosisPoint2D>? contours = detectedObjects[m].contours;
|
|
|
- if (contours!.isNotEmpty && detectedObjects[m].descriptions!.isNotEmpty) {
|
|
|
- final descriptions = jsonDecode(
|
|
|
- detectedObjects[m]
|
|
|
- .descriptions![detectedObjects[m].descriptions!.length - 1]
|
|
|
- .value!,
|
|
|
- );
|
|
|
- if (_HAS_VIEW_STATUS_ARR
|
|
|
- .contains((playerController as VidPlayerController).status)) {
|
|
|
- for (int i = 0; i < contours.length; i++) {
|
|
|
- if (i % 10 == 0) {
|
|
|
- aiResultsList.add(Offset(
|
|
|
- contours[i].x * widthScale,
|
|
|
- contours[i].y * widthScale,
|
|
|
- ));
|
|
|
- }
|
|
|
- }
|
|
|
- p1 = Offset(descriptions['HorizontalPoint1']['X'] * widthScale,
|
|
|
- descriptions['HorizontalPoint1']['Y'] * widthScale);
|
|
|
- p2 = Offset(descriptions['HorizontalPoint2']['X'] * widthScale,
|
|
|
- descriptions['HorizontalPoint2']['Y'] * widthScale);
|
|
|
- p3 = Offset(descriptions['VerticalPoint1']['X'] * widthScale,
|
|
|
- descriptions['VerticalPoint1']['Y'] * widthScale);
|
|
|
- p4 = Offset(descriptions['VerticalPoint2']['X'] * widthScale,
|
|
|
- descriptions['VerticalPoint2']['Y'] * widthScale);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// ai处理图片结果
|
|
|
- bool onGetAIResultsInfo(double widthScale) {
|
|
|
- if (aiResult.isEmpty) {
|
|
|
- return false;
|
|
|
- } else if (aiResult.length == 1) {
|
|
|
- final diagResultsForEachOrgan =
|
|
|
- aiResult[0].diagResultsForEachOrgan?[aiResultIndex];
|
|
|
- final detectedObjects = diagResultsForEachOrgan!.detectedObjects;
|
|
|
- final diagnosisOrgan = diagResultsForEachOrgan.organ;
|
|
|
- _updateFeatures();
|
|
|
- if (detectedObjects!.isNotEmpty) {
|
|
|
- onSingleFrameImage(
|
|
|
- detectedObjects,
|
|
|
- diagnosisOrgan,
|
|
|
- widthScale,
|
|
|
- );
|
|
|
- } else {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
- } else {
|
|
|
- _updateFeatures();
|
|
|
- final diagResultsForEachOrgan =
|
|
|
- aiResult[frameIndex!].diagResultsForEachOrgan![aiResultIndex];
|
|
|
- final detectedObjects = diagResultsForEachOrgan.detectedObjects;
|
|
|
- final diagnosisOrgan = diagResultsForEachOrgan.organ;
|
|
|
- if ((playerController as VidPlayerController).status ==
|
|
|
- VidPlayStatus.pause) {
|
|
|
- if (detectedObjects!.isNotEmpty) {
|
|
|
- onSingleFrameImage(
|
|
|
- detectedObjects,
|
|
|
- diagnosisOrgan,
|
|
|
- widthScale,
|
|
|
- );
|
|
|
- }
|
|
|
- } else if (isPlay) {
|
|
|
- for (int m = 0; m < detectedObjects!.length; m++) {
|
|
|
- final organBoundBox = detectedObjects[m].boundingBox;
|
|
|
-
|
|
|
- left = organBoundBox!.left * widthScale;
|
|
|
- top = organBoundBox.top * widthScale;
|
|
|
- width = organBoundBox.width * widthScale;
|
|
|
- height = organBoundBox.height * widthScale;
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @override
|
|
|
- void initState() {
|
|
|
- _addListenrs();
|
|
|
- //监听Widget是否绘制完毕
|
|
|
- super.initState();
|
|
|
- widget.controller.eventHandler.addListener(onControllerEvent);
|
|
|
- }
|
|
|
-
|
|
|
- @override
|
|
|
- void dispose() {
|
|
|
- super.dispose();
|
|
|
- widget.controller.eventHandler.removeListener(onControllerEvent);
|
|
|
- _removeListenrs();
|
|
|
- }
|
|
|
-
|
|
|
@override
|
|
|
void didUpdateWidget(covariant AIPaintInfo oldWidget) {
|
|
|
if (oldWidget.controller != widget.controller) {
|
|
@@ -260,50 +101,48 @@ class _AIPaintInfoState extends State<AIPaintInfo> {
|
|
|
case VidPlayStatus.pause:
|
|
|
child = LayoutBuilder(builder: (context, constraints) {
|
|
|
final canvasWidth = constraints.maxWidth;
|
|
|
- late final frameDataWidth = application.frameData?.width;
|
|
|
+ late final frameDataWidth =
|
|
|
+ aiPatintController.application.frameData?.width;
|
|
|
late final widthScale = (canvasWidth / frameDataWidth!);
|
|
|
- if (!onGetAIResultsInfo(widthScale)) {
|
|
|
+ if (!aiPatintController.onGetAIResultsInfo(widthScale)) {
|
|
|
return const SizedBox();
|
|
|
} else {
|
|
|
return CustomMultiChildLayout(
|
|
|
delegate: _LayerLayoutDelegate(),
|
|
|
children: [
|
|
|
- if (aiDetectedObject.isNotEmpty) ...[
|
|
|
- LayoutId(
|
|
|
- id: _LayerLayoutIds.dots,
|
|
|
- child: CustomPaint(
|
|
|
- painter: PaintAIDots(aiResultsList),
|
|
|
- ),
|
|
|
- ),
|
|
|
- if (!isPlay) ...[
|
|
|
+ if (aiPatintController.aiDetectedObject.isNotEmpty) ...[
|
|
|
+ if (!aiPatintController.isPlay) ...[
|
|
|
LayoutId(
|
|
|
- id: _LayerLayoutIds.dashLine,
|
|
|
+ id: _LayerLayoutIds.dots,
|
|
|
child: CustomPaint(
|
|
|
- painter: PaintAIDashLine(p1, p2, p3, p4),
|
|
|
+ painter: PaintAIDots(aiPatintController.aiResultsList),
|
|
|
),
|
|
|
),
|
|
|
LayoutId(
|
|
|
- id: _LayerLayoutIds.aiResult,
|
|
|
- child: AIResultPanel(
|
|
|
- aiDetectedObject,
|
|
|
- diagnosisOrgan,
|
|
|
- aiResultIndex,
|
|
|
+ id: _LayerLayoutIds.dashLine,
|
|
|
+ child: CustomPaint(
|
|
|
+ painter: PaintAIDashLine(
|
|
|
+ aiPatintController.p1,
|
|
|
+ aiPatintController.p2,
|
|
|
+ aiPatintController.p3,
|
|
|
+ aiPatintController.p4,
|
|
|
+ ),
|
|
|
),
|
|
|
),
|
|
|
],
|
|
|
- if (isPlay)
|
|
|
- LayoutId(
|
|
|
- id: _LayerLayoutIds.rectangle,
|
|
|
- child: CustomPaint(
|
|
|
- painter: PaintAIRectangle(
|
|
|
- left,
|
|
|
- top,
|
|
|
- width,
|
|
|
- height,
|
|
|
- ),
|
|
|
+ ],
|
|
|
+ if (aiPatintController.isPlay)
|
|
|
+ LayoutId(
|
|
|
+ id: _LayerLayoutIds.rectangle,
|
|
|
+ child: CustomPaint(
|
|
|
+ painter: PaintAIRectangle(
|
|
|
+ aiPatintController.left,
|
|
|
+ aiPatintController.top,
|
|
|
+ aiPatintController.width,
|
|
|
+ aiPatintController.height,
|
|
|
),
|
|
|
),
|
|
|
- ]
|
|
|
+ ),
|
|
|
],
|
|
|
);
|
|
|
}
|
|
@@ -323,68 +162,6 @@ class _AIPaintInfoState extends State<AIPaintInfo> {
|
|
|
child: child,
|
|
|
);
|
|
|
}
|
|
|
-
|
|
|
- void _updateFeatures() {
|
|
|
- aiResultsList = [];
|
|
|
- left = 0;
|
|
|
- top = 0;
|
|
|
- width = 0;
|
|
|
- height = 0;
|
|
|
- p1 = Offset.zero;
|
|
|
- p2 = Offset.zero;
|
|
|
- p3 = Offset.zero;
|
|
|
- p4 = Offset.zero;
|
|
|
- }
|
|
|
-
|
|
|
- void _onMeasureRerenderReady(Object sender, void e) async {
|
|
|
- // if ((playerController as VidPlayerController).status ==
|
|
|
- // VidPlayStatus.play) {
|
|
|
- // // aiResults = measureData.aiResults;
|
|
|
- // if (mounted) {
|
|
|
- // // aiResults = measureData.aiResults;
|
|
|
- // setState(() {
|
|
|
- // _setAIResult();
|
|
|
- // });
|
|
|
- // }
|
|
|
- // } else {
|
|
|
- // if (mounted && aiResults == '') {
|
|
|
- // setState(() {
|
|
|
- // _setAIResult();
|
|
|
- // _updateFeatures();
|
|
|
- // });
|
|
|
- // }
|
|
|
- // }
|
|
|
- }
|
|
|
-
|
|
|
- void _setAIResult() {
|
|
|
- if (aiResults != null && aiResults!.isNotEmpty) {
|
|
|
- final measureDataAIResults = jsonDecode(
|
|
|
- aiResults!,
|
|
|
- );
|
|
|
- for (int i = 0; i < (measureDataAIResults as List).length; i++) {
|
|
|
- aiResult.add(
|
|
|
- AIDiagnosisPerImageDTO.fromJson(
|
|
|
- measureDataAIResults[i],
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void _addListenrs() async {
|
|
|
- application.updateRenderReady.addListener(_onMeasureRerenderReady);
|
|
|
- measureData.aiResultsInfoChanged
|
|
|
- .addListener(onMeasuredAIResultsInfoChanged);
|
|
|
- if (measureData.aiResults.isNotEmpty) {
|
|
|
- onMeasuredAIResultsInfoChanged(this, measureData.aiResults);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void _removeListenrs() {
|
|
|
- application.updateRenderReady.removeListener(_onMeasureRerenderReady);
|
|
|
- measureData.aiResultsInfoChanged
|
|
|
- .removeListener(onMeasuredAIResultsInfoChanged);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
class _LayerLayoutDelegate extends MultiChildLayoutDelegate {
|
|
@@ -407,8 +184,6 @@ class _LayerLayoutDelegate extends MultiChildLayoutDelegate {
|
|
|
/// 同步图像显示尺寸
|
|
|
application.displaySize = renderSize;
|
|
|
|
|
|
- // layoutLayer(_LayerLayoutIds.player, offset, renderSize);
|
|
|
-
|
|
|
/// 其他层按播放器尺寸位置层叠布局
|
|
|
layoutLayer(_LayerLayoutIds.dots, offset, renderSize);
|
|
|
layoutLayer(_LayerLayoutIds.dashLine, offset, renderSize);
|