@@ -214,12 +214,14 @@ PYBIND11_MODULE(ncnn, m)
214214 mat = new Mat (shape[0 ].cast <int >(), shape[1 ].cast <int >(), elemsize, elempack, allocator);
215215 break ;
216216 case 3 :
217- mat = new Mat (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(),
218- elemsize, elempack, allocator);
217+ mat = new Mat (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(), elemsize, elempack, allocator);
218+ break ;
219+ case 4 :
220+ mat = new Mat (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(), shape[3 ].cast <int >(), elemsize, elempack, allocator);
219221 break ;
220222 default :
221223 std::stringstream ss;
222- ss << " shape must be 1, 2 or 3 dims, not " << shape.size ();
224+ ss << " shape must be 1, 2, 3 or 4 dims, not " << shape.size ();
223225 pybind11::pybind11_fail (ss.str ());
224226 }
225227 return mat;
@@ -235,15 +237,18 @@ PYBIND11_MODULE(ncnn, m)
235237 .def (py::init<int , int , int , size_t , int , Allocator*>(),
236238 py::arg (" w" ), py::arg (" h" ), py::arg (" c" ), py::kw_only (),
237239 py::arg (" elemsize" ) = 4 , py::arg (" elempack" ) = 1 , py::arg (" allocator" ) = nullptr )
240+ .def (py::init<int , int , int , int , size_t , int , Allocator*>(),
241+ py::arg (" w" ), py::arg (" h" ), py::arg (" d" ), py::arg (" c" ), py::kw_only (),
242+ py::arg (" elemsize" ) = 4 , py::arg (" elempack" ) = 1 , py::arg (" allocator" ) = nullptr )
238243
239244 .def (py::init<const Mat&>(), py::arg (" m" ))
240245
241246 .def (py::init ([](py::buffer const b) {
242247 py::buffer_info info = b.request ();
243- if (info.ndim > 3 )
248+ if (info.ndim > 4 )
244249 {
245250 std::stringstream ss;
246- ss << " convert numpy.ndarray to ncnn.Mat only dims <=3 support now, but given " << info.ndim ;
251+ ss << " convert numpy.ndarray to ncnn.Mat only dims <=4 support now, but given " << info.ndim ;
247252 pybind11::pybind11_fail (ss.str ());
248253 }
249254
@@ -283,6 +288,15 @@ PYBIND11_MODULE(ncnn, m)
283288 // so we set the cstep as numpy's cstep
284289 v->cstep = (int )info.shape [2 ] * (int )info.shape [1 ];
285290 }
291+ else if (info.ndim == 4 )
292+ {
293+ v = new Mat ((int )info.shape [3 ], (int )info.shape [2 ], (int )info.shape [1 ], (int )info.shape [0 ], info.ptr , elemsize);
294+
295+ // in ncnn, buffer to construct ncnn::Mat need align to ncnn::alignSize
296+ // with (w * h * d elemsize, 16) / elemsize, but the buffer from numpy not
297+ // so we set the cstep as numpy's cstep
298+ v->cstep = (int )info.shape [3 ] * (int )info.shape [2 ] * (int )info.shape [1 ];
299+ }
286300 return v;
287301 }),
288302 py::arg (" array" ))
@@ -323,6 +337,17 @@ PYBIND11_MODULE(ncnn, m)
323337 strides.push_back (m.w * m.elemsize );
324338 strides.push_back (m.elemsize );
325339 }
340+ else if (m.dims == 4 )
341+ {
342+ shape.push_back (m.c );
343+ shape.push_back (m.d );
344+ shape.push_back (m.h );
345+ shape.push_back (m.w );
346+ strides.push_back (m.cstep * m.elemsize );
347+ strides.push_back (m.w * m.h * m.elemsize );
348+ strides.push_back (m.w * m.elemsize );
349+ strides.push_back (m.elemsize );
350+ }
326351 return py::buffer_info (
327352 m.data , /* Pointer to buffer */
328353 m.elemsize , /* Size of one scalar */
@@ -347,9 +372,11 @@ PYBIND11_MODULE(ncnn, m)
347372 return mat.reshape (shape[0 ].cast <int >(), shape[1 ].cast <int >(), allocator);
348373 case 3 :
349374 return mat.reshape (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(), allocator);
375+ case 4 :
376+ return mat.reshape (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(), shape[3 ].cast <int >(), allocator);
350377 default :
351378 std::stringstream ss;
352- ss << " shape must be 1, 2 or 3 dims, not " << shape.size ();
379+ ss << " shape must be 1, 2, 3 or 4 dims, not " << shape.size ();
353380 pybind11::pybind11_fail (ss.str ());
354381 }
355382 return Mat ();
@@ -361,6 +388,8 @@ PYBIND11_MODULE(ncnn, m)
361388 py::arg (" w" ), py::arg (" h" ), py::kw_only (), py::arg (" allocator" ) = nullptr )
362389 .def (" reshape" , (Mat (Mat::*)(int , int , int , Allocator*) const ) & Mat::reshape,
363390 py::arg (" w" ), py::arg (" h" ), py::arg (" c" ), py::kw_only (), py::arg (" allocator" ) = nullptr )
391+ .def (" reshape" , (Mat (Mat::*)(int , int , int , int , Allocator*) const ) & Mat::reshape,
392+ py::arg (" w" ), py::arg (" h" ), py::arg (" d" ), py::arg (" c" ), py::kw_only (), py::arg (" allocator" ) = nullptr )
364393
365394 .def (
366395 " create" ,
@@ -372,11 +401,12 @@ PYBIND11_MODULE(ncnn, m)
372401 case 2 :
373402 return mat.create (shape[0 ].cast <int >(), shape[1 ].cast <int >(), elemsize, elempack, allocator);
374403 case 3 :
375- return mat.create (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(),
376- elemsize, elempack, allocator);
404+ return mat.create (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(), elemsize, elempack, allocator);
405+ case 4 :
406+ return mat.create (shape[0 ].cast <int >(), shape[1 ].cast <int >(), shape[2 ].cast <int >(), shape[3 ].cast <int >(), elemsize, elempack, allocator);
377407 default :
378408 std::stringstream ss;
379- ss << " shape must be 1, 2 or 3 dims, not " << shape.size ();
409+ ss << " shape must be 1, 2, 3 or 4 dims, not " << shape.size ();
380410 pybind11::pybind11_fail (ss.str ());
381411 }
382412 return ;
@@ -393,6 +423,9 @@ PYBIND11_MODULE(ncnn, m)
393423 .def (" create" , (void (Mat::*)(int , int , int , size_t , int , Allocator*)) & Mat::create,
394424 py::arg (" w" ), py::arg (" h" ), py::arg (" c" ), py::kw_only (),
395425 py::arg (" elemsize" ) = 4 , py::arg (" elempack" ) = 1 , py::arg (" allocator" ) = nullptr )
426+ .def (" create" , (void (Mat::*)(int , int , int , int , size_t , int , Allocator*)) & Mat::create,
427+ py::arg (" w" ), py::arg (" h" ), py::arg (" d" ), py::arg (" c" ), py::kw_only (),
428+ py::arg (" elemsize" ) = 4 , py::arg (" elempack" ) = 1 , py::arg (" allocator" ) = nullptr )
396429 .def (" create_like" , (void (Mat::*)(const Mat&, Allocator*)) & Mat::create_like,
397430 py::arg (" m" ), py::arg (" allocator" ) = nullptr )
398431 .def (" addref" , &Mat::addref)
@@ -403,6 +436,8 @@ PYBIND11_MODULE(ncnn, m)
403436 .def (" shape" , &Mat::shape)
404437 .def (" channel" , (Mat (Mat::*)(int )) & Mat::channel, py::arg (" c" ))
405438 // .def("channel", (const Mat (Mat::*)(int) const) & Mat::channel, py::arg("c"))
439+ .def (" depth" , (Mat (Mat::*)(int )) & Mat::depth, py::arg (" z" ))
440+ // .def("depth", (const Mat (Mat::*)(int) const) & Mat::depth, py::arg("z"))
406441 .def (
407442 " row" ,
408443 [](Mat& m, int y) {
@@ -431,6 +466,8 @@ PYBIND11_MODULE(ncnn, m)
431466 py::arg (" y" ))
432467 .def (" channel_range" , (Mat (Mat::*)(int , int )) & Mat::channel_range, py::arg (" c" ), py::arg (" channels" ))
433468 // .def("channel_range", (const Mat (Mat::*)(int, int) const) & Mat::channel_range, py::arg("c"), py::arg("channels"))
469+ .def (" depth_range" , (Mat (Mat::*)(int , int )) & Mat::depth_range, py::arg (" z" ), py::arg (" depths" ))
470+ // .def("depth_range", (const Mat (Mat::*)(int, int) const) & Mat::depth_range, py::arg("z"), py::arg("depths"))
434471 .def (" row_range" , (Mat (Mat::*)(int , int )) & Mat::row_range, py::arg (" y" ), py::arg (" rows" ))
435472 // .def("row_range", (const Mat (Mat::*)(int, int) const) & Mat::row_range, py::arg("y"), py::arg("rows"))
436473 .def (" range" , (Mat (Mat::*)(int , int )) & Mat::range, py::arg (" x" ), py::arg (" n" ))
@@ -508,11 +545,12 @@ PYBIND11_MODULE(ncnn, m)
508545 .def_readwrite (" dims" , &Mat::dims)
509546 .def_readwrite (" w" , &Mat::w)
510547 .def_readwrite (" h" , &Mat::h)
548+ .def_readwrite (" d" , &Mat::d)
511549 .def_readwrite (" c" , &Mat::c)
512550 .def_readwrite (" cstep" , &Mat::cstep)
513551 .def (" __repr__" , [](const Mat& m) {
514552 std::stringstream ss;
515- ss << " <ncnn.Mat w=" << m.w << " h=" << m.h << " c=" << m.c << " dims=" << m.dims
553+ ss << " <ncnn.Mat w=" << m.w << " h=" << m.h << " d= " << m. d << " c=" << m.c << " dims=" << m.dims
516554 << " cstep=" << m.cstep << " elemsize=" << m.elemsize << " elempack=" << m.elempack << " \n\t "
517555 << " refcount=" << (m.refcount ? *m.refcount : 0 ) << " data=0x" << static_cast <const void *>(m.data )
518556 << " allocator=0x" << static_cast <const void *>(m.allocator ) << " >\n " ;
@@ -720,6 +758,119 @@ PYBIND11_MODULE(ncnn, m)
720758 } // for k
721759 ss << " ]\n " ;
722760 }
761+ else if (m.dims == 4 )
762+ {
763+ bool dot_printed_c = false ;
764+ ss << " [" ;
765+ for (int k = 0 ; k < m.c ; k++)
766+ {
767+ bool dot_printed_d = false ;
768+ if (k < max_count / 2 || k >= m.c - max_count / 2 )
769+ {
770+ Mat channel = m.channel (k);
771+ if (k > 0 )
772+ {
773+ ss << " " ;
774+ }
775+ ss << " [" ;
776+ for (int z = 0 ; z < channel.d ; z++)
777+ {
778+ bool dot_printed_h = false ;
779+ if (z < max_count / 2 || z >= channel.d - max_count / 2 )
780+ {
781+ if (z > 0 )
782+ {
783+ ss << " " ;
784+ }
785+ ss << " [" ;
786+ for (int j = 0 ; j < channel.h ; j++)
787+ {
788+ bool dot_printed_w = false ;
789+ if (j < max_count / 2 || j >= channel.h - max_count / 2 )
790+ {
791+ if (j > 0 )
792+ {
793+ ss << " " ;
794+ }
795+ ss << " [" ;
796+ if (m.elemsize == 1 )
797+ {
798+ const int8_t * row = channel.depth (z).row <int8_t >(j);
799+ for (int i = 0 ; i < channel.w ; i++)
800+ {
801+ if (i < max_count / 2 || i >= channel.w - max_count / 2 )
802+ {
803+ if (i > 0 )
804+ {
805+ ss << " , " ;
806+ }
807+ ss << static_cast <int >(row[i]);
808+ }
809+ else if (!dot_printed_w)
810+ {
811+ dot_printed_w = true ;
812+ ss << " , ..." ;
813+ }
814+ }
815+ }
816+ if (m.elemsize == 4 )
817+ {
818+ const float * row = channel.depth (z).row <float >(j);
819+ for (int i = 0 ; i < m.w ; i++)
820+ {
821+ if (i < max_count / 2 || i >= m.w - max_count / 2 )
822+ {
823+ if (i > 0 )
824+ {
825+ ss << " , " ;
826+ }
827+ ss << row[i];
828+ }
829+ else if (!dot_printed_w)
830+ {
831+ dot_printed_w = true ;
832+ ss << " , ..." ;
833+ }
834+ }
835+ }
836+ ss << " ]" ;
837+ if (j < channel.h - 1 )
838+ {
839+ ss << " \n " ;
840+ }
841+ }
842+ else if (!dot_printed_h)
843+ {
844+ dot_printed_h = true ;
845+ ss << " ...\n " ;
846+ }
847+ } // for j
848+ ss << " ]" ;
849+ if (z < channel.d - 1 )
850+ {
851+ ss << " \n " ;
852+ }
853+ }
854+ else if (!dot_printed_d)
855+ {
856+ dot_printed_d = true ;
857+ ss << " ...\n " ;
858+ }
859+ } // for z
860+ ss << " ]" ;
861+ if (k < m.c - 1 )
862+ {
863+ ss << " \n\n " ;
864+ }
865+ }
866+ else if (!dot_printed_c)
867+ {
868+ dot_printed_c = true ;
869+ ss << " ...\n " ;
870+ }
871+ } // for k
872+ ss << " ]\n " ;
873+ }
723874 return ss.str ();
724875 });
725876
@@ -932,6 +1083,21 @@ PYBIND11_MODULE(ncnn, m)
9321083 py::arg (" top" ), py::arg (" bottom" ), py::arg (" left" ), py::arg (" right" ),
9331084 py::arg (" type" ), py::arg (" v" ), py::arg (" opt" ) = Option ());
9341085
1086+ m.def (" copy_make_border_3d" , ©_make_border_3d,
1087+ py::arg (" src" ), py::arg (" dst" ),
1088+ py::arg (" top" ), py::arg (" bottom" ), py::arg (" left" ), py::arg (" right" ), py::arg (" front" ), py::arg (" behind" ),
1089+ py::arg (" type" ), py::arg (" v" ), py::arg (" opt" ) = Option ());
1090+ m.def (
1091+ " copy_make_border_3d" ,
1092+ [](const Mat& src, int top, int bottom, int left, int right, int front, int behind, int type, float v, const Option& opt) {
1093+ Mat dst;
1094+ copy_make_border_3d (src, dst, top, bottom, left, right, front, behind, type, v, opt);
1095+ return dst;
1096+ },
1097+ py::arg (" src" ),
1098+ py::arg (" top" ), py::arg (" bottom" ), py::arg (" left" ), py::arg (" right" ), py::arg (" front" ), py::arg (" behind" ),
1099+ py::arg (" type" ), py::arg (" v" ), py::arg (" opt" ) = Option ());
1100+
9351101 m.def (" copy_cut_border" , ©_cut_border,
9361102 py::arg (" src" ), py::arg (" dst" ),
9371103 py::arg (" top" ), py::arg (" bottom" ), py::arg (" left" ), py::arg (" right" ),
0 commit comments