11 #ifndef CVCORE_TENSOR_H
12 #define CVCORE_TENSOR_H
14 #include <initializer_list>
17 #include <type_traits>
22 using half = std::uint16_t;
204 std::size_t
getSize(
int dimIdx)
const;
247 static constexpr
int kMinDimCount = 2;
248 static constexpr
int kMaxDimCount = 4;
253 DimData m_dimData[kMaxDimCount];
262 template<TensorLayout TL>
265 static_assert(TL ==
LC || TL ==
CL,
"unsupported variant!");
270 template<TensorLayout TL>
273 static_assert(TL ==
HWC || TL ==
CHW,
"unsupported variant!");
279 template<TensorLayout TL>
282 static_assert(TL ==
DHWC || TL ==
DCHW || TL ==
CDHW,
"unsupported variant!");
289 template<TensorLayout TL,
typename =
void>
294 template<TensorLayout TL>
297 static constexpr
int kDimCount = 2;
300 template<TensorLayout TL>
303 static constexpr
int kDimCount = 3;
306 template<TensorLayout TL>
307 struct LayoutToIndex<TL, typename std::enable_if<TL == DHWC || TL == DCHW || TL == CDHW>::type>
310 static constexpr
int kDimCount = 4;
313 template<ChannelType CT>
360 template<ChannelCount CC>
382 template<TensorLayout TL, ChannelType CT>
409 Tensor2D(std::initializer_list<DimData> dimData, DataType *dataPtr,
bool isCPU)
451 throw std::out_of_range(
"cvcore::Tensor2D::getStride ==> Requested TensorDimension is out of bounds");
479 template<TensorLayout TL, ChannelType CT>
506 Tensor3D(std::initializer_list<DimData> dimData, DataType *dataPtr,
bool isCPU)
559 throw std::out_of_range(
"cvcore::Tensor3D::getStride ==> Requested TensorDimension is out of bounds");
587 template<TensorLayout TL, ChannelType CT>
614 Tensor4D(std::initializer_list<DimData> dimData, DataType *dataPtr,
bool isCPU)
678 throw std::out_of_range(
"cvcore::Tensor4D::getStride ==> Requested TensorDimension is out of bounds");
703 template<TensorLayout TL, ChannelCount CC, ChannelType CT>
713 template<ChannelCount CC, ChannelType CT>
723 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
724 Tensor(std::size_t length,
bool isCPU =
true)
725 : detail::Tensor2D<
LC, CT>({{length, detail::ChannelToCount<CC>()}, {detail::ChannelToCount<CC>(), 1}}, isCPU)
729 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
730 Tensor(std::size_t length, std::size_t channelCount,
bool isCPU =
true)
731 : detail::Tensor2D<
LC, CT>({{length, channelCount}, {channelCount, 1}}, isCPU)
735 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
737 : detail::Tensor2D<
LC, CT>({{length, detail::ChannelToCount<CC>()}, {detail::ChannelToCount<CC>(), 1}}, dataPtr,
742 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
743 Tensor(std::size_t length, std::size_t channelCount,
DataType *dataPtr,
bool isCPU =
true)
744 : detail::Tensor2D<
LC, CT>({{length, channelCount}, {channelCount, 1}}, dataPtr, isCPU)
754 template<ChannelCount CC, ChannelType CT>
764 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
765 Tensor(std::size_t length,
bool isCPU =
true)
766 : detail::Tensor2D<
CL, CT>({{detail::ChannelToCount<CC>(), length}, {length, 1}}, isCPU)
770 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
771 Tensor(std::size_t length, std::size_t channelCount,
bool isCPU =
true)
772 : detail::Tensor2D<
CL, CT>({{channelCount, length}, {length, 1}}, isCPU)
776 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
778 : detail::Tensor2D<
CL, CT>({{detail::ChannelToCount<CC>(), length}, {length, 1}}, dataPtr, isCPU)
782 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
783 Tensor(std::size_t length, std::size_t channelCount,
DataType *dataPtr,
bool isCPU =
true)
784 : detail::Tensor2D<
CL, CT>({{channelCount, length}, {length, 1}}, dataPtr, isCPU)
796 template<ChannelCount CC, ChannelType CT>
807 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
808 Tensor(std::size_t width, std::size_t height, B isCPU =
true)
809 : detail::Tensor3D<
HWC, CT>({{height, width * detail::ChannelToCount<CC>()},
810 {width, detail::ChannelToCount<CC>()},
811 {detail::ChannelToCount<CC>(), 1}},
817 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
818 Tensor(std::size_t width, std::size_t height, std::size_t channelCount, B isCPU =
true)
819 : detail::Tensor3D<
HWC, CT>({{height, width * channelCount}, {width, channelCount}, {channelCount, 1}}, isCPU)
824 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
826 : detail::Tensor3D<
HWC, CT>({{height, width * detail::ChannelToCount<CC>()},
827 {width, detail::ChannelToCount<CC>()},
828 {detail::ChannelToCount<CC>(), 1}},
834 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
835 Tensor(std::size_t width, std::size_t height, std::size_t rowPitch,
DataType *dataPtr, B isCPU =
true)
837 {width, detail::ChannelToCount<CC>()},
838 {detail::ChannelToCount<CC>(), 1}},
843 throw std::domain_error(
844 "cvcore::Tensor<HWC, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
849 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
850 Tensor(std::size_t width, std::size_t height, std::size_t channelCount,
DataType *dataPtr, B isCPU =
true)
851 : detail::Tensor3D<
HWC, CT>({{height, width * channelCount}, {width, channelCount}, {channelCount, 1}}, dataPtr,
857 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
858 Tensor(std::size_t width, std::size_t height, std::size_t channelCount, std::size_t rowPitch,
DataType *dataPtr,
860 : detail::Tensor3D<
HWC, CT>({{height, rowPitch /
GetChannelSize(CT)}, {width, channelCount}, {channelCount, 1}},
865 throw std::domain_error(
866 "cvcore::Tensor<HWC, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
876 template<ChannelCount CC, ChannelType CT>
886 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
887 Tensor(std::size_t width, std::size_t height,
bool isCPU =
true)
888 : detail::Tensor3D<
CHW, CT>({{detail::ChannelToCount<CC>(), width * height}, {height, width}, {width, 1}},
893 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
894 Tensor(std::size_t width, std::size_t height, std::size_t channelCount,
bool isCPU =
true)
895 : detail::Tensor3D<
CHW, CT>({{channelCount, width * height}, {height, width}, {width, 1}}, isCPU)
899 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
900 Tensor(std::size_t width, std::size_t height,
DataType *dataPtr,
bool isCPU =
true)
901 : detail::Tensor3D<
CHW, CT>({{detail::ChannelToCount<CC>(), width * height}, {height, width}, {width, 1}},
907 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
908 Tensor(std::size_t width, std::size_t height, std::size_t rowPitch,
DataType *dataPtr, B isCPU =
true)
909 : detail::Tensor3D<
CHW, CT>({{detail::ChannelToCount<CC>(), height * rowPitch /
GetChannelSize(CT)},
916 throw std::domain_error(
917 "cvcore::Tensor<CHW, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
921 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
922 Tensor(std::size_t width, std::size_t height, std::size_t channelCount,
DataType *dataPtr,
bool isCPU =
true)
923 : detail::Tensor3D<
CHW, CT>({{channelCount, width * height}, {height, width}, {width, 1}}, dataPtr, isCPU)
928 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
929 Tensor(std::size_t width, std::size_t height, std::size_t channelCount, std::size_t rowPitch,
DataType *dataPtr,
931 : detail::Tensor3D<
CHW, CT>({{channelCount, height * rowPitch /
GetChannelSize(CT)},
938 throw std::domain_error(
939 "cvcore::Tensor<CHW, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
951 template<ChannelCount CC, ChannelType CT>
962 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
963 Tensor(std::size_t width, std::size_t height, std::size_t depth, B isCPU =
true)
964 : detail::Tensor4D<
DHWC, CT>({{depth, height * width * detail::ChannelToCount<CC>()},
965 {height, width * detail::ChannelToCount<CC>()},
966 {width, detail::ChannelToCount<CC>()},
967 {detail::ChannelToCount<CC>(), 1}},
973 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
974 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount, B isCPU =
true)
975 : detail::Tensor4D<
DHWC, CT>({{depth, height * width * channelCount},
976 {height, width * channelCount},
977 {width, channelCount},
984 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
985 Tensor(std::size_t width, std::size_t height, std::size_t depth,
DataType *dataPtr, B isCPU =
true)
986 : detail::Tensor4D<
DHWC, CT>({{depth, height * width * detail::ChannelToCount<CC>()},
987 {height, width * detail::ChannelToCount<CC>()},
988 {width, detail::ChannelToCount<CC>()},
989 {detail::ChannelToCount<CC>(), 1}},
995 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
996 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t rowPitch,
DataType *dataPtr,
1000 {width, detail::ChannelToCount<CC>()},
1001 {detail::ChannelToCount<CC>(), 1}},
1006 throw std::domain_error(
1007 "cvcore::Tensor<DHWC, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
1012 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
1013 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount,
DataType *dataPtr,
1015 : detail::Tensor4D<
DHWC, CT>({{depth, height * width * channelCount},
1016 {height, width * channelCount},
1017 {width, channelCount},
1024 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
1025 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount, std::size_t rowPitch,
1029 {width, channelCount},
1035 throw std::domain_error(
1036 "cvcore::Tensor<DHWC, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
1046 template<ChannelCount CC, ChannelType CT>
1056 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
1057 Tensor(std::size_t width, std::size_t height, std::size_t depth,
bool isCPU =
true)
1058 : detail::Tensor4D<
DCHW, CT>({{depth, detail::ChannelToCount<CC>() * width * height},
1059 {detail::ChannelToCount<CC>(), width * height},
1066 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
1067 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount,
bool isCPU =
true)
1068 : detail::Tensor4D<
DCHW, CT>(
1069 {{depth, channelCount * width * height}, {channelCount, width * height}, {height, width}, {width, 1}},
1074 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
1075 Tensor(std::size_t width, std::size_t height, std::size_t depth,
DataType *dataPtr,
bool isCPU =
true)
1076 : detail::Tensor4D<
DCHW, CT>({{depth, detail::ChannelToCount<CC>() * width * height},
1077 {detail::ChannelToCount<CC>(), width * height},
1085 typename std::enable_if<T != CX && std::is_same<B, bool>::value>::type * =
nullptr>
1086 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t rowPitch,
DataType *dataPtr,
1088 : detail::Tensor4D<
DCHW, CT>({{depth, detail::ChannelToCount<CC>() * height * rowPitch /
GetChannelSize(CT)},
1089 {detail::ChannelToCount<CC>(), height * rowPitch /
GetChannelSize(CT)},
1096 throw std::domain_error(
1097 "cvcore::Tensor<DCHW, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
1101 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
1102 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount,
DataType *dataPtr,
1104 : detail::Tensor4D<
DCHW, CT>(
1105 {{depth, channelCount * width * height}, {channelCount, width * height}, {height, width}, {width, 1}},
1111 typename std::enable_if<T == CX && std::is_same<B, bool>::value>::type * =
nullptr>
1112 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount, std::size_t rowPitch,
1114 : detail::Tensor4D<
DCHW, CT>({{depth, channelCount * height * rowPitch /
GetChannelSize(CT)},
1122 throw std::domain_error(
1123 "cvcore::Tensor<DCHW, CC, CT>::Tensor ==> Parameter rowPitch is not evenly divisible by channel size");
1133 template<ChannelCount CC, ChannelType CT>
1143 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
1144 Tensor(std::size_t width, std::size_t height, std::size_t depth,
bool isCPU =
true)
1145 : detail::Tensor4D<
CDHW, CT>({{detail::ChannelToCount<CC>(), depth * width * height},
1146 {depth, width * height},
1153 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
1154 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount,
bool isCPU =
true)
1155 : detail::Tensor4D<
CDHW, CT>(
1156 {{channelCount, depth * width * height}, {depth, width * height}, {height, width}, {width, 1}}, isCPU)
1160 template<ChannelCount T = CC, typename = typename std::enable_if<T != CX>::type>
1161 Tensor(std::size_t width, std::size_t height, std::size_t depth,
DataType *dataPtr,
bool isCPU =
true)
1162 : detail::Tensor4D<
CDHW, CT>({{detail::ChannelToCount<CC>(), depth * width * height},
1163 {depth, width * height},
1170 template<ChannelCount T = CC, typename = typename std::enable_if<T == CX>::type>
1171 Tensor(std::size_t width, std::size_t height, std::size_t depth, std::size_t channelCount,
DataType *dataPtr,
1173 : detail::Tensor4D<
CDHW, CT>(
1174 {{channelCount, depth * width * height}, {depth, width * height}, {height, width}, {width, 1}}, dataPtr,
1182 #endif // CVCORE_TENSOR_H