Files
featherVoice/TencentCloudHuiyanSDKFace_framework/Libs/YTCv.framework/Headers/mat.hpp
2025-08-08 10:49:36 +08:00

647 lines
16 KiB
C++

// fbc_cv is free software and uses the same licence as OpenCV
// Email: fengbingchun@163.com
#ifndef FBC_CV_CORE_MAT_HPP_
#define FBC_CV_CORE_MAT_HPP_
/* reference: include/opencv2/core/mat.hpp
core/src/alloc.cpp
include/opencv2/core/utility.hpp
include/opencv2/core/cvstd.hpp
include/opencv2/core/mat.inl.hpp
*/
#ifndef __cplusplus
#error mat.hpp header must be compiled as C++
#endif
#include <typeinfo>
#include <string.h>
#include <float.h>
#include "fbcdef.hpp"
#include "types.hpp"
#include "base.hpp"
#include "interface.hpp"
#include "fbcstd.hpp"
#include "utility.hpp"
#include "saturate.hpp"
namespace yt_tinycv {
// The class Mat_ represents an n-dimensional dense numerical single-channel or multi-channel array
template<typename _Tp, int chs> class Mat_ {
public:
typedef _Tp value_type;
// default constructor
Mat_() : rows(0), cols(0), channels(0), data(NULL), step(0), allocated(false), datastart(NULL), dataend(NULL) {}
// constructs 2D matrix of the specified size
Mat_(int _rows, int _cols);
// constucts 2D matrix and fills it with the specified value _s
Mat_(int _rows, int _cols, const Scalar& _s);
// constructor for matrix headers pointing to user-allocated data, no data is copied
Mat_(int _rows, int _cols, void* _data);
// copy constructor, NOTE: deep copy
Mat_(const Mat_<_Tp, chs>& _m);
Mat_& operator = (const Mat_& _m);
Mat_ clone() const;
// reports whether the matrix is continuous or not
bool isContinuous() const;
// returns true if the matrix is a submatrix of another matrix
bool isSubmatrix() const;
// copies the matrix content to "_m"
void copyTo(Mat_<_Tp, chs>& _m, const Rect& rect = Rect(0, 0, 0, 0)) const;
// return typed pointer to the specified matrix row,i0, A 0-based row index
const uchar* ptr(int i0 = 0) const;
uchar* ptr(int i0 = 0);
// no data is copied, no memory is allocated
void getROI(Mat_<_Tp, chs>& _m, const Rect& rect = Rect(0, 0, 0, 0));
// Locates the matrix header within a parent matrix
void locateROI(Size& wholeSize, Point& ofs) const;
// Adjusts a submatrix size and position within the parent matrix
void adjustROI(int dtop, int dbottom, int dleft, int dright);
// value converted to the actual array type
void setTo(const Scalar& _value);
// Converts an array to another data type with optional scaling
// the method converts source pixel values to the target data type
// if it does not have a proper size before the operation, it is reallocated
// \f[m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) + \beta )\f]
template<typename _Tp2>
void convertTo(Mat_<_Tp2, chs>& _m, double alpha = 1, const Scalar& scalar = Scalar(0, 0, 0, 0)) const;
Mat_<_Tp, chs>& zeros(int _rows, int _cols);
// returns the matrix cols and rows
Size size() const;
// returns true if Mat_::total() is 0 or if Mat_::data is NULL
bool empty() const;
// returns the matrix element size in bytes: sizeof(_Tp) * channels
size_t elemSize() const;
// returns the size of each matrix element channel in bytes: sizeof(_Tp)
size_t elemSize1() const;
// returns the total number of array elements
size_t total() const;
// release memory
inline void release();
// destructor - calls release()
~Mat_() { release(); };
public:
// the number of rows and columns
int rows, cols;
// channel num
int channels;
// pointer to the data
uchar* data;
// bytes per row
int step; // stride
// memory allocation flag
bool allocated;
// helper fields used in locateROI and adjustROI
const uchar* datastart;
const uchar* dataend;
}; // Mat_
typedef Mat_<uchar, 1> Mat1Gray;
typedef Mat_<uchar, 3> Mat3BGR;
typedef Mat_<uchar, 4> Mat4BGRA;
template<typename _Tp, int chs> inline
void Mat_<_Tp, chs>::release()
{
if (this->data && this->allocated) {
fastFree(this->data);
}
this->data = NULL;
this->datastart = NULL;
this->dataend = NULL;
this->allocated = false;
this->rows = this->cols = this->step = this->channels = 0;
}
template<typename _Tp, int chs>
Mat_<_Tp, chs>::Mat_(int _rows, int _cols)
{
FBC_Assert(_rows > 0 && _cols > 0 && chs > 0);
this->rows = _rows;
this->cols = _cols;
this->channels = chs;
this->step = sizeof(_Tp) * _cols * chs;
this->allocated = true;
size_t size_ = this->rows * this->step;
uchar* p = (uchar*)fastMalloc(size_);
FBC_Assert(p != NULL);
this->data = p;
this->datastart = this->data;
this->dataend = this->data + size_;
}
template<typename _Tp, int chs>
Mat_<_Tp, chs>::Mat_(int _rows, int _cols, const Scalar& _s)
{
FBC_Assert(_rows > 0 && _cols > 0 && chs > 0);
this->rows = _rows;
this->cols = _cols;
this->channels = chs;
this->step = sizeof(_Tp) * _cols * chs;
this->allocated = true;
size_t size_ = this->rows * this->step;
uchar* p = (uchar*)fastMalloc(size_);
FBC_Assert(p != NULL);
this->data = p;
this->datastart = this->data;
this->dataend = this->data + size_;
for (int i = 0; i < _rows; i++) {
_Tp* pRow = (_Tp*)this->data + i * _cols * chs;
for (int j = 0; j < _cols; j++) {
_Tp* pPixel = pRow + j * chs;
for (int m = 0, n = 0; m < chs && n < 4; m++, n++) {
pPixel[n] = saturate_cast<_Tp>(_s.val[n]);
}
}
}
}
template<typename _Tp, int chs>
Mat_<_Tp, chs>::Mat_(int _rows, int _cols, void* _data)
{
FBC_Assert(_rows > 0 && _cols > 0 && chs > 0);
this->rows = _rows;
this->cols = _cols;
this->channels = chs;
this->step = sizeof(_Tp) * _cols * chs;
this->allocated = false;
this->data = (uchar*)_data;
this->datastart = this->data;
this->dataend = this->data + this->step * this->rows;
}
template<typename _Tp, int chs>
Mat_<_Tp, chs>::Mat_(const Mat_<_Tp, chs>& _m)
{
this->rows = _m.rows;
this->cols = _m.cols;
this->channels = _m.channels;
this->step = sizeof(_Tp) * this->cols * this->channels;
size_t size_ = this->rows * this->step;
if (size_ > 0) {
this->allocated = true;
uchar* p = (uchar*)fastMalloc(size_);
FBC_Assert(p != NULL);
memcpy(p, _m.data, size_);
this->data = p;
} else {
this->allocated = false;
this->data = NULL;
}
this->datastart = this->data;
this->dataend = this->data + size_;
}
// template<typename _Tp, int chs>
// Mat_<_Tp, chs>& Mat_<_Tp, chs>::operator () (const Rect& roi)
// {
// return *this;
// }
template<typename _Tp, int chs>
Mat_<_Tp, chs>& Mat_<_Tp, chs>::operator = (const Mat_& _m)
{
size_t size1 = this->rows * this->step;
size_t size2 = _m.rows * _m.step;
this->rows = _m.rows;
this->cols = _m.cols;
this->channels = _m.channels;
this->step = sizeof(_Tp) * this->cols * this->channels;
if ((size1 == size2) && (this->allocated == true) && (this->data != _m.data)) {
memcpy(this->data, _m.data, size2);
} else if (size2 > 0){
if (this->allocated == true) {
fastFree(this->data);
}
this->allocated = true;
uchar* p = (uchar*)fastMalloc(size2);
FBC_Assert(p != NULL);
memcpy(p, _m.data, size2);
this->data = p;
} else {
this->allocated = false;
this->data = NULL;
}
this->datastart = this->data;
this->dataend = this->data + size2;
return *this;
}
template<typename _Tp, int chs>
Mat_<_Tp, chs> Mat_<_Tp, chs>::clone() const
{
Mat_ m;
Rect rect(0, 0, this->cols, this->rows);
copyTo(m, rect);
return m;
}
template<typename _Tp, int chs>
bool Mat_<_Tp, chs>::isContinuous() const
{
return this->rows == 1 || this->step == this->cols * this->elemSize();
}
template<typename _Tp, int chs>
bool Mat_<_Tp, chs>::isSubmatrix() const
{
if ((this->datastart < this->data) || ((this->data + this->step * this->rows) < this->dataend))
return true;
return false;
}
template<typename _Tp, int chs>
void Mat_<_Tp, chs>::copyTo(Mat_<_Tp, chs>& _m, const Rect& rect) const
{
FBC_Assert((this->rows >= rect.y + rect.height) && (this->cols >= rect.x + rect.width));
if (this->data != NULL) {
if ((rect.width > 0) && (rect.height > 0)) {
size_t size1 = sizeof(_Tp) * this->channels * rect.width * rect.height;
int step_ = sizeof(_Tp) * this->channels * rect.width;
size_t size2 = _m.rows * _m.step;
if (size1 == size2) {
uchar* p1 = _m.data;
uchar* p2 = this->data;
for (int i = 0; i < rect.height; i++) {
uchar* p1_ = p1 + i * sizeof(_Tp) * this->channels * rect.width;
uchar* p2_ = p2 + (rect.y + i) * this->step + rect.x * this->channels * sizeof(_Tp);
memcpy(p1_, p2_, step_);
}
} else {
if (_m.allocated == true)
fastFree(_m.data);
uchar* p1 = (uchar*)fastMalloc(size1);
FBC_Assert(p1 != NULL);
uchar* p2 = this->data;
for (int i = 0; i < rect.height; i++) {
uchar* p1_ = p1 + i * sizeof(_Tp) * this->channels * rect.width;
uchar* p2_ = p2 + (rect.y + i) * this->step + rect.x * this->channels * sizeof(_Tp);
memcpy(p1_, p2_, step_);
}
_m.data = p1;
_m.allocated = true;
}
_m.rows = rect.height;
_m.cols = rect.width;
_m.step = step_;
} else {
size_t size1 = this->rows * this->step;
size_t size2 = _m.step * _m.rows;
if (size1 == size2) {
memcpy(_m.data, this->data, size1);
} else {
if (_m.allocated == true)
fastFree(_m.data);
uchar* p = (uchar*)fastMalloc(size1);
FBC_Assert(p != NULL);
memcpy(p, this->data, size1);
_m.data = p;
_m.allocated = true;
}
_m.rows = this->rows;
_m.cols = this->cols;
_m.step = this->step;
}
_m.channels = this->channels;
} else {
if ((_m.data != NULL) && (_m.allocated == true)) {
fastFree(_m.data);
}
_m.data = NULL;
_m.allocated = false;
_m.rows = 0;
_m.cols = 0;
_m.step = 0;
_m.channels = 0;
}
_m.datastart = _m.data;
_m.dataend = _m.data + _m.step * _m.rows;
}
template<typename _Tp, int chs>
const uchar* Mat_<_Tp, chs>::ptr(int i0) const
{
FBC_Assert(i0 < this->rows);
return this->data + i0 * this->step;
}
template<typename _Tp, int chs>
uchar* Mat_<_Tp, chs>::ptr(int i0)
{
FBC_Assert(i0 < this->rows);
return this->data + i0 * this->step;
}
template<typename _Tp, int chs>
void Mat_<_Tp, chs>::getROI(Mat_<_Tp, chs>& _m, const Rect& rect)
{
FBC_Assert((rect.x >= 0) && (rect.y >= 0) && (rect.width > 0) && (rect.height > 0) &&
(this->rows >= rect.y + rect.height) && (this->cols >= rect.x + rect.width));
if (_m.allocated == true) {
fastFree(_m.data);
}
_m.rows = rect.height;
_m.cols = rect.width;
_m.channels = this->channels;
_m.allocated = false;
_m.step = this->step;
_m.data = this->data + rect.y * this->step + rect.x * sizeof(_Tp) * this->channels;
_m.datastart = this->datastart;
_m.dataend = this->dataend;
}
template<typename _Tp, int chs>
void Mat_<_Tp, chs>::locateROI(Size& wholeSize, Point& ofs) const
{
wholeSize.width = this->step / (sizeof(_Tp) * chs);
wholeSize.height = (this->dataend - this->datastart) / this->step;
ofs.y = (this->data - this->datastart) / this->step;
ofs.x = ((this->data - this->datastart) - ((this->data - this->datastart) / this->step * this->step)) / (sizeof(_Tp) * chs);
FBC_Assert(wholeSize.width >= 0 && wholeSize.height >= 0 && ofs.x >= 0 && ofs.y >= 0);
}
template<typename _Tp, int chs>
void Mat_<_Tp, chs>::adjustROI(int dtop, int dbottom, int dleft, int dright)
{
Size wholeSize; Point ofs;
size_t esz = elemSize();
locateROI(wholeSize, ofs);
int row1 = std::max(ofs.y - dtop, 0);
int row2 = std::min(ofs.y + rows + dbottom, wholeSize.height);
int col1 = std::max(ofs.x - dleft, 0);
int col2 = std::min(ofs.x + cols + dright, wholeSize.width);
this->data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
this->rows = row2 - row1;
this->cols = col2 - col1;
}
template<typename _Tp, int chs>
void Mat_<_Tp, chs>::setTo(const Scalar& _value)
{
for (int i = 0; i < this->rows; i++) {
uchar* pRow = this->data + i * this->step;
for (int j = 0; j < this->cols; j++) {
_Tp* pPixel = (_Tp*)pRow + j * chs;
for (int m = 0, n = 0; m < chs && n < 4; m++, n++) {
pPixel[n] = saturate_cast<_Tp>(_value.val[n]);
}
}
}
}
template<typename _Tp, int chs> template<typename _Tp2>
void Mat_<_Tp, chs>::convertTo(Mat_<_Tp2, chs>& _m, double alpha, const Scalar& scalar) const
{
FBC_Assert(this->channels <= 4);
bool noScale = fabs(alpha - 1) < DBL_EPSILON && fabs(scalar[0]) < DBL_EPSILON && fabs(scalar[1]) < DBL_EPSILON &&
fabs(scalar[2]) < DBL_EPSILON && fabs(scalar[3]) < DBL_EPSILON;
/*if ((typeid(_Tp).name() == typeid(_Tp2).name()) && noScale) {
this->copyTo(_m);
return;
}*/
size_t size = this->rows * this->cols * this->channels * sizeof(_Tp2);
if (this->rows * this->cols != _m.rows * _m.cols) {
if (_m.allocated == true) {
fastFree(_m.data);
}
uchar* p = (uchar*)fastMalloc(size);
FBC_Assert(p != NULL);
_m.data = p;
_m.allocated = true;
}
_m.channels = this->channels;
_m.rows = this->rows;
_m.cols = this->cols;
_m.step = _m.cols * sizeof(_Tp2) * _m.channels;
_m.datastart = _m.data;
_m.dataend = _m.data + _m.step * _m.rows;
_Tp2 alpha_ = (_Tp2)alpha;
Scalar_<_Tp2> scalar_;
for (int i = 0; i < 4; i++) {
scalar_.val[i]= (_Tp2)scalar.val[i];
}
for (int i = 0; i < this->rows; i++) {
uchar* p1 = this->data + i * this->step;
uchar* p2 = _m.data + i * _m.step;
for (int j = 0; j < this->cols; j++) {
_Tp* p1_ = (_Tp*)p1 + j * chs;
_Tp2* p2_ = (_Tp2*)p2 + j * chs;
for (int ch = 0; ch < chs; ch++) {
p2_[ch] = saturate_cast<_Tp2>(p1_[ch] * alpha_ + scalar_.val[ch]);
}
}
}
}
template<typename _Tp, int chs>
Mat_<_Tp, chs>& Mat_<_Tp, chs>::zeros(int _rows, int _cols)
{
this->rows = _rows;
this->cols = _cols;
this->channels = chs;
this->step = sizeof(_Tp) * _cols * chs;
this->allocated = true;
size_t size_ = this->rows * this->step;
uchar* p = (uchar*)fastMalloc(size_);
FBC_Assert(p != NULL);
this->data = p;
memset(this->data, 0, size_);
return *this;
}
template<typename _Tp, int chs>
Size Mat_<_Tp, chs>::size() const
{
return Size(this->cols, this->rows);
}
template<typename _Tp, int chs>
size_t Mat_<_Tp, chs>::elemSize() const
{
return (this->channels * sizeof(_Tp));
}
template<typename _Tp, int chs>
size_t Mat_<_Tp, chs>::elemSize1() const
{
return sizeof(_Tp);
}
template<typename _Tp, int chs>
size_t Mat_<_Tp, chs>::total() const
{
return (size_t)rows * cols;
}
template<typename _Tp, int chs>
bool Mat_<_Tp, chs>::empty() const
{
return total() == 0 || this->data == NULL;
}
/////////////////////////// Mat_ out-of-class operators ///////////////////////////
template<typename _Tp1, typename _Tp2, int chs> static inline
Mat_<_Tp1, chs>& operator -= (Mat_<_Tp1, chs>& a, const Mat_<_Tp2, chs>& b)
{
FBC_Assert(a.rows == b.rows && a.cols == b.cols);
for (int y = 0; y < a.rows; y++) {
_Tp1* pa = (_Tp1*)a.ptr(y);
_Tp2* pb = (_Tp2*)b.ptr(y);
for (int x = 0; x < a.cols * chs; x++) {
pa[x] = saturate_cast<_Tp1>(pa[x] - pb[x]);
}
}
return a;
}
template<typename _Tp1, typename _Tp2, int chs> static inline
Mat_<_Tp1, chs>& operator += (Mat_<_Tp1, chs>& a, const Mat_<_Tp2, chs>& b)
{
FBC_Assert(a.rows == b.rows && a.cols == b.cols);
for (int y = 0; y < a.rows; y++) {
_Tp1* pa = (_Tp1*)a.ptr(y);
_Tp2* pb = (_Tp2*)b.ptr(y);
for (int x = 0; x < a.cols * chs; x++) {
pa[x] = saturate_cast<_Tp1>(pa[x] + pb[x]);
}
}
return a;
}
template<typename _Tp1, typename _Tp2, int chs> static inline
Mat_<_Tp1, chs> operator - (const Mat_<_Tp1, chs>& a, const Mat_<_Tp2, chs>& b)
{
FBC_Assert(a.rows == b.rows && a.cols == b.cols);
Mat_<_Tp1, chs> c(a.rows, a.cols);
for (int y = 0; y < a.rows; y++) {
_Tp1* pa = (_Tp1*)a.ptr(y);
_Tp2* pb = (_Tp2*)b.ptr(y);
_Tp1* pc = (_Tp1*)c.ptr(y);
for (int x = 0; x < a.cols * chs; x++) {
pc[x] = saturate_cast<_Tp1>(pa[x] - pb[x]);
}
}
return c;
}
template<typename _Tp1, typename _Tp2, int chs> static inline
Mat_<_Tp1, chs> operator == (const Mat_<_Tp1, chs>& a, const Mat_<_Tp2, chs>& b)
{
FBC_Assert(a.rows == b.rows && a.cols == b.cols);
Mat_<_Tp1, chs> c(a.rows, a.cols);
for (int y = 0; y < a.rows; y++) {
_Tp1* pa = (_Tp1*)a.ptr(y);
_Tp2* pb = (_Tp2*)b.ptr(y);
_Tp1* pc = (_Tp1*)c.ptr(y);
for (int x = 0; x < a.cols * chs; x++) {
pc[x] = pa[x] != pb[x] ? 0 : 1;
}
}
return c;
}
template<typename _Tp, int chs> static inline
Mat_<_Tp, chs> operator & (const Mat_<_Tp, chs>& a, const Mat_<_Tp, chs>& b)
{
FBC_Assert(a.rows == b.rows && a.cols == b.cols);
Mat_<_Tp, chs> c(a.rows, a.cols);
for (int y = 0; y < a.rows; y++) {
_Tp* pa = (_Tp*)a.ptr(y);
_Tp* pb = (_Tp*)b.ptr(y);
_Tp* pc = (_Tp*)c.ptr(y);
for (int x = 0; x < a.cols * chs; x++) {
pc[x] = pa[x] & pb[x];
}
}
return c;
}
} // yt_tinycv
#endif // FBC_CV_CORE_MAT_HPP_