Skip to content

Commit 5ab0142

Browse files
Updated the model inference to output relative bounding boxes.
Updated the model inference to output relative bounding boxes, i.e. as a fraction of the image dimensions. This is so that different size/resolution images can still be used with each other.
1 parent bfd1f74 commit 5ab0142

21 files changed

+358
-239
lines changed

lib/src/data/image_data.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ sealed class ImageData with _$ImageData {
1515
required int imageHeight,
1616
@Default([]) List<YoloEntityOutput> components,
1717
// @Default(0.3) double componentDetectionThreshold,
18-
@Default(0.4) double benchmarkOverlapThreshold,
18+
@Default(0.1) double benchmarkOverlapThreshold,
1919
@Default([]) List<YoloEntityOutput> trackDefects,
2020
@Default(0.25) double trackDefectDetectionThreshold,
2121
@Default(false) bool tracksOnly,

lib/src/data/image_data.freezed.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ as bool,
8383
@JsonSerializable()
8484

8585
class _ImageData extends ImageData {
86-
_ImageData({required this.imageWidth, required this.imageHeight, final List<YoloEntityOutput> components = const [], this.benchmarkOverlapThreshold = 0.4, final List<YoloEntityOutput> trackDefects = const [], this.trackDefectDetectionThreshold = 0.25, this.tracksOnly = false}): _components = components,_trackDefects = trackDefects,super._();
86+
_ImageData({required this.imageWidth, required this.imageHeight, final List<YoloEntityOutput> components = const [], this.benchmarkOverlapThreshold = 0.1, final List<YoloEntityOutput> trackDefects = const [], this.trackDefectDetectionThreshold = 0.25, this.tracksOnly = false}): _components = components,_trackDefects = trackDefects,super._();
8787
factory _ImageData.fromJson(Map<String, dynamic> json) => _$ImageDataFromJson(json);
8888

8989
@override final int imageWidth;

lib/src/data/image_data.g.dart

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/data/image_status_tile_data.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ enum ImageStatus {
1313
late Color tileColor;
1414
switch (this) {
1515
case ImageStatus.Unchecked:
16-
trailingIcon = Icons.warning_amber;
17-
tileColor = Colors.amberAccent[100]!;
16+
trailingIcon = Icons.question_mark;
17+
tileColor = Colors.blueGrey[100]!;
1818
case ImageStatus.Faulty:
19-
trailingIcon = Icons.error;
20-
tileColor = Colors.redAccent[100]!;
19+
trailingIcon = Icons.warning;
20+
tileColor = Colors.amberAccent[100]!;
2121
case ImageStatus.Ok:
2222
trailingIcon = Icons.check;
2323
tileColor = Colors.greenAccent[100]!;

lib/src/models/auto_slicing.dart

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,26 +71,47 @@ sealed class ModelInferenceParameters with _$ModelInferenceParameters {
7171
],
7272
);
7373
case Resolution.high:
74-
int sliceSize1 = sampleLength ~/ 3.5;
74+
int sliceSize1 = minLength ~/ 2.5;
75+
int sliceSize2 = sampleLength ~/ 1.5;
7576
return ModelInferenceParameters(
7677
keepOriginal: true,
7778
sliceOptions: [
7879
SliceInputParams(
7980
sliceWidth: sliceSize1,
8081
sliceHeight: sliceSize1,
81-
overlapWidthRatio: 0.175,
82-
overlapHeightRatio: 0.175,
82+
overlapWidthRatio: 0.2,
83+
overlapHeightRatio: 0.2,
84+
),
85+
SliceInputParams(
86+
sliceWidth: sliceSize2,
87+
sliceHeight: sliceSize2,
88+
overlapWidthRatio: 0.15,
89+
overlapHeightRatio: 0.15,
8390
),
8491
],
8592
);
8693
case Resolution.ultraHigh:
87-
int sliceSize1 = sampleLength ~/ 4;
94+
int sliceSize1 = minLength ~/ 2.5;
95+
int sliceSize2 = sampleLength ~/ 1.5;
96+
int sliceSize0 = sampleLength ~/ 3;
8897
return ModelInferenceParameters(
89-
keepOriginal: false,
98+
keepOriginal: true,
9099
sliceOptions: [
100+
SliceInputParams(
101+
sliceWidth: sliceSize0,
102+
sliceHeight: sliceSize0,
103+
overlapWidthRatio: 0.125,
104+
overlapHeightRatio: 0.125,
105+
),
91106
SliceInputParams(
92107
sliceWidth: sliceSize1,
93108
sliceHeight: sliceSize1,
109+
overlapWidthRatio: 0.2,
110+
overlapHeightRatio: 0.2,
111+
),
112+
SliceInputParams(
113+
sliceWidth: sliceSize2,
114+
sliceHeight: sliceSize2,
94115
overlapWidthRatio: 0.15,
95116
overlapHeightRatio: 0.15,
96117
),

lib/src/rust/api/utils.dart

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,24 @@ import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
99
part 'utils.freezed.dart';
1010
part 'utils.g.dart';
1111

12-
// These functions are ignored because they are not marked as `pub`: `new_with_log`, `new`, `non_maximum_suppression_with_sorted_boxes`, `non_maximum_suppression`, `sort_predictions`
13-
// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DropTimer`
14-
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `clone`, `drop`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`
12+
// These functions are ignored because they are not marked as `pub`: `height`, `new_with_log`, `new`, `new`, `non_maximum_suppression_with_sorted_boxes`, `non_maximum_suppression`, `sort_predictions`, `width`
13+
// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `DropTimer`, `SliceBoundingBox`
14+
// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `drop`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`
1515
// These functions are ignored (category: IgnoreBecauseExplicitAttribute): `non_maximum_suppression_collect`, `non_maximum_suppression_collect`
1616

1717
@freezed
1818
sealed class BoundingBox with _$BoundingBox {
1919
const BoundingBox._();
2020
const factory BoundingBox.raw({
21-
required int x1,
22-
required int y1,
23-
required int x2,
24-
required int y2,
21+
required double x1,
22+
required double y1,
23+
required double x2,
24+
required double y2,
2525
}) = _BoundingBox;
2626
double area() =>
2727
RustLib.instance.api.crateApiUtilsBoundingBoxArea(that: this);
2828

29-
int height() =>
29+
double height() =>
3030
RustLib.instance.api.crateApiUtilsBoundingBoxHeight(that: this);
3131

3232
double intersection({required BoundingBox box2}) => RustLib.instance.api
@@ -49,10 +49,10 @@ sealed class BoundingBox with _$BoundingBox {
4949
);
5050

5151
factory BoundingBox({
52-
required int x1,
53-
required int y1,
54-
required int x2,
55-
required int y2,
52+
required double x1,
53+
required double y1,
54+
required double x2,
55+
required double y2,
5656
}) => RustLib.instance.api.crateApiUtilsBoundingBoxNew(
5757
x1: x1,
5858
y1: y1,
@@ -63,7 +63,8 @@ sealed class BoundingBox with _$BoundingBox {
6363
double union({required BoundingBox box2}) => RustLib.instance.api
6464
.crateApiUtilsBoundingBoxUnion(that: this, box2: box2);
6565

66-
int width() => RustLib.instance.api.crateApiUtilsBoundingBoxWidth(that: this);
66+
double width() =>
67+
RustLib.instance.api.crateApiUtilsBoundingBoxWidth(that: this);
6768

6869
factory BoundingBox.fromJson(Map<String, dynamic> json) =>
6970
_$BoundingBoxFromJson(json);

lib/src/rust/api/utils.freezed.dart

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
1616
/// @nodoc
1717
mixin _$BoundingBox {
1818

19-
int get x1; int get y1; int get x2; int get y2;
19+
double get x1; double get y1; double get x2; double get y2;
2020
/// Create a copy of BoundingBox
2121
/// with the given fields replaced by the non-null parameter values.
2222
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -49,7 +49,7 @@ abstract mixin class $BoundingBoxCopyWith<$Res> {
4949
factory $BoundingBoxCopyWith(BoundingBox value, $Res Function(BoundingBox) _then) = _$BoundingBoxCopyWithImpl;
5050
@useResult
5151
$Res call({
52-
int x1, int y1, int x2, int y2
52+
double x1, double y1, double x2, double y2
5353
});
5454

5555

@@ -69,10 +69,10 @@ class _$BoundingBoxCopyWithImpl<$Res>
6969
@pragma('vm:prefer-inline') @override $Res call({Object? x1 = null,Object? y1 = null,Object? x2 = null,Object? y2 = null,}) {
7070
return _then(_self.copyWith(
7171
x1: null == x1 ? _self.x1 : x1 // ignore: cast_nullable_to_non_nullable
72-
as int,y1: null == y1 ? _self.y1 : y1 // ignore: cast_nullable_to_non_nullable
73-
as int,x2: null == x2 ? _self.x2 : x2 // ignore: cast_nullable_to_non_nullable
74-
as int,y2: null == y2 ? _self.y2 : y2 // ignore: cast_nullable_to_non_nullable
75-
as int,
72+
as double,y1: null == y1 ? _self.y1 : y1 // ignore: cast_nullable_to_non_nullable
73+
as double,x2: null == x2 ? _self.x2 : x2 // ignore: cast_nullable_to_non_nullable
74+
as double,y2: null == y2 ? _self.y2 : y2 // ignore: cast_nullable_to_non_nullable
75+
as double,
7676
));
7777
}
7878

@@ -86,10 +86,10 @@ class _BoundingBox extends BoundingBox {
8686
const _BoundingBox({required this.x1, required this.y1, required this.x2, required this.y2}): super._();
8787
factory _BoundingBox.fromJson(Map<String, dynamic> json) => _$BoundingBoxFromJson(json);
8888

89-
@override final int x1;
90-
@override final int y1;
91-
@override final int x2;
92-
@override final int y2;
89+
@override final double x1;
90+
@override final double y1;
91+
@override final double x2;
92+
@override final double y2;
9393

9494
/// Create a copy of BoundingBox
9595
/// with the given fields replaced by the non-null parameter values.
@@ -124,7 +124,7 @@ abstract mixin class _$BoundingBoxCopyWith<$Res> implements $BoundingBoxCopyWith
124124
factory _$BoundingBoxCopyWith(_BoundingBox value, $Res Function(_BoundingBox) _then) = __$BoundingBoxCopyWithImpl;
125125
@override @useResult
126126
$Res call({
127-
int x1, int y1, int x2, int y2
127+
double x1, double y1, double x2, double y2
128128
});
129129

130130

@@ -144,10 +144,10 @@ class __$BoundingBoxCopyWithImpl<$Res>
144144
@override @pragma('vm:prefer-inline') $Res call({Object? x1 = null,Object? y1 = null,Object? x2 = null,Object? y2 = null,}) {
145145
return _then(_BoundingBox(
146146
x1: null == x1 ? _self.x1 : x1 // ignore: cast_nullable_to_non_nullable
147-
as int,y1: null == y1 ? _self.y1 : y1 // ignore: cast_nullable_to_non_nullable
148-
as int,x2: null == x2 ? _self.x2 : x2 // ignore: cast_nullable_to_non_nullable
149-
as int,y2: null == y2 ? _self.y2 : y2 // ignore: cast_nullable_to_non_nullable
150-
as int,
147+
as double,y1: null == y1 ? _self.y1 : y1 // ignore: cast_nullable_to_non_nullable
148+
as double,x2: null == x2 ? _self.x2 : x2 // ignore: cast_nullable_to_non_nullable
149+
as double,y2: null == y2 ? _self.y2 : y2 // ignore: cast_nullable_to_non_nullable
150+
as double,
151151
));
152152
}
153153

lib/src/rust/api/utils.g.dart

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/src/rust/frb_generated.dart

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ abstract class RustLibApi extends BaseApi {
135135

136136
double crateApiUtilsBoundingBoxArea({required BoundingBox that});
137137

138-
int crateApiUtilsBoundingBoxHeight({required BoundingBox that});
138+
double crateApiUtilsBoundingBoxHeight({required BoundingBox that});
139139

140140
double crateApiUtilsBoundingBoxIntersection({
141141
required BoundingBox that,
@@ -161,18 +161,18 @@ abstract class RustLibApi extends BaseApi {
161161
});
162162

163163
BoundingBox crateApiUtilsBoundingBoxNew({
164-
required int x1,
165-
required int y1,
166-
required int x2,
167-
required int y2,
164+
required double x1,
165+
required double y1,
166+
required double x2,
167+
required double y2,
168168
});
169169

170170
double crateApiUtilsBoundingBoxUnion({
171171
required BoundingBox that,
172172
required BoundingBox box2,
173173
});
174174

175-
int crateApiUtilsBoundingBoxWidth({required BoundingBox that});
175+
double crateApiUtilsBoundingBoxWidth({required BoundingBox that});
176176

177177
Future<void> crateApiMainInitApp();
178178

@@ -643,7 +643,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
643643
const TaskConstMeta(debugName: "bounding_box_area", argNames: ["that"]);
644644

645645
@override
646-
int crateApiUtilsBoundingBoxHeight({required BoundingBox that}) {
646+
double crateApiUtilsBoundingBoxHeight({required BoundingBox that}) {
647647
return handler.executeSync(
648648
SyncTask(
649649
callFfi: () {
@@ -652,7 +652,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
652652
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 13)!;
653653
},
654654
codec: SseCodec(
655-
decodeSuccessData: sse_decode_u_32,
655+
decodeSuccessData: sse_decode_f_32,
656656
decodeErrorData: null,
657657
),
658658
constMeta: kCrateApiUtilsBoundingBoxHeightConstMeta,
@@ -815,19 +815,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
815815

816816
@override
817817
BoundingBox crateApiUtilsBoundingBoxNew({
818-
required int x1,
819-
required int y1,
820-
required int x2,
821-
required int y2,
818+
required double x1,
819+
required double y1,
820+
required double x2,
821+
required double y2,
822822
}) {
823823
return handler.executeSync(
824824
SyncTask(
825825
callFfi: () {
826826
final serializer = SseSerializer(generalizedFrbRustBinding);
827-
sse_encode_u_32(x1, serializer);
828-
sse_encode_u_32(y1, serializer);
829-
sse_encode_u_32(x2, serializer);
830-
sse_encode_u_32(y2, serializer);
827+
sse_encode_f_32(x1, serializer);
828+
sse_encode_f_32(y1, serializer);
829+
sse_encode_f_32(x2, serializer);
830+
sse_encode_f_32(y2, serializer);
831831
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 19)!;
832832
},
833833
codec: SseCodec(
@@ -878,7 +878,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
878878
);
879879

880880
@override
881-
int crateApiUtilsBoundingBoxWidth({required BoundingBox that}) {
881+
double crateApiUtilsBoundingBoxWidth({required BoundingBox that}) {
882882
return handler.executeSync(
883883
SyncTask(
884884
callFfi: () {
@@ -887,7 +887,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
887887
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 21)!;
888888
},
889889
codec: SseCodec(
890-
decodeSuccessData: sse_decode_u_32,
890+
decodeSuccessData: sse_decode_f_32,
891891
decodeErrorData: null,
892892
),
893893
constMeta: kCrateApiUtilsBoundingBoxWidthConstMeta,
@@ -1025,10 +1025,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
10251025
if (arr.length != 4)
10261026
throw Exception('unexpected arr length: expect 4 but see ${arr.length}');
10271027
return BoundingBox.raw(
1028-
x1: dco_decode_u_32(arr[0]),
1029-
y1: dco_decode_u_32(arr[1]),
1030-
x2: dco_decode_u_32(arr[2]),
1031-
y2: dco_decode_u_32(arr[3]),
1028+
x1: dco_decode_f_32(arr[0]),
1029+
y1: dco_decode_f_32(arr[1]),
1030+
x2: dco_decode_f_32(arr[2]),
1031+
y2: dco_decode_f_32(arr[3]),
10321032
);
10331033
}
10341034

@@ -1240,10 +1240,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
12401240
@protected
12411241
BoundingBox sse_decode_bounding_box(SseDeserializer deserializer) {
12421242
// Codec=Sse (Serialization based), see doc to use other codecs
1243-
var var_x1 = sse_decode_u_32(deserializer);
1244-
var var_y1 = sse_decode_u_32(deserializer);
1245-
var var_x2 = sse_decode_u_32(deserializer);
1246-
var var_y2 = sse_decode_u_32(deserializer);
1243+
var var_x1 = sse_decode_f_32(deserializer);
1244+
var var_y1 = sse_decode_f_32(deserializer);
1245+
var var_x2 = sse_decode_f_32(deserializer);
1246+
var var_y2 = sse_decode_f_32(deserializer);
12471247
return BoundingBox.raw(x1: var_x1, y1: var_y1, x2: var_x2, y2: var_y2);
12481248
}
12491249

@@ -1481,10 +1481,10 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
14811481
@protected
14821482
void sse_encode_bounding_box(BoundingBox self, SseSerializer serializer) {
14831483
// Codec=Sse (Serialization based), see doc to use other codecs
1484-
sse_encode_u_32(self.x1, serializer);
1485-
sse_encode_u_32(self.y1, serializer);
1486-
sse_encode_u_32(self.x2, serializer);
1487-
sse_encode_u_32(self.y2, serializer);
1484+
sse_encode_f_32(self.x1, serializer);
1485+
sse_encode_f_32(self.y1, serializer);
1486+
sse_encode_f_32(self.x2, serializer);
1487+
sse_encode_f_32(self.y2, serializer);
14881488
}
14891489

14901490
@protected

lib/src/store/image_data.store.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ sealed class _ImageDataStore with Store {
155155
setComponents(components);
156156
}
157157

158+
@action
159+
void addComponent(YoloEntityOutput addVal) {
160+
var components = imageData.components;
161+
final idx = components.indexOf(addVal);
162+
if (idx != -1) return;
163+
components = List.of(components);
164+
components.add(addVal);
165+
setComponents(components);
166+
}
167+
158168
@action
159169
void deleteImage() {
160170
parent.removeImage(folderName);

0 commit comments

Comments
 (0)