123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- import 'dart:convert';
- import 'dart:math';
- import 'package:fis_common/logger/logger.dart';
- import 'package:fis_i18n/i18n.dart';
- import 'package:fis_measure/interfaces/process/standard_line/calibration.dart';
- import 'package:fis_measure/interfaces/process/workspace/application.dart';
- import 'package:fis_measure/process/visual/visual.dart';
- import 'package:fis_measure/process/workspace/third_part/application.dart';
- import 'package:fis_measure/process/workspace/third_part/calibration_controller.dart';
- import 'package:fis_measure/process/workspace/visual_loader.dart';
- import 'package:fis_measure/values/unit_desc.dart';
- import 'package:fis_measure/view/paint/ai_patint_controller.dart';
- import 'package:fis_measure/view/paint/date_structure.dart';
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'package:vid/us/vid_us_unit.dart';
- /// AI诊断结果
- class ResultInfo extends StatefulWidget {
- const ResultInfo(this.aiDetectedObject, {Key? key}) : super(key: key);
- final List<AIDetectedObject>? aiDetectedObject;
- @override
- State<ResultInfo> createState() => _ResultInfoState();
- }
- class _ResultInfoState extends State<ResultInfo> {
- late final aiPatintController = Get.find<AiPatintController>();
- IStandardLineCalibrationController? standardLineCalibrationController;
- late AIDetectedObject aiDetectedObjectItem;
- double _unitsPhysicalPixels = 0;
- late final application = Get.find<IApplication>();
- // 图像的物理单位
- String _xUnit = '';
- @override
- void initState() {
- _updateImagePhysicalSize();
- try {
- if (application.isThirdPart) {
- final standradLine = (application as ThirdPartApplication).standardLine;
- standardLineCalibrationController =
- StandardLineCalibrationController(application, standradLine);
- Get.put<IStandardLineCalibrationController>(
- standardLineCalibrationController!);
- if (standardLineCalibrationController != null) {
- standardLineCalibrationController!.editStateChanged
- .addListener(onStandardLineUpdated);
- }
- }
- } catch (e) {
- logger.e('standardLineCalibrationController cannot find ', e);
- }
- super.initState();
- }
- @override
- void didUpdateWidget(ResultInfo oldWidget) {
- _updateImagePhysicalSize();
- super.didUpdateWidget(oldWidget);
- }
- @override
- void dispose() {
- if (standardLineCalibrationController != null) {
- standardLineCalibrationController!.editStateChanged
- .removeListener(onStandardLineUpdated);
- }
- super.dispose();
- }
- void onStandardLineUpdated(_, e) {
- _updateImagePhysicalSize();
- }
- @override
- Widget build(BuildContext context) {
- if (_unitsPhysicalPixels <= 0) {
- _updateImagePhysicalSize();
- }
- final description = widget
- .aiDetectedObject?[aiPatintController.state.aiResultIndex].descriptions;
- var lesionSizeDescription = description?.firstWhereOrNull(
- (element) => element.type == DiagnosisDescriptionEnum.LesionSize);
- var lesionSize = lesionSizeDescription?.value ?? '';
- late final lesionSizeMap =
- (description?.length ?? 0) > 1 ? jsonDecode(lesionSize) : '';
- return Container(
- decoration: BoxDecoration(
- border: Border.all(
- color: Colors.grey,
- ),
- borderRadius: BorderRadius.circular(4),
- color: Colors.transparent,
- ),
- padding: const EdgeInsets.only(bottom: 10),
- child: Column(
- children: [
- Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Expanded(
- child: Container(
- decoration: const BoxDecoration(
- borderRadius: BorderRadius.only(
- topLeft: Radius.circular(4),
- topRight: Radius.circular(4),
- ),
- color: Color.fromRGBO(54, 169, 206, 1),
- ),
- padding: const EdgeInsets.only(
- top: 4,
- bottom: 10,
- left: 8,
- right: 8,
- ),
- child: Text(
- i18nBook.measure.aiDiagnosticResults.t,
- style: const TextStyle(
- color: Colors.white,
- ),
- ),
- ),
- )
- ],
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Expanded(
- child: Container(
- padding: const EdgeInsets.only(
- left: 10,
- ),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- _buildTitle(
- i18nBook.measure.diseaseLabels.t,
- _buildAITitle(),
- ),
- if (lesionSizeMap != '' && lesionSizeMap != null)
- _buildTitle(
- i18nBook.measure.isLesionSize.t,
- _buildLesionSize(
- lesionSizeMap?['HorizontalLengthInPixel'] ?? 0,
- lesionSizeMap?['VerticalLengthInPixel'] ?? 0,
- _unitsPhysicalPixels,
- ),
- )
- ],
- ),
- ),
- ),
- Container(
- margin: const EdgeInsets.symmetric(
- vertical: 5,
- ),
- padding: const EdgeInsets.only(right: 8),
- child: Column(
- children: [
- Text(
- i18nBook.measure.possibility.t,
- style: const TextStyle(
- color: Colors.grey,
- ),
- ),
- const SizedBox(
- height: 8,
- ),
- SizedBox(
- width: 70,
- height: 70,
- child: Stack(
- children: [
- SizedBox(
- width: 70,
- height: 70,
- child: Obx(() {
- final aiDetected = widget.aiDetectedObject?[
- aiPatintController.state.aiResultIndex];
- return CircularProgressIndicator(
- valueColor: AlwaysStoppedAnimation(
- _buildAITextColor(
- aiDetected?.label ?? 0,
- ),
- ),
- backgroundColor: Colors.grey,
- value: aiDetected?.confidence,
- );
- }),
- ),
- Center(
- child: SizedBox(
- width: 65,
- height: 45,
- child: Obx(
- () {
- final confidence = widget
- .aiDetectedObject?[aiPatintController
- .state.aiResultIndex]
- .confidence;
- return Center(
- child: Text(
- '${((confidence ?? 0) * 100).toStringAsFixed(1)}%',
- style: const TextStyle(
- color: Colors.white,
- fontSize: 18,
- fontWeight: FontWeight.bold,
- ),
- ),
- );
- },
- ),
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- ],
- ),
- );
- }
- Widget _buildLesionSize(
- int horizontalLengthInPixel,
- int verticalLengthInPixel,
- double unitsPhysicalPixels,
- ) {
- return Text(
- (horizontalLengthInPixel * unitsPhysicalPixels)
- .toStringAsFixed(2)
- .toString() +
- '$_xUnit x' +
- (verticalLengthInPixel * unitsPhysicalPixels)
- .toStringAsFixed(2)
- .toString() +
- _xUnit,
- style: const TextStyle(color: Colors.white),
- );
- }
- /// 更新图像物理尺度信息
- void _updateImagePhysicalSize() {
- if (application.visuals.isEmpty) {
- return;
- }
- if (application.visuals[0].visualAreas.isEmpty) {
- return;
- }
- _unitsPhysicalPixels =
- (application.visuals[0].visualAreas[0].viewport?.region.width)! /
- (application.frameData!.width).toDouble();
- VidUsUnit targetUnit =
- application.visuals[0].visualAreas[0].viewport?.xUnit ?? VidUsUnit.cm;
- _xUnit = UnitDescriptionMap.getDesc(targetUnit);
- }
- Widget _buildTitle(String label, Widget value) {
- return Column(
- mainAxisSize: MainAxisSize.max,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- label,
- style: const TextStyle(
- color: Color.fromRGBO(54, 169, 206, 1),
- ),
- ),
- value,
- const SizedBox(
- height: 5,
- ),
- ],
- );
- }
- Color _buildAITextColor(int label) {
- switch (aiPatintController.diagnosisOrgan) {
- /// 乳腺是0:未见异常; 1、2、3良性; 4、5、6、7恶性;
- case DiagnosisOrganEnum.Breast:
- switch (label) {
- case 0:
- return Colors.lightBlue;
- case 1:
- case 2:
- case 3:
- return Colors.greenAccent;
- case 4:
- case 5:
- case 6:
- case 7:
- return Colors.redAccent;
- default:
- return Colors.lightBlue;
- }
- /// 肝脏是0:未见异常; 1、2、3、4、5、6、7、8良性;
- case DiagnosisOrganEnum.Liver:
- switch (label) {
- case 0:
- return Colors.lightBlue;
- case 4:
- return Colors.redAccent;
- case 1:
- case 2:
- case 3:
- case 5:
- case 6:
- case 7:
- case 8:
- return Colors.greenAccent;
- default:
- return Colors.lightBlue;
- }
- /// 甲状腺是0:未见异常; 1、2、3、4、5、6、7、8良性;
- case DiagnosisOrganEnum.Thyroid:
- switch (label) {
- case 0:
- return Colors.lightBlue;
- case 1:
- case 2:
- case 7:
- return Colors.greenAccent;
- case 3:
- case 4:
- case 5:
- case 6:
- return Colors.redAccent;
- default:
- return Colors.lightBlue;
- }
- default:
- return Colors.lightBlue;
- }
- }
- Widget _buildAITitle() {
- switch (aiPatintController.diagnosisOrgan) {
- case DiagnosisOrganEnum.Breast:
- return Obx(() {
- aiDetectedObjectItem = widget
- .aiDetectedObject?[aiPatintController.state.aiResultIndex] ??
- AIDetectedObject();
- return _buildBreastDescription(aiDetectedObjectItem.label);
- });
- case DiagnosisOrganEnum.Liver:
- return Obx(() {
- aiDetectedObjectItem = widget
- .aiDetectedObject?[aiPatintController.state.aiResultIndex] ??
- AIDetectedObject();
- return _buildLiverDescription(aiDetectedObjectItem.label);
- });
- case DiagnosisOrganEnum.Thyroid:
- return Obx(() {
- aiDetectedObjectItem = widget
- .aiDetectedObject?[aiPatintController.state.aiResultIndex] ??
- AIDetectedObject();
- return _buildThyroidDescription(aiDetectedObjectItem.label);
- });
- case DiagnosisOrganEnum.CarotidArtery:
- return Obx(() {
- aiDetectedObjectItem = widget
- .aiDetectedObject?[aiPatintController.state.aiResultIndex] ??
- AIDetectedObject();
- return _buildCarotidArteryDescription(aiDetectedObjectItem.label);
- });
- default:
- return const SizedBox();
- }
- }
- Widget _buildBreastDescription(int label) {
- switch (label) {
- case 0:
- return _buildDescription(
- i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
- case 1:
- return _buildDescription(i18nBook.measure.lipoma.t);
- case 2:
- return _buildDescription('BI-RADS 2');
- case 3:
- return _buildDescription('BI-RADS 3');
- case 4:
- return _buildDescription('BI-RADS 4a');
- case 5:
- return _buildDescription('BI-RADS 4b');
- case 6:
- return _buildDescription('BI-RADS 4c');
- case 7:
- return _buildDescription('BI-RADS 5');
- case 8:
- return _buildDescription(
- i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
- default:
- return _buildDescription(null);
- }
- }
- Widget _buildLiverDescription(int label) {
- switch (label) {
- case 0:
- return _buildDescription(
- i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
- case 1:
- return _buildDescription(i18nBook.measure.intrahepaticStrongEchoFoci.t);
- case 2:
- return _buildDescription(i18nBook.measure.hepaticHemangioma.t);
- case 3:
- return _buildDescription(i18nBook.measure.liverCysts.t);
- case 4:
- return _buildDescription(i18nBook.measure.liverCancerMayOccur.t);
- case 5:
- return _buildDescription(i18nBook.measure.fattyLiver.t);
- case 6:
- return _buildDescription(
- i18nBook.measure.panisodicChangesLiverDiffuseLesions.t);
- case 7:
- return _buildDescription(i18nBook.measure.cirrhosis.t);
- case 8:
- return _buildDescription(i18nBook.measure.polycysticLiver.t);
- default:
- return _buildDescription(null);
- }
- }
- Widget _buildThyroidDescription(int label) {
- switch (label) {
- case 0:
- return _buildDescription(
- i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
- case 1:
- return _buildDescription('TIRADS2');
- case 2:
- return _buildDescription('TIRADS3');
- case 3:
- return _buildDescription('TIRADS4a');
- case 4:
- return _buildDescription('TIRADS4b');
- case 5:
- return _buildDescription('TIRADS4c');
- case 6:
- return _buildDescription('TIRADS5');
- case 7:
- return _buildDescription(i18nBook.measure.presenceDiffuseDisease.t);
- default:
- return _buildDescription(null);
- }
- }
- Widget _buildDescription(
- String? title,
- ) {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- if (title != null) ...[
- const SizedBox(
- height: 5,
- ),
- Text(
- title,
- style: const TextStyle(color: Colors.white),
- ),
- ],
- ],
- );
- }
- Widget _buildCarotidArteryDescription(int label) {
- switch (label) {
- case 0:
- return _buildDescription(
- i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
- case 1:
- return _buildDescription(i18nBook.measure.patch.t);
- default:
- return _buildDescription(null);
- }
- }
- }
|