Quellcode durchsuchen

1、update ai result

bakamaka.guan vor 2 Jahren
Ursprung
Commit
ae7f343594

+ 6 - 0
.vscode/settings.json

@@ -0,0 +1,6 @@
+{
+    "editor.detectIndentation": false,
+    "editor.tabSize": 4,
+    "editor.formatOnPaste": true,
+    "editor.formatOnSave": true
+}

+ 57 - 38
lib/view/main/desktop.dart

@@ -7,7 +7,9 @@ import 'package:fis_measure/utils/canvas.dart';
 import 'package:fis_measure/values/colors.dart';
 import 'package:fis_measure/view/gesture/annotation/annotation_gesture.dart';
 import 'package:fis_measure/view/paint/ai_patint.dart';
+import 'package:fis_measure/view/paint/ai_patint_result.dart';
 import 'package:fis_measure/view/pause/pause_panel.dart';
+import 'package:fis_measure/view/result/results_panel.dart';
 import 'package:fis_ui/define.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
@@ -20,7 +22,6 @@ import '../pause/pause_panel.dart';
 import '../player/control_board/control_board.dart';
 import '../player/controller.dart';
 import '../player/player.dart';
-import '../result/results_panel.dart';
 
 class MeasureMainView extends StatefulWidget implements FWidget {
   const MeasureMainView({Key? key}) : super(key: key);
@@ -97,47 +98,65 @@ class _MeasureMainViewState extends State<MeasureMainView> {
         child: Column(
           children: [
             Expanded(
-              child: CustomMultiChildLayout(
-                delegate: _LayerLayoutDelegate(),
+              child: Row(
+                crossAxisAlignment: CrossAxisAlignment.start,
                 children: [
-                  LayoutId(
-                    id: _LayerLayoutIds.player,
-                    child: Container(
-                      child: VidPlayer(playerController as VidPlayerController),
-                    ),
+                  const SizedBox(
+                    width: 200,
+                    child: MeasureResultPanel(),
                   ),
-                  if (canMeasure) ...[
-                    LayoutId(
-                      id: _LayerLayoutIds.recordsCanvas,
-                      child: const MeasureRecordsCanvasPanel(),
-                    ),
-                    LayoutId(
-                      id: _LayerLayoutIds.activeMeasure,
-                      child: const MeasureActiveCanvasPanel(),
-                    ),
-                    LayoutId(
-                      id: _LayerLayoutIds.activeAnnotation,
-                      child: const AnnotationCanvas(),
+                  Expanded(
+                    child: CustomMultiChildLayout(
+                      delegate: _LayerLayoutDelegate(),
+                      children: [
+                        LayoutId(
+                          id: _LayerLayoutIds.player,
+                          child: Container(
+                            child: VidPlayer(
+                                playerController as VidPlayerController),
+                          ),
+                        ),
+                        if (canMeasure) ...[
+                          LayoutId(
+                            id: _LayerLayoutIds.recordsCanvas,
+                            child: const MeasureRecordsCanvasPanel(),
+                          ),
+                          LayoutId(
+                            id: _LayerLayoutIds.activeMeasure,
+                            child: const MeasureActiveCanvasPanel(),
+                          ),
+                          LayoutId(
+                            id: _LayerLayoutIds.activeAnnotation,
+                            child: const AnnotationCanvas(),
+                          ),
+                          LayoutId(
+                            id: _LayerLayoutIds.gesture,
+                            child: inAnnotation
+                                ? const AnnotationGestureLayer()
+                                : const MeasureMouseGesturePanel(),
+                          ),
+                          // LayoutId(
+                          //   id: _LayerLayoutIds.result,
+                          //   child: const MeasureResultPanel(),
+                          // ),
+                        ],
+                        if (measureData.aiResults.isNotEmpty) ...[
+                          LayoutId(
+                            id: _LayerLayoutIds.paintAI,
+                            child: AIPaintInfo(
+                              playerController as VidPlayerController,
+                            ),
+                          )
+                        ],
+                      ],
                     ),
-                    LayoutId(
-                      id: _LayerLayoutIds.gesture,
-                      child: inAnnotation
-                          ? const AnnotationGestureLayer()
-                          : const MeasureMouseGesturePanel(),
-                    ),
-                    LayoutId(
-                      id: _LayerLayoutIds.result,
-                      child: const MeasureResultPanel(),
+                  ),
+                  SizedBox(
+                    width: 200,
+                    child: AIPaintInfoReslut(
+                      playerController as VidPlayerController,
                     ),
-                  ],
-                  if (measureData.aiResults.isNotEmpty) ...[
-                    LayoutId(
-                      id: _LayerLayoutIds.paintAI,
-                      child: AIPaintInfo(
-                        playerController as VidPlayerController,
-                      ),
-                    )
-                  ],
+                  ),
                 ],
               ),
             ),

+ 0 - 2
lib/view/measure/measure_images_bar.dart

@@ -236,8 +236,6 @@ class _LeftSiderImageListState extends State<LeftSiderImageList> {
             terminalImage: TerminalImage(
               previewUrl: remedicalItemList[index].terminalImages!.previewUrl,
             ),
-            diagnosisConclusion: remedicalItemList[index].diagnosisConclusion,
-            diagnosisOrgans: remedicalItemList[index].diagnosisOrgans,
             isMeasure: true,
             onChangeImage: () => onChangeImage(
               remedicalItemList[index].terminalImages!.imageUrl!,

+ 4 - 4
lib/view/measure/measure_view.dart

@@ -106,10 +106,10 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
     }
   }
 
-  @override
-  void dispose() {
-    super.dispose();
-  }
+  // @override
+  // void dispose() {
+  //   super.dispose();
+  // }
 
   @override
   FWidget build(BuildContext context) {

+ 1 - 0
lib/view/measure/tool_chest_title.dart

@@ -130,6 +130,7 @@ class _LeftSiderTabBarState extends State<_LeftSiderTabBar> {
         ),
       ),
       onPressed: () {
+        print(tag);
         measureHandler.changedTab = tag;
         setState(() {});
       },

+ 44 - 269
lib/view/paint/ai_patint.dart

@@ -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);

+ 212 - 0
lib/view/paint/ai_patint_controller.dart

@@ -0,0 +1,212 @@
+import 'dart:convert';
+
+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/ai_patint_state.dart';
+import 'package:fis_measure/view/paint/date_structure.dart';
+import 'package:fis_measure/view/player/controller.dart';
+import 'package:fis_measure/view/player/enums.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+
+class AiPatintController extends GetxController {
+  static const _HAS_VIEW_STATUS_ARR = [VidPlayStatus.play, VidPlayStatus.pause];
+
+  /// 播放器控制器
+  final VidPlayerController controller;
+  final state = AiPatintState();
+
+  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;
+
+  /// 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;
+
+  AiPatintController(this.controller);
+
+  @override
+  void onInit() {
+    _addListenrs();
+
+    super.onInit();
+  }
+
+  void onMeasuredAIResultsInfoChanged(Object sender, String e) {
+    if (e.isNotEmpty && e != "[]") {
+      aiResults = e;
+      final measureDataAIResults = jsonDecode(
+        aiResults ?? '',
+      );
+      state.aiResult.clear();
+      for (int i = 0; i < (measureDataAIResults as List).length; i++) {
+        state.aiResult.add(
+          AIDiagnosisPerImageDTO.fromJson(
+            measureDataAIResults[i],
+          ),
+        );
+      }
+    } else {
+      aiResults = '';
+      state.aiResult.clear();
+    }
+  }
+
+  /// 单帧图处理
+  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 (state.aiResult.isEmpty) {
+      return false;
+    } else if (state.aiResult.length == 1) {
+      final diagResultsForEachOrgan =
+          state.aiResult[0].diagResultsForEachOrgan?[state.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 = state.aiResult[state.frameIndex!]
+          .diagResultsForEachOrgan![state.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;
+    }
+  }
+
+  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 {
+    update();
+  }
+
+  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);
+  }
+}

+ 118 - 0
lib/view/paint/ai_patint_result.dart

@@ -0,0 +1,118 @@
+import 'package:fis_measure/view/paint/ai_patint_controller.dart';
+import 'package:fis_measure/view/paint/parts/ai_result.dart';
+import 'package:fis_measure/view/player/controller.dart';
+import 'package:fis_measure/view/player/enums.dart';
+import 'package:fis_measure/view/player/events.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+
+class AIPaintInfoReslut extends StatefulWidget {
+  /// 播放器控制器
+  final VidPlayerController controller;
+  final double? width;
+  final double? height;
+
+  const AIPaintInfoReslut(
+    this.controller, {
+    Key? key,
+    this.width,
+    this.height,
+  }) : super(key: key);
+
+  @override
+  State<AIPaintInfoReslut> createState() => _AIPaintInfoState();
+}
+
+class _AIPaintInfoState extends State<AIPaintInfoReslut> {
+  late final aiPatintController = Get.put(
+    AiPatintController(
+      widget.controller,
+    ),
+  );
+
+  void onControllerEvent(Object sender, VidPlayerEvent e) {
+    if (e is VidPlayerStatusChangeEvent) {
+      if (!widget.controller.hasView) {
+        setState(() {});
+      }
+    }
+    if (e is VidPlayerFrameIndexChangeEvent) {
+      onFrameChanged(e);
+    }
+    if (e is VidPlayerBrightnessChangeEvent) {
+      updateFrame();
+    }
+    if (e is VidPlayerContrastChangeEvent) {
+      updateFrame();
+    }
+  }
+
+  void onFrameChanged(VidPlayerFrameIndexChangeEvent e) {
+    setState(() {
+      aiPatintController.state.frameIndex = e.index;
+    });
+  }
+
+  void updateFrame() {
+    setState(() {});
+  }
+
+  @override
+  void initState() {
+    //监听Widget是否绘制完毕
+    super.initState();
+    widget.controller.eventHandler.addListener(onControllerEvent);
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  void didUpdateWidget(covariant AIPaintInfoReslut oldWidget) {
+    if (oldWidget.controller != widget.controller) {
+      throw UnsupportedError("[VidTestPlayer] unsupport replace controller.");
+    }
+    super.didUpdateWidget(oldWidget);
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    Widget? child;
+
+    if (widget.controller.status == VidPlayStatus.pause) {
+      child = LayoutBuilder(builder: (context, constraints) {
+        final canvasWidth = constraints.maxWidth;
+        late final frameDataWidth =
+            aiPatintController.application.frameData?.width;
+        late final widthScale = (canvasWidth / frameDataWidth!);
+        if (!aiPatintController.onGetAIResultsInfo(widthScale)) {
+          return const SizedBox();
+        } else {
+          if (aiPatintController.aiDetectedObject.isNotEmpty) {
+            return Obx(() {
+              return AIResultPanel(
+                aiPatintController.aiDetectedObject,
+                aiPatintController.diagnosisOrgan,
+                aiPatintController.state.aiResultIndex,
+              );
+            });
+          } else {
+            return Container();
+          }
+        }
+      });
+    } else {
+      child = Container();
+    }
+
+    return buildBox(context, child);
+  }
+
+  Widget buildBox(BuildContext context, Widget child) {
+    return Container(
+      child: child,
+    );
+  }
+}

+ 22 - 0
lib/view/paint/ai_patint_state.dart

@@ -0,0 +1,22 @@
+import 'package:fis_measure/view/paint/date_structure.dart';
+import 'package:get/get.dart';
+
+class AiPatintState {
+  final Rx<int> _frameIndex = Rx(0);
+  final Rx<int> _aiResultIndex = Rx(0);
+
+  final Rx<List<AIDiagnosisPerImageDTO>> _aiResult =
+      Rx(<AIDiagnosisPerImageDTO>[]);
+
+  /// 当前帧数
+  set frameIndex(value) => _frameIndex.value = value;
+  get frameIndex => _frameIndex.value;
+
+  /// 当前ai帧数
+  set aiResultIndex(value) => _aiResultIndex.value = value;
+  get aiResultIndex => _aiResultIndex.value;
+
+  /// ai结果集合
+  set aiResult(List<AIDiagnosisPerImageDTO> value) => _aiResult(value);
+  List<AIDiagnosisPerImageDTO> get aiResult => _aiResult.value;
+}

+ 0 - 21
lib/view/paint/parts/ai_resul_info.dart

@@ -200,27 +200,6 @@ class ResultInfo extends StatelessWidget {
     }
   }
 
-  // String _buildAIText(DiagnosisOrganEnum diagnosisConclusion) {
-  //   switch (diagnosisConclusion) {
-  //     case DiagnosisOrganEnum.NotRequired:
-  //       return i18nBook.remedical.noNeedAIYet.t;
-  //     case DiagnosisOrganEnum.InProcess:
-  //       return i18nBook.remedical.didNotHandle.t;
-  //     case DiagnosisOrganEnum.Unrecognized:
-  //       return i18nBook.remedical.didNotIdentify.t;
-  //     case DiagnosisOrganEnum.NoObviousLesion:
-  //       return i18nBook.remedical.noAbnormal.t;
-  //     case DiagnosisOrganEnum.Benign:
-  //       return i18nBook.remedical.benign.t;
-  //     case DiagnosisOrganEnum.Malignant:
-  //       return i18nBook.remedical.malignant.t;
-  //     case DiagnosisOrganEnum.BenignAndMalignant:
-  //       return i18nBook.remedical.benignWithMalignant.t;
-  //     default:
-  //       return i18nBook.remedical.didNotIdentify.t;
-  //   }
-  // }
-
   Color _buildAITextColor(int label) {
     switch (label) {
       case 0:

+ 1 - 1
pubspec.yaml

@@ -93,7 +93,7 @@ dependency_overrides:
   fis_lib_business_components:
     git:
       url: http://git.ius.plus/bakamaka.guan/fis_lib_business_components.git
-      ref: 15bc6b7    
+      ref: 07cf619    
 dev_dependencies:
   flutter_test:
     sdk: flutter