Skip to content

Commit 3f04623

Browse files
authored
Merge pull request #158 from rainyl/fp16
support fp16
2 parents 6c1fcd6 + f39e838 commit 3f04623

File tree

11 files changed

+331
-9
lines changed

11 files changed

+331
-9
lines changed

lib/src/core/mat.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class Mat extends CvStruct<cvg.Mat> {
4444
MatType.CV_32S => VecI32.fromList(data.cast<int>()) as Vec,
4545
MatType.CV_32F => VecF32.fromList(data.cast<double>()) as Vec,
4646
MatType.CV_64F => VecF64.fromList(data.cast<double>()) as Vec,
47+
MatType.CV_16F => VecF16.fromList(data.cast<double>()) as Vec,
4748
_ => throw UnsupportedError("Mat.fromBytes for MatType $type unsupported"),
4849
};
4950
// copy
@@ -1221,6 +1222,7 @@ class Mat extends CvStruct<cvg.Mat> {
12211222
return dst;
12221223
}
12231224

1225+
@Deprecated("Use convertTo instead")
12241226
Mat convertToFp16() {
12251227
final p = calloc<cvg.Mat>();
12261228
cvRun(() => ccore.Mat_ConvertFp16(ref, p));

lib/src/core/mat_type.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ extension type const MatType(int value) {
1818
const MatType.CV_32SC(int channels) : this.makeType(CV_32S, channels);
1919
const MatType.CV_32FC(int channels) : this.makeType(CV_32F, channels);
2020
const MatType.CV_64FC(int channels) : this.makeType(CV_64F, channels);
21+
const MatType.CV_16FC(int channels) : this.makeType(CV_16F, channels);
2122

2223
int get depth => value & (CV_DEPTH_MAX - 1);
2324
bool get isInteger => depth < CV_32F;
@@ -38,7 +39,7 @@ extension type const MatType(int value) {
3839
static const int CV_32S = 4;
3940
static const int CV_32F = 5;
4041
static const int CV_64F = 6;
41-
static const int CV_USRTYPE1 = 7;
42+
static const int CV_16F = 7;
4243

4344
/// predefined type constants
4445
static const CV_8UC1 = MatType.CV_8UC(1); // 0
@@ -69,6 +70,10 @@ extension type const MatType(int value) {
6970
static const CV_64FC2 = MatType.CV_64FC(2); // 14
7071
static const CV_64FC3 = MatType.CV_64FC(3); // 22
7172
static const CV_64FC4 = MatType.CV_64FC(4); // 30
73+
static const CV_16FC1 = MatType.CV_16FC(1); // 7
74+
static const CV_16FC2 = MatType.CV_16FC(2); // 15
75+
static const CV_16FC3 = MatType.CV_16FC(3); // 23
76+
static const CV_16FC4 = MatType.CV_16FC(4); // 31
7277

7378
// TODO: extension type do not support override/redeclare methods exist in Object
7479
// such as toString(), if they support this feature, we can just use toString()
@@ -81,7 +86,7 @@ extension type const MatType(int value) {
8186
CV_32S => "CV_32S",
8287
CV_32F => "CV_32F",
8388
CV_64F => "CV_64F",
84-
CV_USRTYPE1 => "CV_USRTYPE1",
89+
CV_16F => "CV_16F",
8590
_ => throw CvdException("Unsupported type value ($value)"),
8691
};
8792
return channels <= 4 ? "${s}C$channels" : "${s}C($channels)";

lib/src/core/vec.dart

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,127 @@ class VecF64Iterator extends VecIterator<double> {
601601
double operator [](int idx) => ref.ptr[idx];
602602
}
603603

604+
class VecF16 extends Vec<cvg.VecF16, double> {
605+
VecF16.fromPointer(super.ptr, [bool attach = true]) : super.fromPointer() {
606+
if (attach) {
607+
Vec.finalizer.attach(this, ptr.cast<ffi.Void>(), detach: this);
608+
Vec.finalizer.attach(this, ptr.ref.ptr.cast<ffi.Void>(), detach: this);
609+
}
610+
}
611+
612+
factory VecF16([int length = 0, double value = 0.0]) => VecF16.generate(length, (i) => value);
613+
factory VecF16.fromList(List<double> pts) => VecF16.generate(pts.length, (i) => pts[i]);
614+
615+
factory VecF16.generate(int length, double Function(int i) generator) {
616+
final pp = calloc<cvg.VecF16>()..ref.length = length;
617+
pp.ref.ptr = calloc<ffi.Uint16>(length);
618+
for (var i = 0; i < length; i++) {
619+
pp.ref.ptr[i] = generator(i).fp16;
620+
}
621+
return VecF16.fromPointer(pp);
622+
}
623+
624+
@override
625+
VecF16 clone() => VecF16.generate(length, (idx) => this[idx]);
626+
627+
@override
628+
int get length => ref.length;
629+
630+
Uint16List get data => ref.ptr.cast<ffi.Uint16>().asTypedList(length);
631+
Iterable<double> get dataFp16 => data.map(float16);
632+
633+
@override
634+
Iterator<double> get iterator => VecF16Iterator(ref);
635+
@override
636+
cvg.VecF16 get ref => ptr.ref;
637+
638+
@override
639+
void dispose() {
640+
Vec.finalizer.detach(this);
641+
calloc.free(ptr.ref.ptr);
642+
calloc.free(ptr);
643+
}
644+
645+
@override
646+
ffi.Pointer<ffi.Void> asVoid() => ref.ptr.cast<ffi.Void>();
647+
648+
@override
649+
void reattach({ffi.Pointer<cvg.VecF16>? newPtr}) {
650+
super.reattach(newPtr: newPtr);
651+
Vec.finalizer.attach(this, ref.ptr.cast<ffi.Void>(), detach: this);
652+
}
653+
654+
@override
655+
void operator []=(int idx, double value) => ref.ptr[idx] = float16Inv(value);
656+
}
657+
658+
class VecF16Iterator extends VecIterator<double> {
659+
VecF16Iterator(this.ref);
660+
cvg.VecF16 ref;
661+
662+
@override
663+
int get length => ref.length;
664+
665+
@override
666+
double operator [](int idx) => float16(ref.ptr[idx]);
667+
}
668+
669+
double float16(int w) {
670+
final t = calloc<ffi.UnsignedInt>()..value = ((w & 0x7fff) << 13) + 0x38000000;
671+
final sign = calloc<ffi.UnsignedInt>()..value = (w & 0x8000) << 16;
672+
final e = calloc<ffi.UnsignedInt>()..value = w & 0x7c00;
673+
674+
final out = calloc<cvg.Cv32suf_C>()..ref.u = t.value + (1 << 23);
675+
if (e.value >= 0x7c00) {
676+
out.ref.u = t.value + 0x38000000;
677+
} else {
678+
if (e.value == 0) {
679+
out.ref.f -= 6.103515625e-05;
680+
} else {
681+
out.ref.u = t.value;
682+
}
683+
}
684+
out.ref.u |= sign.value;
685+
final rval = out.ref.f;
686+
calloc.free(out);
687+
calloc.free(t);
688+
calloc.free(sign);
689+
calloc.free(e);
690+
return rval;
691+
}
692+
693+
int float16Inv(double x) {
694+
final in_ = calloc<cvg.Cv32suf_C>()..ref.f = x;
695+
final sign = calloc<ffi.UnsignedInt>()..value = in_.ref.u & 0x80000000;
696+
final w = calloc<ffi.UnsignedInt>();
697+
in_.ref.u ^= sign.value;
698+
if (in_.ref.u > 0x47800000) {
699+
w.value = in_.ref.u > 0x7f800000 ? 0x7e00 : 0x7c00;
700+
} else {
701+
if (in_.ref.u < 0x38800000) {
702+
in_.ref.f += 0.5;
703+
w.value = in_.ref.u - 0x3f000000;
704+
} else {
705+
final t = calloc<ffi.UnsignedInt>()..value = in_.ref.u + 0xc8000fff;
706+
w.value = (t.value + ((in_.ref.u >> 13) & 1)) >> 13;
707+
calloc.free(t);
708+
}
709+
}
710+
final rval = w.value | (sign.value >> 16);
711+
calloc.free(in_);
712+
calloc.free(sign);
713+
calloc.free(w);
714+
return rval;
715+
}
716+
717+
extension DoubleFp16Extension on double {
718+
int get fp16 => float16Inv(this);
719+
}
720+
721+
extension IntFp16Extension on int {
722+
double get fp16 => float16(this);
723+
}
724+
604725
extension StringVecExtension on String {
605726
VecUChar get u8 {
606727
return cvRunArena<VecUChar>((arena) {
@@ -630,7 +751,7 @@ extension ListUCharExtension on List<int> {
630751
VecI16 get i16 => VecI16.fromList(this);
631752
VecI32 get i32 => VecI32.fromList(this);
632753
VecF32 get f32 => VecF32.fromList(map((e) => e.toDouble()).toList());
633-
VecF64 get f64 => VecF64.fromList(cast<double>());
754+
VecF64 get f64 => VecF64.fromList(map((e) => e.toDouble()).toList());
634755
}
635756

636757
extension ListListCharExtension on List<List<int>> {
@@ -640,6 +761,7 @@ extension ListListCharExtension on List<List<int>> {
640761
extension ListFloatExtension on List<double> {
641762
VecF32 get f32 => VecF32.fromList(this);
642763
VecF64 get f64 => VecF64.fromList(this);
764+
VecF16 get f16 => VecF16.fromList(this);
643765
}
644766

645767
extension ListStringExtension on List<String> {

lib/src/g/core.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -834,12 +834,12 @@ files:
834834
name: openCVVersion_Async
835835
c:@F@registerErrorCallback:
836836
name: registerErrorCallback
837-
c:exception.h@T@ErrorCallback:
838-
name: ErrorCallback
839-
c:math.h@T@double_t:
837+
c:@T@double_t:
840838
name: double_t
841-
c:math.h@T@float_t:
839+
c:@T@float_t:
842840
name: float_t
841+
c:exception.h@T@ErrorCallback:
842+
name: ErrorCallback
843843
c:types.h@T@CvStatus:
844844
name: CvStatus
845845
c:types.h@T@Mat:

lib/src/g/types.g.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ typedef Contour3f = VecPoint3f;
1818
typedef Contours = VecVecPoint;
1919
typedef Contours2f = VecVecPoint2f;
2020
typedef Contours3f = VecVecPoint3f;
21+
22+
final class Cv16suf_C extends ffi.Union {
23+
@ffi.Short()
24+
external int i;
25+
26+
@ushort()
27+
external int u;
28+
}
29+
30+
final class Cv32suf_C extends ffi.Union {
31+
@ffi.Int()
32+
external int i;
33+
34+
@ffi.UnsignedInt()
35+
external int u;
36+
37+
@ffi.Float()
38+
external double f;
39+
}
40+
2141
typedef CvCallback_0 = ffi.Pointer<ffi.NativeFunction<CvCallback_0Function>>;
2242
typedef CvCallback_0Function = ffi.Void Function();
2343
typedef DartCvCallback_0Function = void Function();
@@ -688,6 +708,15 @@ final class VecDMatch extends ffi.Struct {
688708

689709
typedef VecDMatchPtr = ffi.Pointer<VecDMatch>;
690710

711+
final class VecF16 extends ffi.Struct {
712+
external ffi.Pointer<ffi.Uint16> ptr;
713+
714+
@ffi.Size()
715+
external int length;
716+
}
717+
718+
typedef VecF16Ptr = ffi.Pointer<VecF16>;
719+
691720
final class VecF32 extends ffi.Struct {
692721
external ffi.Pointer<ffi.Float> ptr;
693722

lib/src/g/types.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ files:
108108
name: VecChar
109109
c:@S@VecDMatch:
110110
name: VecDMatch
111+
c:@S@VecF16:
112+
name: VecF16
111113
c:@S@VecF32:
112114
name: VecF32
113115
c:@S@VecF64:
@@ -158,6 +160,10 @@ files:
158160
name: VecVecPoint3f
159161
c:@S@VecVecPoint3i:
160162
name: VecVecPoint3i
163+
c:@U@Cv16suf_C:
164+
name: Cv16suf_C
165+
c:@U@Cv32suf_C:
166+
name: Cv32suf_C
161167
c:types.h@T@Contour:
162168
name: Contour
163169
c:types.h@T@Contour2f:
@@ -200,6 +206,8 @@ files:
200206
name: VecCharPtr
201207
c:types.h@T@VecDMatchPtr:
202208
name: VecDMatchPtr
209+
c:types.h@T@VecF16Ptr:
210+
name: VecF16Ptr
203211
c:types.h@T@VecF32Ptr:
204212
name: VecF32Ptr
205213
c:types.h@T@VecF64Ptr:

src/core/core.cpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "core.h"
22
#include "lut.hpp"
3+
#include "opencv2/core/cvdef.h"
34
#include "vec.hpp"
45

56
#include <cassert>
@@ -1547,7 +1548,7 @@ CvStatus *Mat_colRange(Mat m, int start, int end, Mat *rval) {
15471548
CvStatus *LUT(Mat src, Mat lut, Mat dst) {
15481549
BEGIN_WRAP
15491550
auto cn = src.ptr->channels(), depth = src.ptr->depth();
1550-
if (depth == CV_8U || depth == CV_8S) {
1551+
if (lut.ptr->depth() != CV_16F && (depth == CV_8U || depth == CV_8S)) {
15511552
cv::LUT(*src.ptr, *lut.ptr, *dst.ptr);
15521553
} else {
15531554
int lutcn = lut.ptr->channels(), lut_depth = lut.ptr->depth();
@@ -1580,6 +1581,27 @@ CvStatus *LUT(Mat src, Mat lut, Mat dst) {
15801581
int len = (int)it.size;
15811582

15821583
switch (depth) {
1584+
case CV_8U:
1585+
cvd::LUT8u_16f(
1586+
src.ptr->ptr<uchar>(),
1587+
lut.ptr->ptr<cv::hfloat>(),
1588+
dst.ptr->ptr<cv::hfloat>(),
1589+
len,
1590+
cn,
1591+
lutcn
1592+
);
1593+
break;
1594+
case CV_8S:
1595+
cvd::LUT8s_16f(
1596+
src.ptr->ptr<char>(),
1597+
lut.ptr->ptr<cv::hfloat>(),
1598+
dst.ptr->ptr<cv::hfloat>(),
1599+
len,
1600+
cn,
1601+
lutcn
1602+
);
1603+
break;
1604+
15831605
case CV_16U:
15841606
switch (lut_depth) {
15851607
case CV_8U:
@@ -1617,6 +1639,11 @@ CvStatus *LUT(Mat src, Mat lut, Mat dst) {
16171639
src.ptr->ptr<ushort>(), lut.ptr->ptr<double>(), dst.ptr->ptr<double>(), len, cn, lutcn
16181640
);
16191641
break;
1642+
case CV_16F:
1643+
cvd::LUT16u_16f(
1644+
src.ptr->ptr<ushort>(), lut.ptr->ptr<cv::hfloat>(), dst.ptr->ptr<cv::hfloat>(), len, cn, lutcn
1645+
);
1646+
break;
16201647
default:
16211648
cv::String err = "lut Mat Type not supported for CV_16U";
16221649
throw cv::Exception(cv::Error::StsNotImplemented, err, __func__, __FILE__, __LINE__);
@@ -1659,6 +1686,11 @@ CvStatus *LUT(Mat src, Mat lut, Mat dst) {
16591686
src.ptr->ptr<short>(), lut.ptr->ptr<double>(), dst.ptr->ptr<double>(), len, cn, lutcn
16601687
);
16611688
break;
1689+
case CV_16F:
1690+
cvd::LUT16s_16f(
1691+
src.ptr->ptr<short>(), lut.ptr->ptr<cv::hfloat>(), dst.ptr->ptr<cv::hfloat>(), len, cn, lutcn
1692+
);
1693+
break;
16621694
default:
16631695
cv::String err = "lut Mat Type not supported for CV_16S";
16641696
throw cv::Exception(cv::Error::StsNotImplemented, err, __func__, __FILE__, __LINE__);

src/core/lut.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ namespace cvd
1717
dst[i + k] = lut[src[i + k] * cn + k]; \
1818
}
1919

20+
// NOTE: opencv doesn't support LUT from CV_8U or CV_8S to CV_16F now
21+
static void LUT8u_16f(const uchar *src, const cv::hfloat *lut, cv::hfloat *dst, int len, int cn, int lutcn)
22+
{
23+
LUT_BODY
24+
}
25+
26+
static void LUT8s_16f(const char *src, const cv::hfloat *lut, cv::hfloat *dst, int len, int cn, int lutcn)
27+
{
28+
LUT_BODY
29+
}
30+
2031
// 16u
2132
static void LUT16u_8u(const ushort *src, const uchar *lut, uchar *dst, int len, int cn, int lutcn)
2233
{
@@ -48,6 +59,11 @@ static void LUT16u_64f(const ushort *src, const double *lut, double *dst, int le
4859
LUT_BODY
4960
}
5061

62+
static void LUT16u_16f(const ushort *src, const cv::hfloat *lut, cv::hfloat *dst, int len, int cn, int lutcn)
63+
{
64+
LUT_BODY
65+
}
66+
5167
// 16s
5268
static void LUT16s_8u(const short *src, const uchar *lut, uchar *dst, int len, int cn, int lutcn)
5369
{
@@ -79,6 +95,11 @@ static void LUT16s_64f(const short *src, const double *lut, double *dst, int len
7995
LUT_BODY
8096
}
8197

98+
static void LUT16s_16f(const short *src, const cv::hfloat *lut, cv::hfloat *dst, int len, int cn, int lutcn)
99+
{
100+
LUT_BODY
101+
}
102+
82103
// 32s
83104
static void LUT32s_32s(const int *src, const int *lut, int *dst, int len, int cn, int lutcn) { LUT_BODY }
84105

0 commit comments

Comments
 (0)