DFace SDK  2.0.0
LTM
mat.h
1 
2 #ifndef DFACE_MAT_H
3 #define DFACE_MAT_H
4 
5 #include <stdlib.h>
6 #include <string.h>
7 #include <math.h>
8 #if __ARM_NEON
9 #include <arm_neon.h>
10 #endif
11 #include "allocator.h"
12 #include "platform.h"
13 #include "def.h"
14 #include "types.h"
15 
16 namespace dface {
17 
23  class DFACE_EXPORTS Mat
24  {
25  public:
33  Mat();
46  Mat(int w, size_t elemsize = 4u, Allocator* allocator = 0);
60  Mat(int w, int h, size_t elemsize = 4u, Allocator* allocator = 0);
75  Mat(int w, int h, int c, size_t elemsize = 4u, Allocator* allocator = 0);
81  Mat(const Mat& m);
88  Mat(int w, void* data, size_t elemsize = 4u, Allocator* allocator = 0);
102  Mat(int w, int h, void* data, size_t elemsize = 4u, Allocator* allocator = 0);
117  Mat(int w, int h, int c, void* data, size_t elemsize = 4u, Allocator* allocator = 0);
118  // release
119  ~Mat();
124  Mat& operator=(const Mat& m);
125  // set all
126  void fill(float v);
127  void fill(int v);
128  template <typename T> void fill(T v);
133  Mat clone(Allocator* allocator = 0) const;
134  // reshape vec
135  Mat reshape(int w, Allocator* allocator = 0) const;
136  // reshape image
137  Mat reshape(int w, int h, Allocator* allocator = 0) const;
145  Mat reshape(int w, int h, int c, Allocator* allocator = 0) const;
146  // allocate vec
147  void create(int w, size_t elemsize = 4u, Allocator* allocator = 0);
154  void create(int w, int h, size_t elemsize = 4u, Allocator* allocator = 0);
162  void create(int w, int h, int c, size_t elemsize = 4u, Allocator* allocator = 0);
163  // refcount++
164  void addref();
165  // refcount--
170  void release();
175  bool empty() const;
176  size_t total() const;
177 
178  // data reference
179  Mat channel(int c);
180  const Mat channel(int c) const;
181  float* row(int y);
182  const float* row(int y) const;
183  template<typename T> T* row(int y);
184  template<typename T> const T* row(int y) const;
185 
186  // range reference
187  Mat channel_range(int c, int channels);
188  const Mat channel_range(int c, int channels) const;
189  Mat row_range(int y, int rows);
190  const Mat row_range(int y, int rows) const;
191  Mat range(int x, int n);
192  const Mat range(int x, int n) const;
193 
194  // access raw data
195  template<typename T> operator T*();
196  template<typename T> operator const T*() const;
197 
198  // convenient access float vec element
199  float& operator[](int i);
200  const float& operator[](int i) const;
201 
205  enum
206  {
207  PIXEL_CONVERT_SHIFT = 16,
208  PIXEL_FORMAT_MASK = 0x0000ffff,
209  PIXEL_CONVERT_MASK = 0xffff0000,
210 
211  PIXEL_RGB = 1,
212  PIXEL_BGR = (1 << 1),
213  PIXEL_GRAY = (1 << 2),
214  PIXEL_RGBA = (1 << 3),
216  PIXEL_RGB2BGR = PIXEL_RGB | (PIXEL_BGR << PIXEL_CONVERT_SHIFT),
217  PIXEL_RGB2GRAY = PIXEL_RGB | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT),
219  PIXEL_BGR2RGB = PIXEL_BGR | (PIXEL_RGB << PIXEL_CONVERT_SHIFT),
220  PIXEL_BGR2GRAY = PIXEL_BGR | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT),
222  PIXEL_GRAY2RGB = PIXEL_GRAY | (PIXEL_RGB << PIXEL_CONVERT_SHIFT),
223  PIXEL_GRAY2BGR = PIXEL_GRAY | (PIXEL_BGR << PIXEL_CONVERT_SHIFT),
225  PIXEL_RGBA2RGB = PIXEL_RGBA | (PIXEL_RGB << PIXEL_CONVERT_SHIFT),
226  PIXEL_RGBA2BGR = PIXEL_RGBA | (PIXEL_BGR << PIXEL_CONVERT_SHIFT),
227  PIXEL_RGBA2GRAY = PIXEL_RGBA | (PIXEL_GRAY << PIXEL_CONVERT_SHIFT),
229  };
230 
243  static Mat from_pixels(const unsigned char* pixels, int type, int w, int h, Allocator* allocator = 0);
244 
245 
260  static Mat from_pixels_resize(const unsigned char* pixels, int type, int w, int h, int target_width, int target_height, Allocator* allocator = 0);
261 
262 
273  void to_pixels(unsigned char* pixels, int type) const;
274 
275 
288  void to_pixels_resize(unsigned char* pixels, int type, int target_width, int target_height) const;
289 
290  // substract channel-wise mean values, then multiply by normalize values, pass 0 to skip
291  void substract_mean_normalize(const float* mean_vals, const float* norm_vals);
292 
299  static Mat from_float16(const unsigned short* data, int size);
300 
312  static void draw_circle(Mat& im, int x0, int y0, int radius, float r, float g, float b);
313 
326  static void draw_circle_thickness(Mat& im, int x0, int y0, int radius, int width, float r, float g, float b);
327 
338  static void draw_line(Mat& im, Point start, Point end, float r, float g, float b);
339 
350  static void draw_box_grayscale(Mat& im, int x1, int y1, int x2, int y2, float g);
351 
364  static void draw_box(Mat &im, int x1, int y1, int x2, int y2, float r, float g, float b);
365 
375  static void draw_bbox(Mat &im, Box bbox, float r, float g, float b);
376 
387  static void draw_bbox_width(Mat &im, Box bbox, int width, float r, float g, float b);
388 
394  static void flip_mat(Mat &input);
395 
399  void* data;
400 
401  // pointer to the reference counter
402  // when points to user-allocated data, the pointer is NULL
403  int* refcount;
404 
405  // element size in bytes
406  // 4 = float32/int32
407  // 2 = float16
408  // 1 = int8/uint8
409  // 0 = empty
410  size_t elemsize;
411 
412  // the allocator
413  Allocator* allocator;
414 
415  // the dimensionality
416  int dims;
417 
418  int w;
419  int h;
420  int c;
421 
422  size_t cstep;
423  };
424 
425 
426  static void resize_bilinear_image(const Mat& src, Mat& dst, int w, int h)
427  {
428  double scale_x = (double)src.w / w;
429  double scale_y = (double)src.h / h;
430 
431  int* buf = new int[w + h + w*2 + h*2];
432 
433  int* xofs = buf;//new int[w];
434  int* yofs = buf + w;//new int[h];
435 
436  float* alpha = (float*)(buf + w + h);//new float[w * 2];
437  float* beta = (float*)(buf + w + h + w*2);//new float[h * 2];
438 
439  float fx;
440  float fy;
441  int sx;
442  int sy;
443 
444  for (int dx = 0; dx < w; dx++)
445  {
446  fx = (float)((dx + 0.5) * scale_x - 0.5);
447  sx = floor(fx);
448  fx -= sx;
449 
450  if (sx < 0)
451  {
452  sx = 0;
453  fx = 0.f;
454  }
455  if (sx >= src.w - 1)
456  {
457  sx = src.w - 2;
458  fx = 1.f;
459  }
460 
461  xofs[dx] = sx;
462 
463  alpha[dx*2 ] = 1.f - fx;
464  alpha[dx*2 + 1] = fx;
465  }
466 
467  for (int dy = 0; dy < h; dy++)
468  {
469  fy = (float)((dy + 0.5) * scale_y - 0.5);
470  sy = floor(fy);
471  fy -= sy;
472 
473  if (sy < 0)
474  {
475  sy = 0;
476  fy = 0.f;
477  }
478  if (sy >= src.h - 1)
479  {
480  sy = src.h - 2;
481  fy = 1.f;
482  }
483 
484  yofs[dy] = sy;
485 
486  beta[dy*2 ] = 1.f - fy;
487  beta[dy*2 + 1] = fy;
488  }
489 
490  // loop body
491  Mat rowsbuf0(w + 1);
492  Mat rowsbuf1(w + 1);
493  float* rows0 = rowsbuf0;
494  float* rows1 = rowsbuf1;
495 
496  int prev_sy1 = -1;
497 
498  for (int dy = 0; dy < h; dy++ )
499  {
500  int sy = yofs[dy];
501 
502  if (sy == prev_sy1)
503  {
504  // hresize one row
505  float* rows0_old = rows0;
506  rows0 = rows1;
507  rows1 = rows0_old;
508  const float* S1 = src.row(sy+1);
509 
510  const float* alphap = alpha;
511  float* rows1p = rows1;
512  int dx = 0;
513 #if __ARM_NEON
514  for ( ; dx+1 < w; dx += 2 )
515  {
516  int sx = xofs[dx];
517  int sxn = xofs[dx+1];
518  const float* S1p = S1 + sx;
519  const float* S1np = S1 + sxn;
520 
521  float32x4_t _a = vld1q_f32(alphap);
522  float32x2_t _S1 = vld1_f32(S1p);
523  float32x2_t _S1n = vld1_f32(S1np);
524 
525  float32x4_t _S1S1n = vcombine_f32(_S1, _S1n);
526  float32x4_t _ms1 = vmulq_f32(_S1S1n, _a);
527  float32x2_t _rows1 = vpadd_f32(vget_low_f32(_ms1), vget_high_f32(_ms1));
528 
529  vst1_f32(rows1p + dx, _rows1);
530 
531  alphap += 4;
532  }
533 #endif // __ARM_NEON
534  for ( ; dx < w; dx++ )
535  {
536  int sx = xofs[dx];
537  const float* S1p = S1 + sx;
538 
539  float a0 = alphap[0];
540  float a1 = alphap[1];
541  rows1p[dx] = S1p[0]*a0 + S1p[1]*a1;
542 
543  alphap += 2;
544  }
545  }
546  else
547  {
548  // hresize two rows
549  const float* S0 = src.row(sy);
550  const float* S1 = src.row(sy+1);
551 
552  const float* alphap = alpha;
553  float* rows0p = rows0;
554  float* rows1p = rows1;
555  int dx = 0;
556 #if __ARM_NEON
557  for ( ; dx+1 < w; dx += 2 )
558  {
559  int sx = xofs[dx];
560  int sxn = xofs[dx+1];
561  const float* S0p = S0 + sx;
562  const float* S1p = S1 + sx;
563  const float* S0np = S0 + sxn;
564  const float* S1np = S1 + sxn;
565 
566  float32x4_t _a = vld1q_f32(alphap);
567  float32x2_t _S0 = vld1_f32(S0p);
568  float32x2_t _S1 = vld1_f32(S1p);
569  float32x2_t _S0n = vld1_f32(S0np);
570  float32x2_t _S1n = vld1_f32(S1np);
571 
572  float32x4_t _S0S0n = vcombine_f32(_S0, _S0n);
573  float32x4_t _S1S1n = vcombine_f32(_S1, _S1n);
574  float32x4_t _ms0 = vmulq_f32(_S0S0n, _a);
575  float32x4_t _ms1 = vmulq_f32(_S1S1n, _a);
576  float32x2_t _rows0 = vpadd_f32(vget_low_f32(_ms0), vget_high_f32(_ms0));
577  float32x2_t _rows1 = vpadd_f32(vget_low_f32(_ms1), vget_high_f32(_ms1));
578 
579  vst1_f32(rows0p + dx, _rows0);
580  vst1_f32(rows1p + dx, _rows1);
581 
582  alphap += 4;
583  }
584 #endif // __ARM_NEON
585  for ( ; dx < w; dx++ )
586  {
587  int sx = xofs[dx];
588  const float* S0p = S0 + sx;
589  const float* S1p = S1 + sx;
590 
591  float a0 = alphap[0];
592  float a1 = alphap[1];
593  rows0p[dx] = S0p[0]*a0 + S0p[1]*a1;
594  rows1p[dx] = S1p[0]*a0 + S1p[1]*a1;
595 
596  alphap += 2;
597  }
598  }
599 
600  prev_sy1 = sy + 1;
601 
602  // vresize
603  float b0 = beta[0];
604  float b1 = beta[1];
605 
606  float* rows0p = rows0;
607  float* rows1p = rows1;
608  float* Dp = dst.row(dy);
609 
610 #if __ARM_NEON
611  int nn = w >> 3;
612 #else
613  int nn = 0;
614 #endif
615  int remain = w - (nn << 3);
616 
617 #if __ARM_NEON
618  float32x4_t _b0 = vdupq_n_f32(b0);
619  float32x4_t _b1 = vdupq_n_f32(b1);
620  for (; nn>0; nn--)
621  {
622  float32x4_t _rows0 = vld1q_f32(rows0p);
623  float32x4_t _rows1 = vld1q_f32(rows1p);
624 
625  float32x4_t _D = vmulq_f32(_rows0, _b0);
626  _D = vmlaq_f32(_D, _rows1, _b1);
627 
628  vst1q_f32(Dp, _D);
629 
630  float32x4_t _rows0n = vld1q_f32(rows0p+4);
631  float32x4_t _rows1n = vld1q_f32(rows1p+4);
632 
633  float32x4_t _Dn = vmulq_f32(_rows0n, _b0);
634  _Dn = vmlaq_f32(_Dn, _rows1n, _b1);
635 
636  vst1q_f32(Dp+4, _Dn);
637 
638  Dp += 8;
639  rows0p += 8;
640  rows1p += 8;
641  }
642 #endif // __ARM_NEON
643  for ( ; remain; --remain )
644  {
645 // D[x] = rows0[x]*b0 + rows1[x]*b1;
646  *Dp++ = *rows0p++ * b0 + *rows1p++ * b1;
647  }
648 
649  beta += 2;
650  }
651 
652  delete[] buf;
653  }
654 
655 
656 // misc function
657 #if DFACE_PIXEL
658 // image pixel bilinear resize
659 // inline void resize_bilinear_c1(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h)
660 // void resize_bilinear_c3(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h);
661 // void resize_bilinear_c4(const unsigned char* src, int srcw, int srch, unsigned char* dst, int w, int h);
662 #endif // DFACE_PIXEL
663 
664 // mat process
665  enum
666  {
667  BORDER_CONSTANT = 0,
668  BORDER_REPLICATE = 1,
669  };
670 // void copy_make_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, int type, float v, Allocator* allocator = 0, int num_threads = 1);
671 
682  inline void copy_cut_border(const Mat& src, Mat& dst, int top, int bottom, int left, int right, Allocator* allocator = 0, int num_threads = 1){
683  int w = dst.w;
684  int h = dst.h;
685 
686  const float* ptr = src.row(top) + left;//.data + src.w * top + left;
687  float* outptr = dst;//.data;
688 
689  for (int y = 0; y < h; y++)
690  {
691  if(w < 12)
692  {
693  for (int x = 0; x < w; x++)
694  {
695  outptr[x] = ptr[x];
696  }
697  }
698  else
699  {
700  memcpy(outptr, ptr, w*sizeof(float));
701  }
702  outptr += w;
703  ptr += src.w;
704  }
705  }
706 
715  inline void resize_bilinear(const Mat& src, Mat& dst, int w, int h, Allocator* allocator = 0, int num_threads = 1){
716  if (w == src.w && h == src.h)
717  {
718  dst = src;
719  return;
720  }
721 
722  size_t elemsize = src.elemsize;
723 
724  if (src.dims == 2)
725  {
726  dst.create(w, h, elemsize, allocator);
727  if (dst.empty())
728  return;
729 
730  resize_bilinear_image(src, dst, w, h);
731  }
732  else if (src.dims == 3)
733  {
734  int channels = src.c;
735 
736  dst.create(w, h, channels, elemsize, allocator);
737  if (dst.empty())
738  return;
739 
740  // unroll image channel
741 #pragma omp parallel for num_threads(num_threads)
742  for (int q=0; q<channels; q++)
743  {
744  const Mat m = src.channel(q);
745  Mat resizem = dst.channel(q);
746 
747  resize_bilinear_image(m, resizem, w, h);
748  }
749  }
750  }
751 
752 // inline void Mat::to_pixels(unsigned char *pixels, int type) const {
753 // if (type & PIXEL_CONVERT_MASK)
754 // {
755 // if (type == PIXEL_RGB2BGR || type == PIXEL_BGR2RGB)
756 // return to_bgr2rgb(*this, pixels);
757 // }
758 // else
759 // {
760 // if (type == PIXEL_RGB || type == PIXEL_BGR)
761 // return to_rgb(*this, pixels);
762 //
763 // if (type == PIXEL_GRAY)
764 // return to_gray(*this, pixels);
765 //
766 // if (type == PIXEL_RGBA)
767 // return to_rgba(*this, pixels);
768 // }
769 //
770 // }
771 //
772 // inline void Mat::to_pixels_resize(unsigned char *pixels, int type, int target_width,
773 // int target_height) const {
774 // if (w == target_width && h == target_height)
775 // return to_pixels(pixels, type);
776 //
777 // int type_to = (type & PIXEL_CONVERT_MASK) ? (type >> PIXEL_CONVERT_SHIFT) : (type & PIXEL_FORMAT_MASK);
778 //
779 // if (type_to == PIXEL_RGB || type_to == PIXEL_BGR)
780 // {
781 // unsigned char* src = new unsigned char[w * h * 3];
782 //
783 // to_pixels(src, type);
784 //
785 // resize_bilinear_c3(src, w, h, pixels, target_width, target_height);
786 //
787 // delete[] src;
788 // }
789 // else if (type_to == PIXEL_GRAY)
790 // {
791 // unsigned char* src = new unsigned char[w * h];
792 //
793 // to_pixels(src, type);
794 //
795 // resize_bilinear_c1(src, w, h, pixels, target_width, target_height);
796 //
797 // delete[] src;
798 // }
799 // else if (type_to == PIXEL_RGBA)
800 // {
801 // unsigned char* src = new unsigned char[w * h * 4];
802 //
803 // to_pixels(src, type);
804 //
805 // resize_bilinear_c4(src, w, h, pixels, target_width, target_height);
806 //
807 // delete[] src;
808 // }
809 // }
810 
811  inline Mat::Mat()
812  : data(0), refcount(0), elemsize(0), allocator(0), dims(0), w(0), h(0), c(0), cstep(0)
813  {
814  }
815 
816  inline Mat::Mat(int _w, size_t _elemsize, Allocator* allocator)
817  : data(0), refcount(0), dims(0)
818  {
819  create(_w, _elemsize, allocator);
820  }
821 
822  inline Mat::Mat(int _w, int _h, size_t _elemsize, Allocator* allocator)
823  : data(0), refcount(0), dims(0)
824  {
825  create(_w, _h, _elemsize, allocator);
826  }
827 
828  inline Mat::Mat(int _w, int _h, int _c, size_t _elemsize, Allocator* allocator)
829  : data(0), refcount(0), dims(0)
830  {
831  create(_w, _h, _c, _elemsize, allocator);
832  }
833 
834  inline Mat::Mat(const Mat& m)
835  : data(m.data), refcount(m.refcount), elemsize(m.elemsize), allocator(m.allocator), dims(m.dims)
836  {
837  if (refcount)
838  DFACE_XADD(refcount, 1);
839 
840  w = m.w;
841  h = m.h;
842  c = m.c;
843 
844  cstep = m.cstep;
845  }
846 
847  inline Mat::Mat(int _w, void* _data, size_t _elemsize, Allocator* _allocator)
848  : data(_data), refcount(0), elemsize(_elemsize), allocator(_allocator), dims(1)
849  {
850  w = _w;
851  h = 1;
852  c = 1;
853 
854  cstep = w;
855  }
856 
857  inline Mat::Mat(int _w, int _h, void* _data, size_t _elemsize, Allocator* _allocator)
858  : data(_data), refcount(0), elemsize(_elemsize), allocator(_allocator), dims(2)
859  {
860  w = _w;
861  h = _h;
862  c = 1;
863 
864  cstep = w * h;
865  }
866 
867  inline Mat::Mat(int _w, int _h, int _c, void* _data, size_t _elemsize, Allocator* _allocator)
868  : data(_data), refcount(0), elemsize(_elemsize), allocator(_allocator), dims(3)
869  {
870  w = _w;
871  h = _h;
872  c = _c;
873 
874  cstep = alignSize(w * h * elemsize, 16) / elemsize;
875  }
876 
877  inline Mat::~Mat()
878  {
879  release();
880  }
881 
882  inline Mat& Mat::operator=(const Mat& m)
883  {
884  if (this == &m)
885  return *this;
886 
887  if (m.refcount)
888  DFACE_XADD(m.refcount, 1);
889 
890  release();
891 
892  data = m.data;
893  refcount = m.refcount;
894  elemsize = m.elemsize;
895  allocator = m.allocator;
896 
897  dims = m.dims;
898  w = m.w;
899  h = m.h;
900  c = m.c;
901 
902  cstep = m.cstep;
903 
904  return *this;
905  }
906 
907  inline void Mat::fill(float _v)
908  {
909  int size = total();
910  float* ptr = (float*)data;
911 
912 #if __ARM_NEON
913  int nn = size >> 2;
914  int remain = size - (nn << 2);
915 #else
916  int remain = size;
917 #endif // __ARM_NEON
918 
919 #if __ARM_NEON
920  float32x4_t _c = vdupq_n_f32(_v);
921 #if __aarch64__
922  if (nn > 0)
923  {
924  asm volatile (
925  "0: \n"
926  "subs %w0, %w0, #1 \n"
927  "st1 {%4.4s}, [%1], #16 \n"
928  "bne 0b \n"
929  : "=r"(nn), // %0
930  "=r"(ptr) // %1
931  : "0"(nn),
932  "1"(ptr),
933  "w"(_c) // %4
934  : "cc", "memory"
935  );
936  }
937 #else
938  if (nn > 0)
939  {
940  asm volatile(
941  "0: \n"
942  "subs %0, #1 \n"
943  "vst1.f32 {%e4-%f4}, [%1 :128]!\n"
944  "bne 0b \n"
945  : "=r"(nn), // %0
946  "=r"(ptr) // %1
947  : "0"(nn),
948  "1"(ptr),
949  "w"(_c) // %4
950  : "cc", "memory"
951  );
952  }
953 #endif // __aarch64__
954 #endif // __ARM_NEON
955  for (; remain>0; remain--)
956  {
957  *ptr++ = _v;
958  }
959  }
960 
961  inline void Mat::fill(int _v)
962  {
963  int size = total();
964  int* ptr = (int*)data;
965 
966 #if __ARM_NEON
967  int nn = size >> 2;
968  int remain = size - (nn << 2);
969 #else
970  int remain = size;
971 #endif // __ARM_NEON
972 
973 #if __ARM_NEON
974  int32x4_t _c = vdupq_n_s32(_v);
975 #if __aarch64__
976  if (nn > 0)
977  {
978  asm volatile (
979  "0: \n"
980  "subs %w0, %w0, #1 \n"
981  "st1 {%4.4s}, [%1], #16 \n"
982  "bne 0b \n"
983  : "=r"(nn), // %0
984  "=r"(ptr) // %1
985  : "0"(nn),
986  "1"(ptr),
987  "w"(_c) // %4
988  : "cc", "memory"
989  );
990  }
991 #else
992  if (nn > 0)
993  {
994  asm volatile(
995  "0: \n"
996  "subs %0, #1 \n"
997  "vst1.s32 {%e4-%f4}, [%1 :128]!\n"
998  "bne 0b \n"
999  : "=r"(nn), // %0
1000  "=r"(ptr) // %1
1001  : "0"(nn),
1002  "1"(ptr),
1003  "w"(_c) // %4
1004  : "cc", "memory"
1005  );
1006  }
1007 #endif // __aarch64__
1008 #endif // __ARM_NEON
1009  for (; remain>0; remain--)
1010  {
1011  *ptr++ = _v;
1012  }
1013  }
1014 
1015  template <typename T>
1016  inline void Mat::fill(T _v)
1017  {
1018  int size = total();
1019  T* ptr = (T*)data;
1020  for (int i=0; i<size; i++)
1021  {
1022  ptr[i] = _v;
1023  }
1024  }
1025 
1026  inline Mat Mat::clone(Allocator* allocator) const
1027  {
1028  if (empty())
1029  return Mat();
1030 
1031  Mat m;
1032  if (dims == 1)
1033  m.create(w, elemsize, allocator);
1034  else if (dims == 2)
1035  m.create(w, h, elemsize, allocator);
1036  else if (dims == 3)
1037  m.create(w, h, c, elemsize, allocator);
1038 
1039  if (total() > 0)
1040  {
1041  memcpy(m.data, data, total() * elemsize);
1042  }
1043 
1044  return m;
1045  }
1046 
1047  inline Mat Mat::reshape(int _w, Allocator* allocator) const
1048  {
1049  if (w * h * c != _w)
1050  return Mat();
1051 
1052  if (dims == 3 && cstep != (size_t)w * h)
1053  {
1054  Mat m;
1055  m.create(_w, elemsize, allocator);
1056 
1057  // flatten
1058  for (int i=0; i<c; i++)
1059  {
1060  const void* ptr = (unsigned char*)data + i * cstep * elemsize;
1061  void* mptr = (unsigned char*)m.data + i * w * h * elemsize;
1062  memcpy(mptr, ptr, w * h * elemsize);
1063  }
1064 
1065  return m;
1066  }
1067 
1068  Mat m = *this;
1069 
1070  m.dims = 1;
1071  m.w = _w;
1072  m.h = 1;
1073  m.c = 1;
1074 
1075  m.cstep = _w;
1076 
1077  return m;
1078  }
1079 
1080  inline Mat Mat::reshape(int _w, int _h, Allocator* allocator) const
1081  {
1082  if (w * h * c != _w * _h)
1083  return Mat();
1084 
1085  if (dims == 3 && cstep != (size_t)w * h)
1086  {
1087  Mat m;
1088  m.create(_w, _h, elemsize, allocator);
1089 
1090  // flatten
1091  for (int i=0; i<c; i++)
1092  {
1093  const void* ptr = (unsigned char*)data + i * cstep * elemsize;
1094  void* mptr = (unsigned char*)m.data + i * w * h * elemsize;
1095  memcpy(mptr, ptr, w * h * elemsize);
1096  }
1097 
1098  return m;
1099  }
1100 
1101  Mat m = *this;
1102 
1103  m.dims = 2;
1104  m.w = _w;
1105  m.h = _h;
1106  m.c = 1;
1107 
1108  m.cstep = _w * _h;
1109 
1110  return m;
1111  }
1112 
1113  inline Mat Mat::reshape(int _w, int _h, int _c, Allocator* allocator) const
1114  {
1115  if (w * h * c != _w * _h * _c)
1116  return Mat();
1117 
1118  if (dims < 3)
1119  {
1120  if ((size_t)_w * _h != alignSize(_w * _h * elemsize, 16) / elemsize)
1121  {
1122  Mat m;
1123  m.create(_w, _h, _c, elemsize, allocator);
1124 
1125  // align channel
1126  for (int i=0; i<_c; i++)
1127  {
1128  const void* ptr = (unsigned char*)data + i * _w * _h * elemsize;
1129  void* mptr = (unsigned char*)m.data + i * m.cstep * m.elemsize;
1130  memcpy(mptr, ptr, _w * _h * elemsize);
1131  }
1132 
1133  return m;
1134  }
1135  }
1136  else if (c != _c)
1137  {
1138  // flatten and then align
1139  Mat tmp = reshape(_w * _h * _c, allocator);
1140  return tmp.reshape(_w, _h, _c, allocator);
1141  }
1142 
1143  Mat m = *this;
1144 
1145  m.dims = 3;
1146  m.w = _w;
1147  m.h = _h;
1148  m.c = _c;
1149 
1150  m.cstep = alignSize(_w * _h * elemsize, 16) / elemsize;
1151 
1152  return m;
1153  }
1154 
1155  inline void Mat::create(int _w, size_t _elemsize, Allocator* _allocator)
1156  {
1157  if (dims == 1 && w == _w && elemsize == _elemsize && allocator == _allocator)
1158  return;
1159 
1160  release();
1161 
1162  elemsize = _elemsize;
1163  allocator = _allocator;
1164 
1165  dims = 1;
1166  w = _w;
1167  h = 1;
1168  c = 1;
1169 
1170  cstep = w;
1171 
1172  if (total() > 0)
1173  {
1174  size_t totalsize = alignSize(total() * elemsize, 4);
1175  if (allocator)
1176  data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount));
1177  else
1178  data = fastMalloc(totalsize + (int)sizeof(*refcount));
1179  refcount = (int*)(((unsigned char*)data) + totalsize);
1180  *refcount = 1;
1181  }
1182  }
1183 
1184  inline void Mat::create(int _w, int _h, size_t _elemsize, Allocator* _allocator)
1185  {
1186  if (dims == 2 && w == _w && h == _h && elemsize == _elemsize && allocator == _allocator)
1187  return;
1188 
1189  release();
1190 
1191  elemsize = _elemsize;
1192  allocator = _allocator;
1193 
1194  dims = 2;
1195  w = _w;
1196  h = _h;
1197  c = 1;
1198 
1199  cstep = w * h;
1200 
1201  if (total() > 0)
1202  {
1203  size_t totalsize = alignSize(total() * elemsize, 4);
1204  if (allocator)
1205  data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount));
1206  else
1207  data = fastMalloc(totalsize + (int)sizeof(*refcount));
1208  refcount = (int*)(((unsigned char*)data) + totalsize);
1209  *refcount = 1;
1210  }
1211  }
1212 
1213  inline void Mat::create(int _w, int _h, int _c, size_t _elemsize, Allocator* _allocator)
1214  {
1215  if (dims == 3 && w == _w && h == _h && c == _c && elemsize == _elemsize && allocator == _allocator)
1216  return;
1217 
1218  release();
1219 
1220  elemsize = _elemsize;
1221  allocator = _allocator;
1222 
1223  dims = 3;
1224  w = _w;
1225  h = _h;
1226  c = _c;
1227 
1228  cstep = alignSize(w * h * elemsize, 16) / elemsize;
1229 
1230  if (total() > 0)
1231  {
1232  size_t totalsize = alignSize(total() * elemsize, 4);
1233  if (allocator)
1234  data = allocator->fastMalloc(totalsize + (int)sizeof(*refcount));
1235  else
1236  data = fastMalloc(totalsize + (int)sizeof(*refcount));
1237  refcount = (int*)(((unsigned char*)data) + totalsize);
1238  *refcount = 1;
1239  }
1240  }
1241 
1242  inline void Mat::addref()
1243  {
1244  if (refcount)
1245  DFACE_XADD(refcount, 1);
1246  }
1247 
1248  inline void Mat::release()
1249  {
1250  if (refcount && DFACE_XADD(refcount, -1) == 1)
1251  {
1252  if (allocator)
1253  allocator->fastFree(data);
1254  else
1255  fastFree(data);
1256  }
1257 
1258  data = 0;
1259 
1260  elemsize = 0;
1261 
1262  dims = 0;
1263  w = 0;
1264  h = 0;
1265  c = 0;
1266 
1267  cstep = 0;
1268 
1269  refcount = 0;
1270  }
1271 
1272  inline bool Mat::empty() const
1273  {
1274  return data == 0 || total() == 0;
1275  }
1276 
1277  inline size_t Mat::total() const
1278  {
1279  return cstep * c;
1280  }
1281 
1282  inline Mat Mat::channel(int c)
1283  {
1284  return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize, allocator);
1285  }
1286 
1287  inline const Mat Mat::channel(int c) const
1288  {
1289  return Mat(w, h, (unsigned char*)data + cstep * c * elemsize, elemsize, allocator);
1290  }
1291 
1292  inline float* Mat::row(int y)
1293  {
1294  return (float*)data + w * y;
1295  }
1296 
1297  inline const float* Mat::row(int y) const
1298  {
1299  return (const float*)data + w * y;
1300  }
1301 
1302  template <typename T>
1303  inline T* Mat::row(int y)
1304  {
1305  return (T*)data + w * y;
1306  }
1307 
1308  template <typename T>
1309  inline const T* Mat::row(int y) const
1310  {
1311  return (const T*)data + w * y;
1312  }
1313 
1314  inline Mat Mat::channel_range(int _c, int channels)
1315  {
1316  return Mat(w, h, channels, (unsigned char*)data + cstep * _c * elemsize, elemsize, allocator);
1317  }
1318 
1319  inline const Mat Mat::channel_range(int _c, int channels) const
1320  {
1321  return Mat(w, h, channels, (unsigned char*)data + cstep * _c * elemsize, elemsize, allocator);
1322  }
1323 
1324  inline Mat Mat::row_range(int y, int rows)
1325  {
1326  return Mat(w, rows, (unsigned char*)data + w * y * elemsize, elemsize, allocator);
1327  }
1328 
1329  inline const Mat Mat::row_range(int y, int rows) const
1330  {
1331  return Mat(w, rows, (unsigned char*)data + w * y * elemsize, elemsize, allocator);
1332  }
1333 
1334  inline Mat Mat::range(int x, int n)
1335  {
1336  return Mat(n, (unsigned char*)data + x * elemsize, elemsize, allocator);
1337  }
1338 
1339  inline const Mat Mat::range(int x, int n) const
1340  {
1341  return Mat(n, (unsigned char*)data + x * elemsize, elemsize, allocator);
1342  }
1343 
1344  template <typename T>
1345  inline Mat::operator T*()
1346  {
1347  return (T*)data;
1348  }
1349 
1350  template <typename T>
1351  inline Mat::operator const T*() const
1352  {
1353  return (const T*)data;
1354  }
1355 
1356  inline float& Mat::operator[](int i)
1357  {
1358  return ((float*)data)[i];
1359  }
1360 
1361  inline const float& Mat::operator[](int i) const
1362  {
1363  return ((const float*)data)[i];
1364  }
1365 
1366 } // namespace dface
1367 
1368 #endif // DFACE_MAT_H
Definition: allocator.h:14
Definition: types.h:32
void * data
Definition: mat.h:399
Mat()
Definition: mat.h:811
bool empty() const
Definition: mat.h:1272
边框信息(人脸,行人,物体等)
Definition: types.h:16
dface内置的图像数据 dface的所有接口只支持dface::Mat(RGB格式)
Definition: mat.h:23
Mat clone(Allocator *allocator=0) const
Definition: mat.h:1026
void release()
Definition: mat.h:1248
Definition: allocator.h:107
Mat & operator=(const Mat &m)
Definition: mat.h:882