增加换肤功能
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_NARY_MAT_ITERATOR_HPP_
|
||||
#define FBC_CV_CORE_NARY_MAT_ITERATOR_HPP_
|
||||
|
||||
/* reference: include/opencv2/core/map.hpp
|
||||
modules/core/src/matrix.cpp
|
||||
*/
|
||||
|
||||
#include "mat.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
// n-ary multi-dimensional array iterator
|
||||
// Use the class to implement unary, binary, and, generally, n-ary element-wise operations on multi - dimensional arrays.
|
||||
template<typename _Tp, int chs> class NAryMatIterator {
|
||||
public:
|
||||
// the default constructor
|
||||
NAryMatIterator();
|
||||
// the full constructor taking arbitrary number of n-dim matrices
|
||||
NAryMatIterator(const Mat_<_Tp, chs>** arrays, uchar** ptrs, int narrays = -1);
|
||||
// the full constructor taking arbitrary number of n-dim matrices
|
||||
NAryMatIterator(const Mat_<_Tp, chs>** arrays, Mat_<_Tp, chs>* planes, int narrays = -1);
|
||||
// the separate iterator initialization method
|
||||
void init(const Mat_<_Tp, chs>** arrays, Mat_<_Tp, chs>* planes, uchar** ptrs, int narrays = -1);
|
||||
|
||||
// proceeds to the next plane of every iterated matrix
|
||||
NAryMatIterator& operator ++();
|
||||
// proceeds to the next plane of every iterated matrix (postfix increment operator)
|
||||
NAryMatIterator operator ++(int);
|
||||
|
||||
// the iterated arrays
|
||||
const Mat_<_Tp, chs>** arrays;
|
||||
// the current planes
|
||||
Mat_<_Tp, chs>* planes;
|
||||
// data pointers
|
||||
uchar** ptrs;
|
||||
// the number of arrays
|
||||
int narrays;
|
||||
// the number of hyper-planes that the iterator steps through
|
||||
size_t nplanes;
|
||||
// the size of each segment (in elements)
|
||||
size_t size;
|
||||
protected:
|
||||
int iterdepth;
|
||||
size_t idx;
|
||||
};
|
||||
|
||||
template<typename _Tp, int chs> inline
|
||||
NAryMatIterator<_Tp, chs>::NAryMatIterator()
|
||||
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
NAryMatIterator<_Tp, chs>::NAryMatIterator(const Mat_<_Tp, chs>** _arrays, Mat_<_Tp, chs>* _planes, int _narrays)
|
||||
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
|
||||
{
|
||||
init(_arrays, _planes, 0, _narrays);
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
NAryMatIterator<_Tp, chs>::NAryMatIterator(const Mat_<_Tp, chs>** _arrays, uchar** _ptrs, int _narrays)
|
||||
: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0)
|
||||
{
|
||||
init(_arrays, 0, _ptrs, _narrays);
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
void NAryMatIterator<_Tp, chs>::init(const Mat_<_Tp, chs>** _arrays, Mat_<_Tp, chs>* _planes, uchar** _ptrs, int _narrays)
|
||||
{
|
||||
fprintf(stderr, "NAryMatIterator no impl\n");
|
||||
FBC_Error("null"); // TODO
|
||||
/*FBC_Assert(_arrays && (_ptrs || _planes));
|
||||
int i, j, d1 = 0, i0 = -1, d = -1;
|
||||
|
||||
arrays = _arrays;
|
||||
ptrs = _ptrs;
|
||||
planes = _planes;
|
||||
narrays = _narrays;
|
||||
nplanes = 0;
|
||||
size = 0;
|
||||
|
||||
if (narrays < 0) {
|
||||
for (i = 0; _arrays[i] != 0; i++)
|
||||
;
|
||||
narrays = i;
|
||||
FBC_Assert(narrays <= 1000);
|
||||
}
|
||||
|
||||
iterdepth = 0;
|
||||
|
||||
for (i = 0; i < narrays; i++) {
|
||||
FBC_Assert(arrays[i] != 0);
|
||||
const Mat_<_Tp, chs>& A = *arrays[i];
|
||||
if (ptrs)
|
||||
ptrs[i] = A.data;
|
||||
|
||||
if (!A.data)
|
||||
continue;
|
||||
|
||||
if (i0 < 0) {
|
||||
i0 = i;
|
||||
d = 2; // A.dims;
|
||||
|
||||
// find the first dimensionality which is different from 1;
|
||||
// in any of the arrays the first "d1" step do not affect the continuity
|
||||
for (d1 = 0; d1 < d; d1++)
|
||||
if (A.size[d1] > 1)
|
||||
break;
|
||||
} else {
|
||||
FBC_Assert(A.size == arrays[i0]->size);
|
||||
}
|
||||
|
||||
if (!A.isContinuous()) {
|
||||
FBC_Assert(A.step[d - 1] == A.elemSize());
|
||||
for (j = d - 1; j > d1; j--)
|
||||
if (A.step[j] * A.size[j] < A.step[j - 1])
|
||||
break;
|
||||
iterdepth = std::max(iterdepth, j);
|
||||
}
|
||||
}
|
||||
|
||||
if (i0 >= 0) {
|
||||
size = arrays[i0]->size[d - 1];
|
||||
for (j = d - 1; j > iterdepth; j--) {
|
||||
int64 total1 = (int64)size*arrays[i0]->size[j - 1];
|
||||
if (total1 != (int)total1)
|
||||
break;
|
||||
size = (int)total1;
|
||||
}
|
||||
|
||||
iterdepth = j;
|
||||
if (iterdepth == d1)
|
||||
iterdepth = 0;
|
||||
|
||||
nplanes = 1;
|
||||
for (j = iterdepth - 1; j >= 0; j--)
|
||||
nplanes *= arrays[i0]->size[j];
|
||||
} else {
|
||||
iterdepth = 0;
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
|
||||
if (!planes)
|
||||
return;
|
||||
|
||||
for (i = 0; i < narrays; i++) {
|
||||
FBC_Assert(arrays[i] != 0);
|
||||
const Mat_<_Tp, chs>& A = *arrays[i];
|
||||
|
||||
if (!A.data) {
|
||||
planes[i] = Mat_<_Tp, chs>();
|
||||
continue;
|
||||
}
|
||||
|
||||
planes[i] = Mat_<_Tp, chs>(1, (int)size, A.data);
|
||||
}*/
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
NAryMatIterator<_Tp, chs>& NAryMatIterator<_Tp, chs>::operator ++()
|
||||
{
|
||||
fprintf(stderr, "NAryMatIterator no impl\n");
|
||||
/*if (idx >= nplanes - 1)
|
||||
return *this;
|
||||
++idx;
|
||||
|
||||
if (iterdepth == 1) {
|
||||
if (ptrs) {
|
||||
for (int i = 0; i < narrays; i++) {
|
||||
if (!ptrs[i])
|
||||
continue;
|
||||
ptrs[i] = arrays[i]->data + arrays[i]->step[0] * idx;
|
||||
}
|
||||
}
|
||||
if (planes) {
|
||||
for (int i = 0; i < narrays; i++) {
|
||||
if (!planes[i].data)
|
||||
continue;
|
||||
planes[i].data = arrays[i]->data + arrays[i]->step[0] * idx;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < narrays; i++) {
|
||||
const Mat_<_Tp, chs>& A = *arrays[i];
|
||||
if (!A.data)
|
||||
continue;
|
||||
int _idx = (int)idx;
|
||||
uchar* data = A.data;
|
||||
for (int j = iterdepth - 1; j >= 0 && _idx > 0; j--) {
|
||||
int szi = A.size[j], t = _idx / szi;
|
||||
data += (_idx - t * szi)*A.step[j];
|
||||
_idx = t;
|
||||
}
|
||||
if (ptrs)
|
||||
ptrs[i] = data;
|
||||
if (planes)
|
||||
planes[i].data = data;
|
||||
}
|
||||
}*/
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
NAryMatIterator<_Tp, chs> NAryMatIterator<_Tp, chs>::operator ++(int)
|
||||
{
|
||||
NAryMatIterator<_Tp, chs> it = *this;
|
||||
++*this;
|
||||
return it;
|
||||
}
|
||||
|
||||
} // namespace yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_NARY_MAT_ITERATOR_HPP_
|
||||
@@ -0,0 +1,285 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_BASE_HPP_
|
||||
#define FBC_CV_CORE_BASE_HPP_
|
||||
|
||||
// reference: include/opencv2/core/base.hpp
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error base.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "fbcdef.hpp"
|
||||
#include "interface.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
#define FBC_StaticAssert(condition, reason) static_assert((condition), reason " " #condition)
|
||||
#define FBC_Assert(expr) assert(expr)
|
||||
#define FBC_Error(msg) \
|
||||
fprintf(stderr, "Error: "#msg", file: %s, func: %s, line: %d \n", __FILE__, __FUNCTION__, __LINE__); \
|
||||
assert(0);
|
||||
|
||||
template<typename _Tp, typename _AccTp> static inline
|
||||
_AccTp normL2Sqr(const _Tp* a, int n)
|
||||
{
|
||||
_AccTp s = 0;
|
||||
int i = 0;
|
||||
|
||||
for (; i <= n - 4; i += 4) {
|
||||
_AccTp v0 = a[i], v1 = a[i + 1], v2 = a[i + 2], v3 = a[i + 3];
|
||||
s += v0*v0 + v1*v1 + v2*v2 + v3*v3;
|
||||
}
|
||||
|
||||
for (; i < n; i++) {
|
||||
_AccTp v = a[i];
|
||||
s += v*v;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _AccTp> static inline
|
||||
_AccTp normL1(const _Tp* a, int n)
|
||||
{
|
||||
_AccTp s = 0;
|
||||
int i = 0;
|
||||
|
||||
for (; i <= n - 4; i += 4) {
|
||||
s += (_AccTp)cv_abs(a[i]) + (_AccTp)cv_abs(a[i + 1]) +
|
||||
(_AccTp)cv_abs(a[i + 2]) + (_AccTp)cv_abs(a[i + 3]);
|
||||
}
|
||||
|
||||
for (; i < n; i++)
|
||||
s += cv_abs(a[i]);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _AccTp> static inline
|
||||
_AccTp normInf(const _Tp* a, int n)
|
||||
{
|
||||
_AccTp s = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
s = std::max(s, (_AccTp)cv_abs(a[i]));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _AccTp> static inline
|
||||
_AccTp normL2Sqr(const _Tp* a, const _Tp* b, int n)
|
||||
{
|
||||
_AccTp s = 0;
|
||||
int i = 0;
|
||||
|
||||
for (; i <= n - 4; i += 4) {
|
||||
_AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i + 1] - b[i + 1]), v2 = _AccTp(a[i + 2] - b[i + 2]), v3 = _AccTp(a[i + 3] - b[i + 3]);
|
||||
s += v0*v0 + v1*v1 + v2*v2 + v3*v3;
|
||||
}
|
||||
|
||||
for (; i < n; i++) {
|
||||
_AccTp v = _AccTp(a[i] - b[i]);
|
||||
s += v*v;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline float normL2Sqr(const float* a, const float* b, int n)
|
||||
{
|
||||
float s = 0.f;
|
||||
for (int i = 0; i < n; i++) {
|
||||
float v = a[i] - b[i];
|
||||
s += v*v;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _AccTp> static inline
|
||||
_AccTp normL1(const _Tp* a, const _Tp* b, int n)
|
||||
{
|
||||
_AccTp s = 0;
|
||||
int i = 0;
|
||||
|
||||
for (; i <= n - 4; i += 4) {
|
||||
_AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i + 1] - b[i + 1]), v2 = _AccTp(a[i + 2] - b[i + 2]), v3 = _AccTp(a[i + 3] - b[i + 3]);
|
||||
s += std::abs(v0) + std::abs(v1) + std::abs(v2) + std::abs(v3);
|
||||
}
|
||||
|
||||
for (; i < n; i++) {
|
||||
_AccTp v = _AccTp(a[i] - b[i]);
|
||||
s += std::abs(v);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
inline float normL1(const float* a, const float* b, int n)
|
||||
{
|
||||
float s = 0.f;
|
||||
for (int i = 0; i < n; i++) {
|
||||
s += std::abs(a[i] - b[i]);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
inline int normL1(const uchar* a, const uchar* b, int n)
|
||||
{
|
||||
int s = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
s += std::abs(a[i] - b[i]);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _AccTp> static inline
|
||||
_AccTp normInf(const _Tp* a, const _Tp* b, int n)
|
||||
{
|
||||
_AccTp s = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
_AccTp v0 = a[i] - b[i];
|
||||
s = std::max(s, std::abs(v0));
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//! comparison types
|
||||
enum CmpTypes {
|
||||
CMP_EQ = 0, //!< src1 is equal to src2.
|
||||
CMP_GT = 1, //!< src1 is greater than src2.
|
||||
CMP_GE = 2, //!< src1 is greater than or equal to src2.
|
||||
CMP_LT = 3, //!< src1 is less than src2.
|
||||
CMP_LE = 4, //!< src1 is less than or equal to src2.
|
||||
CMP_NE = 5 //!< src1 is unequal to src2.
|
||||
};
|
||||
|
||||
//! matrix decomposition types
|
||||
enum DecompTypes {
|
||||
/** Gaussian elimination with the optimal pivot element chosen. */
|
||||
DECOMP_LU = 0,
|
||||
/** singular value decomposition (SVD) method; the system can be over-defined and/or the matrix
|
||||
src1 can be singular */
|
||||
DECOMP_SVD = 1,
|
||||
/** eigenvalue decomposition; the matrix src1 must be symmetrical */
|
||||
DECOMP_EIG = 2,
|
||||
/** Cholesky \f$LL^T\f$ factorization; the matrix src1 must be symmetrical and positively
|
||||
defined */
|
||||
DECOMP_CHOLESKY = 3,
|
||||
/** QR factorization; the system can be over-defined and/or the matrix src1 can be singular */
|
||||
DECOMP_QR = 4,
|
||||
/** while all the previous flags are mutually exclusive, this flag can be used together with
|
||||
any of the previous; it means that the normal equations
|
||||
\f$\texttt{src1}^T\cdot\texttt{src1}\cdot\texttt{dst}=\texttt{src1}^T\texttt{src2}\f$ are
|
||||
solved instead of the original system
|
||||
\f$\texttt{src1}\cdot\texttt{dst}=\texttt{src2}\f$ */
|
||||
DECOMP_NORMAL = 16
|
||||
};
|
||||
|
||||
/** norm types
|
||||
- For one array:
|
||||
\f[norm = \forkthree{\|\texttt{src1}\|_{L_{\infty}} = \max _I | \texttt{src1} (I)|}{if \(\texttt{normType} = \texttt{NORM_INF}\) }
|
||||
{ \| \texttt{src1} \| _{L_1} = \sum _I | \texttt{src1} (I)|}{if \(\texttt{normType} = \texttt{NORM_L1}\) }
|
||||
{ \| \texttt{src1} \| _{L_2} = \sqrt{\sum_I \texttt{src1}(I)^2} }{if \(\texttt{normType} = \texttt{NORM_L2}\) }\f]
|
||||
|
||||
- Absolute norm for two arrays
|
||||
\f[norm = \forkthree{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} = \max _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if \(\texttt{normType} = \texttt{NORM_INF}\) }
|
||||
{ \| \texttt{src1} - \texttt{src2} \| _{L_1} = \sum _I | \texttt{src1} (I) - \texttt{src2} (I)|}{if \(\texttt{normType} = \texttt{NORM_L1}\) }
|
||||
{ \| \texttt{src1} - \texttt{src2} \| _{L_2} = \sqrt{\sum_I (\texttt{src1}(I) - \texttt{src2}(I))^2} }{if \(\texttt{normType} = \texttt{NORM_L2}\) }\f]
|
||||
|
||||
- Relative norm for two arrays
|
||||
\f[norm = \forkthree{\frac{\|\texttt{src1}-\texttt{src2}\|_{L_{\infty}} }{\|\texttt{src2}\|_{L_{\infty}} }}{if \(\texttt{normType} = \texttt{NORM_RELATIVE_INF}\) }
|
||||
{ \frac{\|\texttt{src1}-\texttt{src2}\|_{L_1} }{\|\texttt{src2}\|_{L_1}} }{if \(\texttt{normType} = \texttt{NORM_RELATIVE_L1}\) }
|
||||
{ \frac{\|\texttt{src1}-\texttt{src2}\|_{L_2} }{\|\texttt{src2}\|_{L_2}} }{if \(\texttt{normType} = \texttt{NORM_RELATIVE_L2}\) }\f]
|
||||
|
||||
As example for one array consider the function \f$r(x)= \begin{pmatrix} x \\ 1-x \end{pmatrix}, x \in [-1;1]\f$.
|
||||
The \f$ L_{1}, L_{2} \f$ and \f$ L_{\infty} \f$ norm for the sample value \f$r(-1) = \begin{pmatrix} -1 \\ 2 \end{pmatrix}\f$
|
||||
is calculated as follows
|
||||
\f{align*}
|
||||
\| r(-1) \|_{L_1} &= |-1| + |2| = 3 \\
|
||||
\| r(-1) \|_{L_2} &= \sqrt{(-1)^{2} + (2)^{2}} = \sqrt{5} \\
|
||||
\| r(-1) \|_{L_\infty} &= \max(|-1|,|2|) = 2
|
||||
\f}
|
||||
and for \f$r(0.5) = \begin{pmatrix} 0.5 \\ 0.5 \end{pmatrix}\f$ the calculation is
|
||||
\f{align*}
|
||||
\| r(0.5) \|_{L_1} &= |0.5| + |0.5| = 1 \\
|
||||
\| r(0.5) \|_{L_2} &= \sqrt{(0.5)^{2} + (0.5)^{2}} = \sqrt{0.5} \\
|
||||
\| r(0.5) \|_{L_\infty} &= \max(|0.5|,|0.5|) = 0.5.
|
||||
\f}
|
||||
The following graphic shows all values for the three norm functions \f$\| r(x) \|_{L_1}, \| r(x) \|_{L_2}\f$ and \f$\| r(x) \|_{L_\infty}\f$.
|
||||
It is notable that the \f$ L_{1} \f$ norm forms the upper and the \f$ L_{\infty} \f$ norm forms the lower border for the example function \f$ r(x) \f$.
|
||||

|
||||
*/
|
||||
enum NormTypes {
|
||||
NORM_INF = 1,
|
||||
NORM_L1 = 2,
|
||||
NORM_L2 = 4,
|
||||
NORM_L2SQR = 5,
|
||||
NORM_HAMMING = 6,
|
||||
NORM_HAMMING2 = 7,
|
||||
NORM_TYPE_MASK = 7,
|
||||
NORM_RELATIVE = 8, // flag
|
||||
NORM_MINMAX = 32 // flag
|
||||
};
|
||||
|
||||
//! Various border types, image boundaries are denoted with `|`
|
||||
enum BorderTypes {
|
||||
BORDER_CONSTANT = 0, //!< `iiiiii|abcdefgh|iiiiiii` with some specified `i`
|
||||
BORDER_REPLICATE = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`
|
||||
BORDER_REFLECT = 2, //!< `fedcba|abcdefgh|hgfedcb`
|
||||
BORDER_WRAP = 3, //!< `cdefgh|abcdefgh|abcdefg`
|
||||
BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
|
||||
BORDER_TRANSPARENT = 5, //!< `uvwxyz|absdefgh|ijklmno`
|
||||
|
||||
BORDER_REFLECT101 = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
|
||||
BORDER_DEFAULT = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
|
||||
BORDER_ISOLATED = 16 //!< do not look outside of ROI
|
||||
};
|
||||
|
||||
enum DftFlags {
|
||||
/** performs an inverse 1D or 2D transform instead of the default forward transform. */
|
||||
DFT_INVERSE = 1,
|
||||
/** scales the result: divide it by the number of array elements. Normally, it is
|
||||
combined with DFT_INVERSE. */
|
||||
DFT_SCALE = 2,
|
||||
/** performs a forward or inverse transform of every individual row of the input
|
||||
matrix; this flag enables you to transform multiple vectors simultaneously and can be used to
|
||||
decrease the overhead (which is sometimes several times larger than the processing itself) to
|
||||
perform 3D and higher-dimensional transformations and so forth.*/
|
||||
DFT_ROWS = 4,
|
||||
/** performs a forward transformation of 1D or 2D real array; the result,
|
||||
though being a complex array, has complex-conjugate symmetry (*CCS*, see the function
|
||||
description below for details), and such an array can be packed into a real array of the same
|
||||
size as input, which is the fastest option and which is what the function does by default;
|
||||
however, you may wish to get a full complex array (for simpler spectrum analysis, and so on) -
|
||||
pass the flag to enable the function to produce a full-size complex output array. */
|
||||
DFT_COMPLEX_OUTPUT = 16,
|
||||
/** performs an inverse transformation of a 1D or 2D complex array; the
|
||||
result is normally a complex array of the same size, however, if the input array has
|
||||
conjugate-complex symmetry (for example, it is a result of forward transformation with
|
||||
DFT_COMPLEX_OUTPUT flag), the output is a real array; while the function itself does not
|
||||
check whether the input is symmetrical or not, you can pass the flag and then the function
|
||||
will assume the symmetry and produce the real output array (note that when the input is packed
|
||||
into a real array and inverse transformation is executed, the function treats the input as a
|
||||
packed complex-conjugate symmetrical array, and the output will also be a real array). */
|
||||
DFT_REAL_OUTPUT = 32,
|
||||
/** performs an inverse 1D or 2D transform instead of the default forward transform. */
|
||||
DCT_INVERSE = DFT_INVERSE,
|
||||
/** performs a forward or inverse transform of every individual row of the input
|
||||
matrix. This flag enables you to transform multiple vectors simultaneously and can be used to
|
||||
decrease the overhead (which is sometimes several times larger than the processing itself) to
|
||||
perform 3D and higher-dimensional transforms and so forth.*/
|
||||
DCT_ROWS = DFT_ROWS
|
||||
};
|
||||
|
||||
} //yt_tinycv
|
||||
|
||||
#endif //FBC_CV_CORE_BASE_HPP_
|
||||
@@ -0,0 +1,313 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_CORE_HPP_
|
||||
#define FBC_CV_CORE_CORE_HPP_
|
||||
|
||||
/* reference: include/opencv2/core/core_c.h
|
||||
include/opencv2/core.hpp
|
||||
modules/core/src/stat.cpp
|
||||
modules/core/include/opencv2/core/private.hpp
|
||||
modules/core/src/matrix.cpp
|
||||
modules/core/src/arithm.cpp
|
||||
*/
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error core.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include "fbcdef.hpp"
|
||||
#include "mat.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
// NormFlags
|
||||
#define FBC_C 1
|
||||
#define FBC_L1 2
|
||||
#define FBC_L2 4
|
||||
#define FBC_NORM_MASK 7
|
||||
#define FBC_RELATIVE 8
|
||||
#define FBC_DIFF 16
|
||||
#define FBC_MINMAX 32
|
||||
|
||||
#define FBC_DIFF_C (FBC_DIFF | FBC_C)
|
||||
#define FBC_DIFF_L1 (FBC_DIFF | FBC_L1)
|
||||
#define FBC_DIFF_L2 (FBC_DIFF | FBC_L2)
|
||||
#define FBC_RELATIVE_C (FBC_RELATIVE | FBC_C)
|
||||
#define FBC_RELATIVE_L1 (FBC_RELATIVE | FBC_L1)
|
||||
#define FBC_RELATIVE_L2 (FBC_RELATIVE | FBC_L2)
|
||||
|
||||
// Discrete Linear Transforms and Related Functions
|
||||
#define FBC_DXT_SCALE 2 // divide result by size of array
|
||||
|
||||
// Fast cubic root calculation
|
||||
FBC_EXPORTS float fbcCbrt(float value);
|
||||
|
||||
template<typename dump>
|
||||
static inline void* fbcAlignPtr(const void* ptr, int align = 32)
|
||||
{
|
||||
FBC_Assert((align & (align - 1)) == 0);
|
||||
return (void*)(((size_t)ptr + align - 1) & ~(size_t)(align - 1));
|
||||
}
|
||||
|
||||
template<typename dump>
|
||||
static inline int fbcAlign(int size, int align)
|
||||
{
|
||||
FBC_Assert((align & (align - 1)) == 0 && size < INT_MAX);
|
||||
return (size + align - 1) & -align;
|
||||
}
|
||||
|
||||
// Computes the source location of an extrapolated pixel
|
||||
/* Various border types, image boundaries are denoted with '|'
|
||||
|
||||
* BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
|
||||
* BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
|
||||
* BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
|
||||
* BORDER_WRAP: cdefgh|abcdefgh|abcdefg
|
||||
* BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i'
|
||||
*/
|
||||
template<typename _Tp>
|
||||
int borderInterpolate(int p, int len, int borderType)
|
||||
{
|
||||
if ((unsigned)p < (unsigned)len) {
|
||||
;
|
||||
} else if (borderType == BORDER_REPLICATE) {
|
||||
p = p < 0 ? 0 : len - 1;
|
||||
} else if (borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101) {
|
||||
int delta = borderType == BORDER_REFLECT_101;
|
||||
if (len == 1)
|
||||
return 0;
|
||||
do {
|
||||
if (p < 0)
|
||||
p = -p - 1 + delta;
|
||||
else
|
||||
p = len - 1 - (p - len) - delta;
|
||||
} while ((unsigned)p >= (unsigned)len);
|
||||
} else if (borderType == BORDER_WRAP) {
|
||||
FBC_Assert(len > 0);
|
||||
if (p < 0)
|
||||
p -= ((p - len + 1) / len)*len;
|
||||
if (p >= len)
|
||||
p %= len;
|
||||
} else if (borderType == BORDER_CONSTANT) {
|
||||
p = -1;
|
||||
} else {
|
||||
FBC_Error("Unknown/unsupported border type");
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// Transposes a matrix
|
||||
// \f[\texttt{dst} (i,j) = \texttt{src} (j,i)\f]
|
||||
template<typename _Tp, int chs>
|
||||
int transpose(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)
|
||||
{
|
||||
if (src.empty()) {
|
||||
dst.release();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// handle the case of single-column/single-row matrices, stored in STL vectors
|
||||
if (src.rows != dst.cols || src.cols != dst.rows) {
|
||||
FBC_Assert(src.size() == dst.size() && (src.cols == 1 || src.rows == 1));
|
||||
src.copyTo(dst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dst.data == src.data) {
|
||||
FBC_Assert(0); // TODO
|
||||
} else {
|
||||
Size sz = src.size();
|
||||
int i = 0, j, m = sz.width, n = sz.height;
|
||||
int sstep = src.step;
|
||||
int dstep = dst.step;
|
||||
|
||||
for (; i <= m - 4; i += 4) {
|
||||
_Tp* d0 = (_Tp*)(dst.data + dstep*i);
|
||||
_Tp* d1 = (_Tp*)(dst.data + dstep*(i + 1));
|
||||
_Tp* d2 = (_Tp*)(dst.data + dstep*(i + 2));
|
||||
_Tp* d3 = (_Tp*)(dst.data + dstep*(i + 3));
|
||||
|
||||
for (j = 0; j <= n - 4; j += 4) {
|
||||
const _Tp* s0 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*j);
|
||||
const _Tp* s1 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*(j + 1));
|
||||
const _Tp* s2 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*(j + 2));
|
||||
const _Tp* s3 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*(j + 3));
|
||||
|
||||
d0[j] = s0[0]; d0[j + 1] = s1[0]; d0[j + 2] = s2[0]; d0[j + 3] = s3[0];
|
||||
d1[j] = s0[1]; d1[j + 1] = s1[1]; d1[j + 2] = s2[1]; d1[j + 3] = s3[1];
|
||||
d2[j] = s0[2]; d2[j + 1] = s1[2]; d2[j + 2] = s2[2]; d2[j + 3] = s3[2];
|
||||
d3[j] = s0[3]; d3[j + 1] = s1[3]; d3[j + 2] = s2[3]; d3[j + 3] = s3[3];
|
||||
}
|
||||
|
||||
for (; j < n; j++) {
|
||||
const _Tp* s0 = (const _Tp*)(src.data + i*sizeof(_Tp) + j*sstep);
|
||||
d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < m; i++) {
|
||||
_Tp* d0 = (_Tp*)(dst.data + dstep*i);
|
||||
j = 0;
|
||||
|
||||
for (; j <= n - 4; j += 4) {
|
||||
const _Tp* s0 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*j);
|
||||
const _Tp* s1 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*(j + 1));
|
||||
const _Tp* s2 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*(j + 2));
|
||||
const _Tp* s3 = (const _Tp*)(src.data + i*sizeof(_Tp) + sstep*(j + 3));
|
||||
|
||||
d0[j] = s0[0]; d0[j + 1] = s1[0]; d0[j + 2] = s2[0]; d0[j + 3] = s3[0];
|
||||
}
|
||||
|
||||
for (; j < n; j++) {
|
||||
const _Tp* s0 = (const _Tp*)(src.data + i*sizeof(_Tp) + j*sstep);
|
||||
d0[j] = s0[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Counts non-zero array elements
|
||||
// \f[\sum _{ I: \; \texttt{ src } (I) \ne0 } 1\f]
|
||||
template<typename _Tp, int chs>
|
||||
int countNonZero(const Mat_<_Tp, chs>& src)
|
||||
{
|
||||
FBC_Assert(chs == 1);
|
||||
|
||||
int len = src.rows * src.cols;
|
||||
const _Tp* p = (_Tp*)src.data;
|
||||
|
||||
int nz = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
nz += (p[i] != 0);
|
||||
}
|
||||
|
||||
return nz;
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
void scalarToRawData(const yt_tinycv::Scalar& s, void* _buf, int unroll_to = 0)
|
||||
{
|
||||
FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float
|
||||
|
||||
int i, cn = chs;
|
||||
FBC_Assert(chs <= 4);
|
||||
int depth = sizeof(_Tp);
|
||||
switch (depth) {
|
||||
case 1: {
|
||||
uchar* buf = (uchar*)_buf;
|
||||
for (i = 0; i < cn; i++)
|
||||
buf[i] = saturate_cast<uchar>(s.val[i]);
|
||||
for (; i < unroll_to; i++)
|
||||
buf[i] = buf[i - cn];
|
||||
}
|
||||
break;
|
||||
case 4: {
|
||||
float* buf = (float*)_buf;
|
||||
for (i = 0; i < cn; i++)
|
||||
buf[i] = saturate_cast<float>(s.val[i]);
|
||||
for (; i < unroll_to; i++)
|
||||
buf[i] = buf[i - cn];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FBC_Error("UnsupportedFormat");
|
||||
}
|
||||
}
|
||||
|
||||
// calculates the per - element bit - wise logical conjunction
|
||||
// \f[\texttt{dst} (I) = \texttt{src1} (I) \wedge \texttt{src2} (I) \quad \texttt{if mask} (I) \ne0\f]
|
||||
// mask optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed
|
||||
template<typename _Tp, int chs>
|
||||
int bitwise_and(const Mat_<_Tp, chs>& src1, const Mat_<_Tp, chs>& src2, Mat_<_Tp, chs>& dst, const Mat_<uchar, 1>& mask = Mat_<uchar, 1>())
|
||||
{
|
||||
FBC_Assert(src1.rows == src2.rows && src1.cols == src2.cols);
|
||||
if (dst.empty()) {
|
||||
dst = Mat_<_Tp, chs>(src1.rows, src1.cols);
|
||||
} else {
|
||||
FBC_Assert(src1.rows == dst.rows && src1.cols == dst.cols);
|
||||
}
|
||||
|
||||
if (!mask.empty()) {
|
||||
FBC_Assert(src1.rows == mask.rows && src1.cols == mask.cols);
|
||||
}
|
||||
|
||||
int bytePerRow = src1.cols * chs * sizeof(_Tp);
|
||||
int bypePerPixel = chs * sizeof(_Tp);
|
||||
for (int y = 0; y < src1.rows; y++) {
|
||||
const uchar* pSrc1 = src1.ptr(y);
|
||||
const uchar* pSrc2 = src2.ptr(y);
|
||||
uchar* pDst = dst.ptr(y);
|
||||
const uchar* pMask = NULL;
|
||||
if (!mask.empty()) {
|
||||
pMask = mask.ptr(y);
|
||||
|
||||
for (int x = 0; x < src1.cols; x++) {
|
||||
if (pMask[x] == 1) {
|
||||
int addr = x * bypePerPixel;
|
||||
for (int t = 0; t < bypePerPixel; t++) {
|
||||
pDst[addr + t] = pSrc1[addr + t] & pSrc2[addr + t];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < bytePerRow; x++) {
|
||||
pDst[x] = pSrc1[x] & pSrc2[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Inverts every bit of an array
|
||||
// \f[\texttt{dst} (I) = \neg \texttt{src} (I)\f]
|
||||
// mask optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed
|
||||
template<typename _Tp, int chs>
|
||||
int bitwise_not(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, const Mat_<uchar, 1>& mask = Mat_<uchar, 1>())
|
||||
{
|
||||
if (dst.empty()) {
|
||||
dst = Mat_<_Tp, chs>(src.rows, src.cols);
|
||||
} else {
|
||||
FBC_Assert(src.rows == dst.rows && src.cols == dst.cols);
|
||||
}
|
||||
|
||||
if (!mask.empty()) {
|
||||
FBC_Assert(src.rows == mask.rows && src.cols == mask.cols);
|
||||
}
|
||||
|
||||
int bytePerRow = src.cols * chs * sizeof(_Tp);
|
||||
int bypePerPixel = chs * sizeof(_Tp);
|
||||
for (int y = 0; y < src.rows; y++) {
|
||||
const uchar* pSrc = src.ptr(y);
|
||||
uchar* pDst = dst.ptr(y);
|
||||
const uchar* pMask = NULL;
|
||||
if (!mask.empty()) {
|
||||
pMask = mask.ptr(y);
|
||||
|
||||
for (int x = 0; x < src.cols; x++) {
|
||||
if (pMask[x] == 1) {
|
||||
int addr = x * bypePerPixel;
|
||||
for (int t = 0; t < bypePerPixel; t++) {
|
||||
pDst[addr + t] = ~pSrc[addr + t];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < bytePerRow; x++) {
|
||||
pDst[x] = ~pSrc[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_CORE_HPP_
|
||||
@@ -0,0 +1,543 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
// from: https://github.com/fengbingchun/OpenCV_Test/blob/master/src/fbc_cv/include/cvtColor.hpp
|
||||
// commitID: 7c0eccf85e31c456256cc4c87d4ba752a56a18dc
|
||||
#ifndef FBC_CV_CVTCOLOR_HPP_
|
||||
#define FBC_CV_CVTCOLOR_HPP_
|
||||
|
||||
/* reference: include/opencv2/imgproc.hpp
|
||||
imgproc/src/color.cpp
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
#include "mat.hpp"
|
||||
#include "saturate.hpp"
|
||||
#include "imgproc.hpp"
|
||||
#include "core.hpp"
|
||||
#ifdef __ARM_NEON__
|
||||
#include "arm_neon.h"
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
namespace yt_tinycv {
|
||||
#define FBC_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n))
|
||||
|
||||
#ifdef __ARM_NEON__
|
||||
// neon intrinsic
|
||||
static void NeonCvtColorRGBA2BGR(unsigned char *rgba, unsigned char *bgr, int rows, int cols) {
|
||||
int len_color = rows * cols;
|
||||
int num8x16 = len_color / 16;
|
||||
int num8len = num8x16 * 16;
|
||||
uint8x16x4_t intlv_rgba;
|
||||
uint8x16x3_t intlv_bgr;
|
||||
for (int i=0; i < num8x16; i++) {
|
||||
intlv_rgba = vld4q_u8(rgba);
|
||||
intlv_bgr.val[0] = intlv_rgba.val[2];
|
||||
intlv_bgr.val[1] = intlv_rgba.val[1];
|
||||
intlv_bgr.val[2] = intlv_rgba.val[0];
|
||||
vst3q_u8(bgr, intlv_bgr);
|
||||
rgba += 64;
|
||||
bgr += 48;
|
||||
}
|
||||
for (; num8len < len_color; num8len++) {
|
||||
bgr[0] = rgba[2];
|
||||
bgr[1] = rgba[1];
|
||||
bgr[2] = rgba[0];
|
||||
rgba += 4;
|
||||
bgr += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void NeonCvtColorRGBA2RGB(unsigned char *rgba, unsigned char *bgr, int rows, int cols) {
|
||||
int len_color = rows * cols;
|
||||
int num8x16 = len_color / 16;
|
||||
int num8len = num8x16 * 16;
|
||||
uint8x16x4_t intlv_rgba;
|
||||
uint8x16x3_t intlv_bgr;
|
||||
for (int i=0; i < num8x16; i++) {
|
||||
intlv_rgba = vld4q_u8(rgba);
|
||||
intlv_bgr.val[0] = intlv_rgba.val[0];
|
||||
intlv_bgr.val[1] = intlv_rgba.val[1];
|
||||
intlv_bgr.val[2] = intlv_rgba.val[2];
|
||||
vst3q_u8(bgr, intlv_bgr);
|
||||
rgba += 64;
|
||||
bgr += 48;
|
||||
}
|
||||
for (; num8len < len_color; num8len++) {
|
||||
bgr[0] = rgba[0];
|
||||
bgr[1] = rgba[1];
|
||||
bgr[2] = rgba[2];
|
||||
rgba += 4;
|
||||
bgr += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void NeonCvtColorRGB2BGR(unsigned char *rgb, unsigned char *bgr, int rows, int cols) {
|
||||
int len_color = rows * cols;
|
||||
int num8x16 = len_color / 16;
|
||||
int num8len = num8x16 * 16;
|
||||
uint8x16x3_t intlv_rgb;
|
||||
uint8x16x3_t intlv_bgr;
|
||||
for (int i=0; i < num8x16; i++) {
|
||||
intlv_rgb = vld3q_u8(rgb);
|
||||
intlv_bgr.val[0] = intlv_rgb.val[2];
|
||||
intlv_bgr.val[1] = intlv_rgb.val[1];
|
||||
intlv_bgr.val[2] = intlv_rgb.val[0];
|
||||
vst3q_u8(bgr, intlv_bgr);
|
||||
rgb += 48;
|
||||
bgr += 48;
|
||||
}
|
||||
for (; num8len < len_color; num8len++) {
|
||||
bgr[0] = rgb[2];
|
||||
bgr[1] = rgb[1];
|
||||
bgr[2] = rgb[0];
|
||||
rgb += 3;
|
||||
bgr += 3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);
|
||||
template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2Gray(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);
|
||||
template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2YCrCb(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i);
|
||||
template<typename _Tp, int chs1, int chs2, int bIdx, int uIdx> static void cvtRGBtoYUV420p(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst);
|
||||
|
||||
#undef R2Y
|
||||
#undef G2Y
|
||||
#undef B2Y
|
||||
|
||||
enum {
|
||||
yuv_shift = 14,
|
||||
xyz_shift = 12,
|
||||
R2Y = 4899,
|
||||
G2Y = 9617,
|
||||
B2Y = 1868,
|
||||
BLOCK_SIZE = 256
|
||||
};
|
||||
|
||||
// Converts an image from one color space to another
|
||||
// support type: uchar/ushort/float
|
||||
template<typename _Tp, int chs1, int chs2>
|
||||
int cvtColor(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int code)
|
||||
{
|
||||
FBC_Assert(src.cols > 0 && src.rows > 0 && dst.cols > 0 && dst.rows > 0);
|
||||
FBC_Assert(src.cols == dst.cols);
|
||||
FBC_Assert(src.data != NULL && dst.data != NULL);
|
||||
FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() ||
|
||||
typeid(ushort).name() == typeid(_Tp).name() ||
|
||||
typeid(float).name() == typeid(_Tp).name());
|
||||
FBC_Assert((sizeof(_Tp) == 1) || sizeof(_Tp) == 2 || sizeof(_Tp) == 4); // uchar || ushort || float
|
||||
|
||||
int scn = src.channels;
|
||||
int dcn = dst.channels; // number of channels in the destination image
|
||||
Size sz = src.size();
|
||||
Size dz = dst.size();
|
||||
int bidx;
|
||||
|
||||
#ifdef __ARM_NEON__
|
||||
if (CV_RGBA2BGR == code || CV_BGRA2RGB == code) {
|
||||
// timeval tv_begin, tv_end;
|
||||
// gettimeofday(&tv_begin, NULL);
|
||||
NeonCvtColorRGBA2BGR(src.data, dst.data, dst.rows, dst.cols);
|
||||
// gettimeofday(&tv_end, NULL);
|
||||
// float elapsed = ((tv_end.tv_sec - tv_begin.tv_sec) * 1000000.0f + tv_end.tv_usec - tv_begin.tv_usec) / 1000.0f;
|
||||
// printf("lgy neon NeonCvtColorRGBA2BGR code : %d, %f ms\n", code, elapsed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CV_RGBA2RGB == code || CV_BGRA2BGR == code) {
|
||||
NeonCvtColorRGBA2RGB(src.data, dst.data, dst.rows, dst.cols);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CV_BGR2RGB == code || CV_RGB2BGR == code) {
|
||||
NeonCvtColorRGB2BGR(src.data, dst.data, dst.rows, dst.cols);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (code) {
|
||||
case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
|
||||
case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA: {
|
||||
FBC_Assert(scn == 3 || scn == 4);
|
||||
dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;
|
||||
FBC_Assert(dst.channels == dcn);
|
||||
bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;
|
||||
|
||||
CvtColorLoop_RGB2RGB(src, dst, bidx); // uchar/ushort/float
|
||||
break;
|
||||
}
|
||||
case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY: {
|
||||
FBC_Assert(scn == 3 || scn == 4);
|
||||
FBC_Assert(dst.channels == 1);
|
||||
bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
|
||||
|
||||
CvtColorLoop_RGB2Gray(src, dst, bidx);
|
||||
break;
|
||||
}
|
||||
case CV_BGR2YUV: case CV_RGB2YUV:{
|
||||
FBC_Assert(scn == 3 || scn == 4);
|
||||
bidx = code == CV_BGR2YUV ? 0 : 2;
|
||||
static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
|
||||
static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };
|
||||
CvtColorLoop_RGB2YCrCb(src, dst, bidx, yuv_f, yuv_i);
|
||||
break;
|
||||
}
|
||||
case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12:
|
||||
case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV: {
|
||||
const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2;
|
||||
const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2;
|
||||
|
||||
FBC_Assert(scn == 3 || scn == 4);
|
||||
FBC_Assert(sizeof(_Tp) == 1);
|
||||
FBC_Assert(dcn == 1);
|
||||
FBC_Assert(sz.width % 2 == 0 && sz.height % 2 == 0);
|
||||
|
||||
//Size dstSz(sz.width, sz.height / 2 * 3);
|
||||
FBC_Assert((dz.width == sz.width) && (sz.height / 2 * 3 == dz.height));
|
||||
|
||||
switch (bIdx + uIdx * 10) {
|
||||
case 10: cvtRGBtoYUV420p<_Tp, chs1, chs2, 0, 1>(src, dst); break;
|
||||
case 12: cvtRGBtoYUV420p<_Tp, chs1, chs2, 2, 1>(src, dst); break;
|
||||
case 20: cvtRGBtoYUV420p<_Tp, chs1, chs2, 0, 2>(src, dst); break;
|
||||
case 22: cvtRGBtoYUV420p<_Tp, chs1, chs2, 2, 2>(src, dst); break;
|
||||
default: FBC_Error("Unknown/unsupported color conversion code"); break;
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FBC_Error("Unknown/unsupported color conversion code");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// computes cubic spline coefficients for a function: (xi=i, yi=f[i]), i=0..n
|
||||
template<typename _Tp> static void splineBuild(const _Tp* f, int n, _Tp* tab)
|
||||
{
|
||||
_Tp cn = 0;
|
||||
int i;
|
||||
tab[0] = tab[1] = (_Tp)0;
|
||||
|
||||
for (i = 1; i < n - 1; i++) {
|
||||
_Tp t = 3 * (f[i + 1] - 2 * f[i] + f[i - 1]);
|
||||
_Tp l = 1 / (4 - tab[(i - 1) * 4]);
|
||||
tab[i * 4] = l; tab[i * 4 + 1] = (t - tab[(i - 1) * 4 + 1])*l;
|
||||
}
|
||||
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
_Tp c = tab[i * 4 + 1] - tab[i * 4] * cn;
|
||||
_Tp b = f[i + 1] - f[i] - (cn + c * 2)*(_Tp)0.3333333333333333;
|
||||
_Tp d = (cn - c)*(_Tp)0.3333333333333333;
|
||||
tab[i * 4] = f[i]; tab[i * 4 + 1] = b;
|
||||
tab[i * 4 + 2] = c; tab[i * 4 + 3] = d;
|
||||
cn = c;
|
||||
}
|
||||
}
|
||||
|
||||
// interpolates value of a function at x, 0 <= x <= n using a cubic spline.
|
||||
template<typename _Tp> static inline _Tp splineInterpolate(_Tp x, const _Tp* tab, int n)
|
||||
{
|
||||
// don't touch this function without urgent need - some versions of gcc fail to inline it correctly
|
||||
int ix = std::min(std::max(int(x), 0), n - 1);
|
||||
x -= ix;
|
||||
tab += ix * 4;
|
||||
return ((tab[3] * x + tab[2])*x + tab[1])*x + tab[0];
|
||||
}
|
||||
|
||||
template<typename _Tp> struct ColorChannel
|
||||
{
|
||||
typedef float worktype_f;
|
||||
static _Tp max() { return std::numeric_limits<_Tp>::max(); }
|
||||
static _Tp half() { return (_Tp)(max() / 2 + 1); }
|
||||
};
|
||||
|
||||
template<> struct ColorChannel<float>
|
||||
{
|
||||
typedef float worktype_f;
|
||||
static float max() { return 1.f; }
|
||||
static float half() { return 0.5f; }
|
||||
};
|
||||
|
||||
template<typename _Tp> struct RGB2Gray
|
||||
{
|
||||
typedef _Tp channel_type;
|
||||
|
||||
RGB2Gray(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
|
||||
{
|
||||
static const float coeffs0[] = { 0.299f, 0.587f, 0.114f };
|
||||
memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3 * sizeof(coeffs[0]));
|
||||
if (blueIdx == 0)
|
||||
std::swap(coeffs[0], coeffs[2]);
|
||||
}
|
||||
|
||||
void operator()(const _Tp* src, _Tp* dst, int n) const
|
||||
{
|
||||
int scn = srccn;
|
||||
float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
|
||||
for (int i = 0; i < n; i++, src += scn)
|
||||
dst[i] = saturate_cast<_Tp>(src[0] * cb + src[1] * cg + src[2] * cr);
|
||||
}
|
||||
int srccn;
|
||||
float coeffs[3];
|
||||
};
|
||||
|
||||
template<> struct RGB2Gray<uchar>
|
||||
{
|
||||
typedef uchar channel_type;
|
||||
|
||||
RGB2Gray(int _srccn, int blueIdx, const int* coeffs) : srccn(_srccn)
|
||||
{
|
||||
const int coeffs0[] = { R2Y, G2Y, B2Y };
|
||||
if (!coeffs) coeffs = coeffs0;
|
||||
|
||||
int b = 0, g = 0, r = (1 << (yuv_shift - 1));
|
||||
int db = coeffs[blueIdx ^ 2], dg = coeffs[1], dr = coeffs[blueIdx];
|
||||
|
||||
for (int i = 0; i < 256; i++, b += db, g += dg, r += dr) {
|
||||
tab[i] = b;
|
||||
tab[i + 256] = g;
|
||||
tab[i + 512] = r;
|
||||
}
|
||||
}
|
||||
void operator()(const uchar* src, uchar* dst, int n) const
|
||||
{
|
||||
int scn = srccn;
|
||||
const int* _tab = tab;
|
||||
for (int i = 0; i < n; i++, src += scn)
|
||||
dst[i] = (uchar)((_tab[src[0]] + _tab[src[1] + 256] + _tab[src[2] + 512]) >> yuv_shift);
|
||||
}
|
||||
int srccn;
|
||||
int tab[256 * 3];
|
||||
};
|
||||
|
||||
template<> struct RGB2Gray<ushort>
|
||||
{
|
||||
typedef ushort channel_type;
|
||||
|
||||
RGB2Gray(int _srccn, int blueIdx, const int* _coeffs) : srccn(_srccn)
|
||||
{
|
||||
static const int coeffs0[] = { R2Y, G2Y, B2Y };
|
||||
memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3 * sizeof(coeffs[0]));
|
||||
if (blueIdx == 0)
|
||||
std::swap(coeffs[0], coeffs[2]);
|
||||
}
|
||||
|
||||
void operator()(const ushort* src, ushort* dst, int n) const
|
||||
{
|
||||
int scn = srccn, cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
|
||||
for (int i = 0; i < n; i++, src += scn)
|
||||
dst[i] = (ushort)FBC_DESCALE((unsigned)(src[0] * cb + src[1] * cg + src[2] * cr), yuv_shift);
|
||||
}
|
||||
int srccn;
|
||||
int coeffs[3];
|
||||
};
|
||||
|
||||
template<typename _Tp> struct RGB2YCrCb_f{
|
||||
typedef _Tp channel_type;
|
||||
RGB2YCrCb_f(int _srccn, int _blueIdx, const float* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)
|
||||
{
|
||||
static const float coeffs0[] = { 0.299f, 0.587f, 0.114f, 0.713f, 0.564f };
|
||||
memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5 * sizeof(coeffs[0]));
|
||||
if (blueIdx == 0) std::swap(coeffs[0], coeffs[2]);
|
||||
}
|
||||
void operator()(const _Tp* src, _Tp* dst, int n) const
|
||||
{
|
||||
int scn = srccn, bidx = blueIdx;
|
||||
const _Tp delta = ColorChannel<_Tp>::half();
|
||||
float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
|
||||
n *= 3;
|
||||
for (int i = 0; i < n; i += 3, src += scn) {
|
||||
_Tp Y = saturate_cast<_Tp>(src[0] * C0 + src[1] * C1 + src[2] * C2);
|
||||
_Tp Cr = saturate_cast<_Tp>((src[bidx ^ 2] - Y)*C3 + delta);
|
||||
_Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta);
|
||||
dst[i] = Y; dst[i + 1] = Cr; dst[i + 2] = Cb;
|
||||
}
|
||||
}
|
||||
int srccn, blueIdx;
|
||||
float coeffs[5];
|
||||
};
|
||||
template<typename _Tp> struct RGB2YCrCb_i{
|
||||
typedef _Tp channel_type;
|
||||
RGB2YCrCb_i(int _srccn, int _blueIdx, const int* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)
|
||||
{
|
||||
static const int coeffs0[] = { R2Y, G2Y, B2Y, 11682, 9241 };
|
||||
memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5 * sizeof(coeffs[0]));
|
||||
if (blueIdx == 0) std::swap(coeffs[0], coeffs[2]);
|
||||
}
|
||||
void operator()(const _Tp* src, _Tp* dst, int n) const
|
||||
{
|
||||
int scn = srccn, bidx = blueIdx;
|
||||
int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
|
||||
int delta = ColorChannel<_Tp>::half()*(1 << yuv_shift);
|
||||
n *= 3;
|
||||
for (int i = 0; i < n; i += 3, src += scn) {
|
||||
int Y = FBC_DESCALE(src[0] * C0 + src[1] * C1 + src[2] * C2, yuv_shift);
|
||||
int Cr = FBC_DESCALE((src[bidx ^ 2] - Y)*C3 + delta, yuv_shift);
|
||||
int Cb = FBC_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift);
|
||||
dst[i] = saturate_cast<_Tp>(Y);
|
||||
dst[i + 1] = saturate_cast<_Tp>(Cr);
|
||||
dst[i + 2] = saturate_cast<_Tp>(Cb);
|
||||
}
|
||||
}
|
||||
int srccn, blueIdx;
|
||||
int coeffs[5];
|
||||
};
|
||||
|
||||
const int ITUR_BT_601_CY = 1220542;
|
||||
const int ITUR_BT_601_CUB = 2116026;
|
||||
const int ITUR_BT_601_CUG = -409993;
|
||||
const int ITUR_BT_601_CVG = -852492;
|
||||
const int ITUR_BT_601_CVR = 1673527;
|
||||
const int ITUR_BT_601_SHIFT = 20;
|
||||
const int ITUR_BT_601_CRY = 269484;
|
||||
const int ITUR_BT_601_CGY = 528482;
|
||||
const int ITUR_BT_601_CBY = 102760;
|
||||
const int ITUR_BT_601_CRU = -155188;
|
||||
const int ITUR_BT_601_CGU = -305135;
|
||||
const int ITUR_BT_601_CBU = 460324;
|
||||
const int ITUR_BT_601_CGV = -385875;
|
||||
const int ITUR_BT_601_CBV = -74448;
|
||||
|
||||
template<typename _Tp, int chs1, int chs2, int bIdx>
|
||||
struct RGB888toYUV420pInvoker{
|
||||
RGB888toYUV420pInvoker(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>* dst, const int uIdx)
|
||||
: src_(src), dst_(dst), uIdx_(uIdx) { }
|
||||
void operator()(const Range& rowRange) const
|
||||
{
|
||||
const int w = src_.cols;
|
||||
const int h = src_.rows;
|
||||
const int cn = src_.channels;
|
||||
for (int i = rowRange.start; i < rowRange.end; i++) {
|
||||
const uchar* row0 = src_.ptr(2 * i);
|
||||
const uchar* row1 = src_.ptr(2 * i + 1);
|
||||
uchar* y = (uchar*)dst_->ptr(2 * i);
|
||||
uchar* u = (uchar*)dst_->ptr(h + i / 2) + (i % 2) * (w / 2);
|
||||
uchar* v = (uchar*)dst_->ptr(h + (i + h / 2) / 2) + ((i + h / 2) % 2) * (w / 2);
|
||||
if (uIdx_ == 2) std::swap(u, v);
|
||||
for (int j = 0, k = 0; j < w * cn; j += 2 * cn, k++) {
|
||||
int r00 = row0[2 - bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j];
|
||||
int r01 = row0[2 - bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j];
|
||||
int r10 = row1[2 - bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j];
|
||||
int r11 = row1[2 - bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j];
|
||||
const int shifted16 = (16 << ITUR_BT_601_SHIFT);
|
||||
const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
|
||||
int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16;
|
||||
int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16;
|
||||
int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16;
|
||||
int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16;
|
||||
y[2 * k + 0] = saturate_cast<uchar>(y00 >> ITUR_BT_601_SHIFT);
|
||||
y[2 * k + 1] = saturate_cast<uchar>(y01 >> ITUR_BT_601_SHIFT);
|
||||
y[2 * k + dst_->step + 0] = saturate_cast<uchar>(y10 >> ITUR_BT_601_SHIFT);
|
||||
y[2 * k + dst_->step + 1] = saturate_cast<uchar>(y11 >> ITUR_BT_601_SHIFT);
|
||||
const int shifted128 = (128 << ITUR_BT_601_SHIFT);
|
||||
int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128;
|
||||
int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128;
|
||||
u[k] = saturate_cast<uchar>(u00 >> ITUR_BT_601_SHIFT);
|
||||
v[k] = saturate_cast<uchar>(v00 >> ITUR_BT_601_SHIFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&);
|
||||
const Mat_<_Tp, chs1>& src_;
|
||||
Mat_<_Tp, chs2>* const dst_;
|
||||
const int uIdx_;
|
||||
};
|
||||
|
||||
|
||||
template<typename _Tp, int chs1, int chs2>
|
||||
static int CvtColorLoop_RGB2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx)
|
||||
{
|
||||
Range range(0, src.rows);
|
||||
|
||||
const uchar* yS_ = src.ptr(range.start);
|
||||
uchar* yD_ = (uchar*)dst.ptr(range.start);
|
||||
int scn = src.channels, dcn = dst.channels;
|
||||
|
||||
for (int h = range.start; h < range.end; ++h, yS_ += src.step, yD_ += dst.step) {
|
||||
int n = src.cols;
|
||||
const _Tp* yS = (const _Tp*)yS_;
|
||||
_Tp* yD = (_Tp*)yD_;
|
||||
|
||||
if (dcn == 3) {
|
||||
n *= 3;
|
||||
for (int i = 0; i < n; i += 3, yS += scn) {
|
||||
_Tp t0 = yS[bidx], t1 = yS[1], t2 = yS[bidx ^ 2];
|
||||
yD[i] = t0; yD[i + 1] = t1; yD[i + 2] = t2;
|
||||
}
|
||||
} else if (scn == 3) {
|
||||
n *= 3;
|
||||
_Tp alpha = ColorChannel<_Tp>::max(); // Note: _Tp = float: alpha = 1.0f
|
||||
for (int i = 0; i < n; i += 3, yD += 4) {
|
||||
_Tp t0 = yS[i], t1 = yS[i + 1], t2 = yS[i + 2];
|
||||
yD[bidx] = t0; yD[1] = t1; yD[bidx ^ 2] = t2; yD[3] = alpha;
|
||||
}
|
||||
} else {
|
||||
n *= 4;
|
||||
for (int i = 0; i < n; i += 4) {
|
||||
_Tp t0 = yS[i], t1 = yS[i + 1], t2 = yS[i + 2], t3 = yS[i + 3];
|
||||
yD[i] = t2; yD[i + 1] = t1; yD[i + 2] = t0; yD[i + 3] = t3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs1, int chs2>
|
||||
static int CvtColorLoop_RGB2Gray(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx)
|
||||
{
|
||||
Range range(0, src.rows);
|
||||
const uchar* yS = src.ptr(range.start);
|
||||
uchar* yD = (uchar*)dst.ptr(range.start);
|
||||
int scn = src.channels, dcn = dst.channels;
|
||||
|
||||
RGB2Gray<_Tp> rgb2gray(scn, bidx, 0);
|
||||
|
||||
for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {
|
||||
rgb2gray((const _Tp*)yS, (_Tp*)yD, src.cols);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs1, int chs2>
|
||||
static int CvtColorLoop_RGB2YCrCb(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i)
|
||||
{
|
||||
Range range(0, src.rows);
|
||||
const uchar* yS = src.ptr(range.start);
|
||||
uchar* yD = (uchar*)dst.ptr(range.start);
|
||||
int scn = src.channels, dcn = dst.channels;
|
||||
if (sizeof(_Tp) == 4) {
|
||||
RGB2YCrCb_f<_Tp> rgb2ycrcb(scn, bidx, coeffs_f);
|
||||
for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {
|
||||
rgb2ycrcb((const _Tp*)yS, (_Tp*)yD, src.cols);
|
||||
}
|
||||
} else {
|
||||
if (sizeof(_Tp) == 1) {
|
||||
RGB2YCrCb_i<uchar> rgb2ycrcb(scn, bidx, coeffs_i);
|
||||
for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {
|
||||
rgb2ycrcb((const uchar*)yS, (uchar*)yD, src.cols);
|
||||
}
|
||||
} else {
|
||||
RGB2YCrCb_i<ushort> rgb2ycrcb(scn, bidx, coeffs_i);
|
||||
for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {
|
||||
rgb2ycrcb((const ushort*)yS, (ushort*)yD, src.cols);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs1, int chs2, int bIdx, int uIdx>
|
||||
static void cvtRGBtoYUV420p(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst)
|
||||
{
|
||||
RGB888toYUV420pInvoker<_Tp, chs1, chs2, bIdx> colorConverter(src, &dst, uIdx);
|
||||
colorConverter(Range(0, src.rows / 2));
|
||||
}
|
||||
|
||||
|
||||
} // namespace yt_tinycv
|
||||
#endif // FBC_CV_CVTCOLOR_HPP_
|
||||
@@ -0,0 +1,75 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_FAST_MATH_HPP_
|
||||
#define FBC_CV_CORE_FAST_MATH_HPP_
|
||||
|
||||
// reference: include/opencv2/core/fast_math.hpp
|
||||
|
||||
#include "fbcdef.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
// Rounds floating-point number to the nearest integer
|
||||
static inline int fbcRound(double value)
|
||||
{
|
||||
// it's ok if round does not comply with IEEE754 standard;
|
||||
// it should allow +/-1 difference when the other functions use round
|
||||
return (int)(value + (value >= 0 ? 0.5 : -0.5));
|
||||
}
|
||||
|
||||
static inline int fbcRound(float value)
|
||||
{
|
||||
// it's ok if round does not comply with IEEE754 standard;
|
||||
// it should allow +/-1 difference when the other functions use round
|
||||
return (int)(value + (value >= 0 ? 0.5f : -0.5f));
|
||||
}
|
||||
|
||||
static inline int fbcRound(int value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// Rounds floating-point number to the nearest integer not larger than the original
|
||||
static inline int fbcFloor(double value)
|
||||
{
|
||||
int i = fbcRound(value);
|
||||
float diff = (float)(value - i);
|
||||
return i - (diff < 0);
|
||||
}
|
||||
|
||||
static inline int fbcFloor(float value)
|
||||
{
|
||||
int i = fbcRound(value);
|
||||
float diff = (float)(value - i);
|
||||
return i - (diff < 0);
|
||||
}
|
||||
|
||||
static inline int fbcFloor(int value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// Rounds floating-point number to the nearest integer not smaller than the original
|
||||
static inline int fbcCeil(double value)
|
||||
{
|
||||
int i = fbcRound(value);
|
||||
float diff = (float)(i - value);
|
||||
return i + (diff < 0);
|
||||
}
|
||||
|
||||
static inline int fbcCeil(float value)
|
||||
{
|
||||
int i = fbcRound(value);
|
||||
float diff = (float)(i - value);
|
||||
return i + (diff < 0);
|
||||
}
|
||||
|
||||
static inline int fbcCeil(int value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
} // yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_FAST_MATH_HPP_
|
||||
@@ -0,0 +1,67 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_FBCDEF_HPP_
|
||||
#define FBC_CV_CORE_FBCDEF_HPP_
|
||||
|
||||
/* reference: include/opencv2/core/cvdef.h
|
||||
include/opencv2/core/typedef_c.h
|
||||
*/
|
||||
|
||||
#include "interface.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FBC_EXPORTS __declspec(dllexport)
|
||||
#define FBC_DECL_ALIGNED(x) __declspec(align(x))
|
||||
#else
|
||||
#define FBC_EXPORTS __attribute__((visibility("default")))
|
||||
#define FBC_DECL_ALIGNED(x) __attribute__((aligned(x)))
|
||||
#endif
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
#define FBC_CN_MAX 512
|
||||
#define FBC_CN_SHIFT 3
|
||||
#define FBC_DEPTH_MAX (1 << FBC_CN_SHIFT)
|
||||
|
||||
#define FBC_MAT_TYPE_MASK (FBC_DEPTH_MAX*FBC_CN_MAX - 1)
|
||||
#define FBC_MAT_TYPE(flags) ((flags) & FBC_MAT_TYPE_MASK)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a) > (b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#define FBC_CN_MAX 512
|
||||
|
||||
// Common macros and inline functions
|
||||
#define FBC_SWAP(a,b,t) ((t) = (a), (a) = (b), (b) = (t))
|
||||
|
||||
/** min & max without jumps */
|
||||
#define FBC_IMIN(a, b) ((a) ^ (((a)^(b)) & (((a) < (b)) - 1)))
|
||||
#define FBC_IMAX(a, b) ((a) ^ (((a)^(b)) & (((a) > (b)) - 1)))
|
||||
|
||||
// fundamental constants
|
||||
#define FBC_PI 3.1415926535897932384626433832795
|
||||
|
||||
// Note: No practical significance
|
||||
class dump {};
|
||||
|
||||
typedef union Cv32suf {
|
||||
int i;
|
||||
unsigned u;
|
||||
float f;
|
||||
} Cv32suf;
|
||||
|
||||
typedef union Cv64suf {
|
||||
int64 i;
|
||||
yt_tinycv::uint64 u;
|
||||
double f;
|
||||
} Cv64suf;
|
||||
|
||||
} // namespace yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_FBCDEF_HPP_
|
||||
@@ -0,0 +1,30 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_FBCSTD_HPP_
|
||||
#define FBC_CV_CORE_FBCSTD_HPP_
|
||||
|
||||
// reference: include/opencv2/core/cvstd.hpp
|
||||
|
||||
#include "fbcdef.hpp"
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error fbcstd.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
/* the alignment of all the allocated buffers */
|
||||
#define FBC_MALLOC_ALIGN 16
|
||||
|
||||
// Allocates an aligned memory buffer
|
||||
FBC_EXPORTS void* fastMalloc(size_t size);
|
||||
// Deallocates a memory buffer
|
||||
FBC_EXPORTS void fastFree(void* ptr);
|
||||
void* cvAlloc(size_t size);
|
||||
void cvFree_(void* ptr);
|
||||
#define cvFree(ptr) (cvFree_(*(ptr)), *(ptr)=0)
|
||||
|
||||
} // namespace yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_FBCSTD_HPP_
|
||||
@@ -0,0 +1,316 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_IMGPROC_HPP_
|
||||
#define FBC_CV_IMGPROC_HPP_
|
||||
|
||||
// reference: include/opencv2/imgproc.hpp
|
||||
|
||||
#include "fbcdef.hpp"
|
||||
#include "interface.hpp"
|
||||
#include "mat.hpp"
|
||||
#include "core.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
// interpolation algorithm
|
||||
enum InterpolationFlags{
|
||||
/** nearest neighbor interpolation */
|
||||
INTER_NEAREST = 0,
|
||||
/** bilinear interpolation */
|
||||
INTER_LINEAR = 1,
|
||||
/** bicubic interpolation */
|
||||
INTER_CUBIC = 2,
|
||||
/** resampling using pixel area relation. It may be a preferred method for image decimation, as
|
||||
it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method. */
|
||||
INTER_AREA = 3,
|
||||
/** Lanczos interpolation over 8x8 neighborhood */
|
||||
INTER_LANCZOS4 = 4,
|
||||
/** mask for interpolation codes */
|
||||
INTER_MAX = 7,
|
||||
/** flag, fills all of the destination image pixels. If some of them correspond to outliers in the
|
||||
source image, they are set to zero */
|
||||
WARP_FILL_OUTLIERS = 8,
|
||||
/** flag, inverse transformation
|
||||
|
||||
For example, polar transforms:
|
||||
- flag is __not__ set: \f$dst( \phi , \rho ) = src(x,y)\f$
|
||||
- flag is set: \f$dst(x,y) = src( \phi , \rho )\f$
|
||||
*/
|
||||
WARP_INVERSE_MAP = 16
|
||||
};
|
||||
|
||||
enum InterpolationMasks {
|
||||
INTER_BITS = 5,
|
||||
INTER_BITS2 = INTER_BITS * 2,
|
||||
INTER_TAB_SIZE = 1 << INTER_BITS,
|
||||
INTER_TAB_SIZE2 = INTER_TAB_SIZE * INTER_TAB_SIZE
|
||||
};
|
||||
|
||||
// Constants for color conversion
|
||||
enum ColorConversionFlags {
|
||||
CV_BGR2BGRA = 0,
|
||||
CV_RGB2RGBA = CV_BGR2BGRA,
|
||||
|
||||
CV_BGRA2BGR = 1,
|
||||
CV_RGBA2RGB = CV_BGRA2BGR,
|
||||
|
||||
CV_BGR2RGBA = 2,
|
||||
CV_RGB2BGRA = CV_BGR2RGBA,
|
||||
|
||||
CV_RGBA2BGR = 3,
|
||||
CV_BGRA2RGB = CV_RGBA2BGR,
|
||||
|
||||
CV_BGR2RGB = 4,
|
||||
CV_RGB2BGR = CV_BGR2RGB,
|
||||
|
||||
CV_BGRA2RGBA = 5,
|
||||
CV_RGBA2BGRA = CV_BGRA2RGBA,
|
||||
|
||||
CV_BGR2GRAY = 6,
|
||||
CV_RGB2GRAY = 7,
|
||||
CV_GRAY2BGR = 8,
|
||||
CV_GRAY2RGB = CV_GRAY2BGR,
|
||||
CV_GRAY2BGRA = 9,
|
||||
CV_GRAY2RGBA = CV_GRAY2BGRA,
|
||||
CV_BGRA2GRAY = 10,
|
||||
CV_RGBA2GRAY = 11,
|
||||
|
||||
// CV_BGR2BGR565 // 12 - 31
|
||||
|
||||
CV_BGR2XYZ = 32,
|
||||
CV_RGB2XYZ = 33,
|
||||
CV_XYZ2BGR = 34,
|
||||
CV_XYZ2RGB = 35,
|
||||
|
||||
CV_BGR2YCrCb = 36,
|
||||
CV_RGB2YCrCb = 37,
|
||||
CV_YCrCb2BGR = 38,
|
||||
CV_YCrCb2RGB = 39,
|
||||
|
||||
CV_BGR2HSV = 40,
|
||||
CV_RGB2HSV = 41,
|
||||
|
||||
CV_BGR2Lab = 44,
|
||||
CV_RGB2Lab = 45,
|
||||
|
||||
// CV_BayerBG2BGR // 46 - 49
|
||||
|
||||
CV_BGR2Luv = 50,
|
||||
CV_RGB2Luv = 51,
|
||||
CV_BGR2HLS = 52,
|
||||
CV_RGB2HLS = 53,
|
||||
|
||||
CV_HSV2BGR = 54,
|
||||
CV_HSV2RGB = 55,
|
||||
|
||||
CV_Lab2BGR = 56,
|
||||
CV_Lab2RGB = 57,
|
||||
CV_Luv2BGR = 58,
|
||||
CV_Luv2RGB = 59,
|
||||
CV_HLS2BGR = 60,
|
||||
CV_HLS2RGB = 61,
|
||||
|
||||
// CV_BayerBG2BGR_VNG // 62 - 65
|
||||
|
||||
CV_BGR2HSV_FULL = 66,
|
||||
CV_RGB2HSV_FULL = 67,
|
||||
CV_BGR2HLS_FULL = 68,
|
||||
CV_RGB2HLS_FULL = 69,
|
||||
|
||||
CV_HSV2BGR_FULL = 70,
|
||||
CV_HSV2RGB_FULL = 71,
|
||||
CV_HLS2BGR_FULL = 72,
|
||||
CV_HLS2RGB_FULL = 73,
|
||||
|
||||
// CV_LBGR2Lab // 74 - 81
|
||||
|
||||
CV_BGR2YUV = 82,
|
||||
CV_RGB2YUV = 83,
|
||||
CV_YUV2BGR = 84,
|
||||
CV_YUV2RGB = 85,
|
||||
|
||||
// CV_BayerBG2GRAY // 86 - 89
|
||||
|
||||
//YUV 4:2:0 formats family
|
||||
CV_YUV2RGB_NV12 = 90,
|
||||
CV_YUV2BGR_NV12 = 91,
|
||||
CV_YUV2RGB_NV21 = 92,
|
||||
CV_YUV2BGR_NV21 = 93,
|
||||
CV_YUV420sp2RGB = CV_YUV2RGB_NV21,
|
||||
CV_YUV420sp2BGR = CV_YUV2BGR_NV21,
|
||||
|
||||
CV_YUV2RGBA_NV12 = 94,
|
||||
CV_YUV2BGRA_NV12 = 95,
|
||||
CV_YUV2RGBA_NV21 = 96,
|
||||
CV_YUV2BGRA_NV21 = 97,
|
||||
CV_YUV420sp2RGBA = CV_YUV2RGBA_NV21,
|
||||
CV_YUV420sp2BGRA = CV_YUV2BGRA_NV21,
|
||||
|
||||
CV_YUV2RGB_YV12 = 98,
|
||||
CV_YUV2BGR_YV12 = 99,
|
||||
CV_YUV2RGB_IYUV = 100,
|
||||
CV_YUV2BGR_IYUV = 101,
|
||||
CV_YUV2RGB_I420 = CV_YUV2RGB_IYUV,
|
||||
CV_YUV2BGR_I420 = CV_YUV2BGR_IYUV,
|
||||
CV_YUV420p2RGB = CV_YUV2RGB_YV12,
|
||||
CV_YUV420p2BGR = CV_YUV2BGR_YV12,
|
||||
|
||||
CV_YUV2RGBA_YV12 = 102,
|
||||
CV_YUV2BGRA_YV12 = 103,
|
||||
CV_YUV2RGBA_IYUV = 104,
|
||||
CV_YUV2BGRA_IYUV = 105,
|
||||
CV_YUV2RGBA_I420 = CV_YUV2RGBA_IYUV,
|
||||
CV_YUV2BGRA_I420 = CV_YUV2BGRA_IYUV,
|
||||
CV_YUV420p2RGBA = CV_YUV2RGBA_YV12,
|
||||
CV_YUV420p2BGRA = CV_YUV2BGRA_YV12,
|
||||
|
||||
CV_YUV2GRAY_420 = 106,
|
||||
CV_YUV2GRAY_NV21 = CV_YUV2GRAY_420,
|
||||
CV_YUV2GRAY_NV12 = CV_YUV2GRAY_420,
|
||||
CV_YUV2GRAY_YV12 = CV_YUV2GRAY_420,
|
||||
CV_YUV2GRAY_IYUV = CV_YUV2GRAY_420,
|
||||
CV_YUV2GRAY_I420 = CV_YUV2GRAY_420,
|
||||
CV_YUV420sp2GRAY = CV_YUV2GRAY_420,
|
||||
CV_YUV420p2GRAY = CV_YUV2GRAY_420,
|
||||
|
||||
// YUV 4:2:2 formats family // 107 - 124
|
||||
|
||||
// alpha premultiplication // 125 - 126
|
||||
|
||||
CV_RGB2YUV_I420 = 127,
|
||||
CV_BGR2YUV_I420 = 128,
|
||||
CV_RGB2YUV_IYUV = CV_RGB2YUV_I420,
|
||||
CV_BGR2YUV_IYUV = CV_BGR2YUV_I420,
|
||||
|
||||
CV_RGBA2YUV_I420 = 129,
|
||||
CV_BGRA2YUV_I420 = 130,
|
||||
CV_RGBA2YUV_IYUV = CV_RGBA2YUV_I420,
|
||||
CV_BGRA2YUV_IYUV = CV_BGRA2YUV_I420,
|
||||
CV_RGB2YUV_YV12 = 131,
|
||||
CV_BGR2YUV_YV12 = 132,
|
||||
CV_RGBA2YUV_YV12 = 133,
|
||||
CV_BGRA2YUV_YV12 = 134
|
||||
|
||||
// Edge-Aware Demosaicing // 135 - 139
|
||||
};
|
||||
|
||||
// type of morphological operation
|
||||
enum MorphTypes{
|
||||
MORPH_ERODE = 0, // see cv::erode
|
||||
MORPH_DILATE = 1, // see cv::dilate
|
||||
MORPH_OPEN = 2, // an opening operation
|
||||
// \f[\texttt{dst} = \mathrm{open} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \mathrm{erode} ( \texttt{src} , \texttt{element} ))\f]
|
||||
MORPH_CLOSE = 3, // a closing operation
|
||||
// \f[\texttt{dst} = \mathrm{close} ( \texttt{src} , \texttt{element} )= \mathrm{erode} ( \mathrm{dilate} ( \texttt{src} , \texttt{element} ))\f]
|
||||
MORPH_GRADIENT = 4, // a morphological gradient
|
||||
// \f[\texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )\f]
|
||||
MORPH_TOPHAT = 5, // "top hat"
|
||||
// \f[\texttt{dst} = \mathrm{tophat} ( \texttt{src} , \texttt{element} )= \texttt{src} - \mathrm{open} ( \texttt{src} , \texttt{element} )\f]
|
||||
MORPH_BLACKHAT = 6, // "black hat"
|
||||
// \f[\texttt{dst} = \mathrm{blackhat} ( \texttt{src} , \texttt{element} )= \mathrm{close} ( \texttt{src} , \texttt{element} )- \texttt{src}\f]
|
||||
MORPH_HITMISS = 7 // "hit and miss"
|
||||
// Only supported for CV_8UC1 binary images. Tutorial can be found in [this page](http://opencv-code.com/tutorials/hit-or-miss-transform-in-opencv/)
|
||||
};
|
||||
|
||||
// shape of the structuring element
|
||||
enum MorphShapes {
|
||||
MORPH_RECT = 0, // a rectangular structuring element: \f[E_{ij}=1\f]
|
||||
MORPH_CROSS = 1, // a cross-shaped structuring element:
|
||||
//!< \f[E_{ij} = \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}\f]
|
||||
MORPH_ELLIPSE = 2 // an elliptic structuring element, that is, a filled ellipse inscribed
|
||||
// into the rectangle Rect(0, 0, esize.width, 0.esize.height)
|
||||
};
|
||||
|
||||
// type of the threshold operation
|
||||
enum ThresholdTypes {
|
||||
THRESH_BINARY = 0, // \f[\texttt{dst} (x,y) = \fork{\texttt{maxval}}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{0}{otherwise}\f]
|
||||
THRESH_BINARY_INV = 1, // \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{maxval}}{otherwise}\f]
|
||||
THRESH_TRUNC = 2, // \f[\texttt{dst} (x,y) = \fork{\texttt{threshold}}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f]
|
||||
THRESH_TOZERO = 3, // \f[\texttt{dst} (x,y) = \fork{\texttt{src}(x,y)}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{0}{otherwise}\f]
|
||||
THRESH_TOZERO_INV = 4, // \f[\texttt{dst} (x,y) = \fork{0}{if \(\texttt{src}(x,y) > \texttt{thresh}\)}{\texttt{src}(x,y)}{otherwise}\f]
|
||||
THRESH_MASK = 7,
|
||||
THRESH_OTSU = 8, // flag, use Otsu algorithm to choose the optimal threshold value, combine the flag with one of the above THRESH_* values
|
||||
THRESH_TRIANGLE = 16 // flag, use Triangle algorithm to choose the optimal threshold value, combine the flag with one of the above THRESH_* values, but not with THRESH_OTSU
|
||||
};
|
||||
|
||||
// adaptive threshold algorithm
|
||||
enum AdaptiveThresholdTypes {
|
||||
/** the threshold value \f$T(x,y)\f$ is a mean of the \f$\texttt{blockSize} \times
|
||||
\texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$ minus C */
|
||||
ADAPTIVE_THRESH_MEAN_C = 0,
|
||||
/** the threshold value \f$T(x, y)\f$ is a weighted sum (cross-correlation with a Gaussian
|
||||
window) of the \f$\texttt{blockSize} \times \texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$
|
||||
minus C . The default sigma (standard deviation) is used for the specified blockSize . See cv::getGaussianKernel*/
|
||||
ADAPTIVE_THRESH_GAUSSIAN_C = 1
|
||||
};
|
||||
|
||||
// helper tables
|
||||
const uchar icvSaturate8u_cv[] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
||||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
||||
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
|
||||
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
|
||||
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
|
||||
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
|
||||
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
|
||||
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255
|
||||
};
|
||||
|
||||
#define FBC_FAST_CAST_8U(t) (assert(-256 <= (t) && (t) <= 512), icvSaturate8u_cv[(t)+256])
|
||||
#define FBC_CALC_MIN_8U(a,b) (a) -= FBC_FAST_CAST_8U((a) - (b))
|
||||
#define FBC_CALC_MAX_8U(a,b) (a) += FBC_FAST_CAST_8U((b) - (a))
|
||||
|
||||
// cal a structuring element of the specified size and shape for morphological operations
|
||||
FBC_EXPORTS int getStructuringElement(Mat_<uchar, 1>& dst, int shape, Size ksize, Point anchor = Point(-1, -1));
|
||||
|
||||
// Returns the optimal DFT size for a given vector size
|
||||
// Arrays whose size is a power-of-two (2, 4, 8, 16, 32, ...) are the fastest to process.
|
||||
// Though, the arrays whose size is a product of 2's, 3's, and 5's are also processed quite efficiently
|
||||
FBC_EXPORTS int getOptimalDFTSize(int vecsize);
|
||||
|
||||
} // namespace yt_tinycv
|
||||
|
||||
#endif // FBC_CV_IMGPROC_HPP_
|
||||
@@ -0,0 +1,38 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_INTERFACE_HPP_
|
||||
#define FBC_CV_CORE_INTERFACE_HPP_
|
||||
|
||||
// reference: include/opencv2/core/hal/interface.h
|
||||
#include <stdint.h>
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
/* primitive types */
|
||||
/*
|
||||
schar - signed 1 byte integer
|
||||
uchar - unsigned 1 byte integer
|
||||
short - signed 2 byte integer
|
||||
ushort - unsigned 2 byte integer
|
||||
int - signed 4 byte integer
|
||||
uint - unsigned 4 byte integer
|
||||
int64 - signed 8 byte integer
|
||||
uint64 - unsigned 8 byte integer
|
||||
*/
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef signed char schar;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
#ifdef _MSC_VER
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef int64_t int64;
|
||||
typedef uint64_t uint64;
|
||||
#endif
|
||||
|
||||
} // yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_INTERFACE_HPP_
|
||||
@@ -0,0 +1,646 @@
|
||||
// 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_
|
||||
@@ -0,0 +1,667 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_MATHFUNCS_HPP_
|
||||
#define FBC_CV_CORE_MATHFUNCS_HPP_
|
||||
|
||||
/* reference: include/opencv2/core.hpp
|
||||
modules/core/src/mathfuncs.cpp
|
||||
modules/core/src/mathfuncs_core.cpp
|
||||
*/
|
||||
|
||||
#include "mat.hpp"
|
||||
#include "NAryMatIterator.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
// calculates the magnitude of 2D vectors formed from the corresponding elements of x and y arrays
|
||||
// \f[\texttt{dst} (I) = \sqrt{\texttt{x}(I)^2 + \texttt{y}(I)^2}\f]
|
||||
// support type: float/double, multi-channels
|
||||
// template <typename _Tp, int chs>
|
||||
// int magnitude(const Mat_<_Tp, chs>& src1, const Mat_<_Tp, chs>& src2, Mat_<_Tp, chs>& dst)
|
||||
// {
|
||||
// FBC_Assert(typeid(float).name() == typeid(_Tp).name() || typeid(double).name() == typeid(_Tp).name());
|
||||
// FBC_Assert(src1.size() == src2.size());
|
||||
|
||||
// if (dst.empty()) {
|
||||
// dst = Mat_<_Tp, chs>(src1.rows, src1.cols);
|
||||
// } else {
|
||||
// FBC_Assert(src1.size() == dst.size());
|
||||
// }
|
||||
|
||||
// for (int y = 0; y < src1.rows; y++) {
|
||||
// const _Tp* pRowSrc1 = (const _Tp*)src1.ptr(y);
|
||||
// const _Tp* pRowSrc2 = (const _Tp*)src2.ptr(y);
|
||||
// _Tp* pRowDst = (_Tp*)dst.ptr(y);
|
||||
|
||||
// for (int x = 0; x < src1.cols; x++) {
|
||||
// pRowDst[x] = std::sqrt(pRowSrc1[x] * pRowSrc1[x] + pRowSrc2[x] * pRowSrc2[x]);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
/////////////////////////////////////////// LOG ///////////////////////////////////////
|
||||
// #define LOGTAB_SCALE 8
|
||||
// #define LOGTAB_MASK ((1 << LOGTAB_SCALE) - 1)
|
||||
// #define LOGTAB_MASK2 ((1 << (20 - LOGTAB_SCALE)) - 1)
|
||||
// #define LOGTAB_MASK2_32F ((1 << (23 - LOGTAB_SCALE)) - 1)
|
||||
|
||||
// static const double FBC_DECL_ALIGNED(16) ifbcLogTab[] = {
|
||||
// 0.0000000000000000000000000000000000000000, 1.000000000000000000000000000000000000000,
|
||||
// .00389864041565732288852075271279318258166, .9961089494163424124513618677042801556420,
|
||||
// .00778214044205494809292034119607706088573, .9922480620155038759689922480620155038760,
|
||||
// .01165061721997527263705585198749759001657, .9884169884169884169884169884169884169884,
|
||||
// .01550418653596525274396267235488267033361, .9846153846153846153846153846153846153846,
|
||||
// .01934296284313093139406447562578250654042, .9808429118773946360153256704980842911877,
|
||||
// .02316705928153437593630670221500622574241, .9770992366412213740458015267175572519084,
|
||||
// .02697658769820207233514075539915211265906, .9733840304182509505703422053231939163498,
|
||||
// .03077165866675368732785500469617545604706, .9696969696969696969696969696969696969697,
|
||||
// .03455238150665972812758397481047722976656, .9660377358490566037735849056603773584906,
|
||||
// .03831886430213659461285757856785494368522, .9624060150375939849624060150375939849624,
|
||||
// .04207121392068705056921373852674150839447, .9588014981273408239700374531835205992509,
|
||||
// .04580953603129420126371940114040626212953, .9552238805970149253731343283582089552239,
|
||||
// .04953393512227662748292900118940451648088, .9516728624535315985130111524163568773234,
|
||||
// .05324451451881227759255210685296333394944, .9481481481481481481481481481481481481481,
|
||||
// .05694137640013842427411105973078520037234, .9446494464944649446494464944649446494465,
|
||||
// .06062462181643483993820353816772694699466, .9411764705882352941176470588235294117647,
|
||||
// .06429435070539725460836422143984236754475, .9377289377289377289377289377289377289377,
|
||||
// .06795066190850773679699159401934593915938, .9343065693430656934306569343065693430657,
|
||||
// .07159365318700880442825962290953611955044, .9309090909090909090909090909090909090909,
|
||||
// .07522342123758751775142172846244648098944, .9275362318840579710144927536231884057971,
|
||||
// .07884006170777602129362549021607264876369, .9241877256317689530685920577617328519856,
|
||||
// .08244366921107458556772229485432035289706, .9208633093525179856115107913669064748201,
|
||||
// .08603433734180314373940490213499288074675, .9175627240143369175627240143369175627240,
|
||||
// .08961215868968712416897659522874164395031, .9142857142857142857142857142857142857143,
|
||||
// .09317722485418328259854092721070628613231, .9110320284697508896797153024911032028470,
|
||||
// .09672962645855109897752299730200320482256, .9078014184397163120567375886524822695035,
|
||||
// .10026945316367513738597949668474029749630, .9045936395759717314487632508833922261484,
|
||||
// .10379679368164355934833764649738441221420, .9014084507042253521126760563380281690141,
|
||||
// .10731173578908805021914218968959175981580, .8982456140350877192982456140350877192982,
|
||||
// .11081436634029011301105782649756292812530, .8951048951048951048951048951048951048951,
|
||||
// .11430477128005862852422325204315711744130, .8919860627177700348432055749128919860627,
|
||||
// .11778303565638344185817487641543266363440, .8888888888888888888888888888888888888889,
|
||||
// .12124924363286967987640707633545389398930, .8858131487889273356401384083044982698962,
|
||||
// .12470347850095722663787967121606925502420, .8827586206896551724137931034482758620690,
|
||||
// .12814582269193003360996385708858724683530, .8797250859106529209621993127147766323024,
|
||||
// .13157635778871926146571524895989568904040, .8767123287671232876712328767123287671233,
|
||||
// .13499516453750481925766280255629681050780, .8737201365187713310580204778156996587031,
|
||||
// .13840232285911913123754857224412262439730, .8707482993197278911564625850340136054422,
|
||||
// .14179791186025733629172407290752744302150, .8677966101694915254237288135593220338983,
|
||||
// .14518200984449788903951628071808954700830, .8648648648648648648648648648648648648649,
|
||||
// .14855469432313711530824207329715136438610, .8619528619528619528619528619528619528620,
|
||||
// .15191604202584196858794030049466527998450, .8590604026845637583892617449664429530201,
|
||||
// .15526612891112392955683674244937719777230, .8561872909698996655518394648829431438127,
|
||||
// .15860503017663857283636730244325008243330, .8533333333333333333333333333333333333333,
|
||||
// .16193282026931324346641360989451641216880, .8504983388704318936877076411960132890365,
|
||||
// .16524957289530714521497145597095368430010, .8476821192052980132450331125827814569536,
|
||||
// .16855536102980664403538924034364754334090, .8448844884488448844884488448844884488449,
|
||||
// .17185025692665920060697715143760433420540, .8421052631578947368421052631578947368421,
|
||||
// .17513433212784912385018287750426679849630, .8393442622950819672131147540983606557377,
|
||||
// .17840765747281828179637841458315961062910, .8366013071895424836601307189542483660131,
|
||||
// .18167030310763465639212199675966985523700, .8338762214983713355048859934853420195440,
|
||||
// .18492233849401198964024217730184318497780, .8311688311688311688311688311688311688312,
|
||||
// .18816383241818296356839823602058459073300, .8284789644012944983818770226537216828479,
|
||||
// .19139485299962943898322009772527962923050, .8258064516129032258064516129032258064516,
|
||||
// .19461546769967164038916962454095482826240, .8231511254019292604501607717041800643087,
|
||||
// .19782574332991986754137769821682013571260, .8205128205128205128205128205128205128205,
|
||||
// .20102574606059073203390141770796617493040, .8178913738019169329073482428115015974441,
|
||||
// .20421554142869088876999228432396193966280, .8152866242038216560509554140127388535032,
|
||||
// .20739519434607056602715147164417430758480, .8126984126984126984126984126984126984127,
|
||||
// .21056476910734961416338251183333341032260, .8101265822784810126582278481012658227848,
|
||||
// .21372432939771812687723695489694364368910, .8075709779179810725552050473186119873817,
|
||||
// .21687393830061435506806333251006435602900, .8050314465408805031446540880503144654088,
|
||||
// .22001365830528207823135744547471404075630, .8025078369905956112852664576802507836991,
|
||||
// .22314355131420973710199007200571941211830, .8000000000000000000000000000000000000000,
|
||||
// .22626367865045338145790765338460914790630, .7975077881619937694704049844236760124611,
|
||||
// .22937410106484582006380890106811420992010, .7950310559006211180124223602484472049689,
|
||||
// .23247487874309405442296849741978803649550, .7925696594427244582043343653250773993808,
|
||||
// .23556607131276688371634975283086532726890, .7901234567901234567901234567901234567901,
|
||||
// .23864773785017498464178231643018079921600, .7876923076923076923076923076923076923077,
|
||||
// .24171993688714515924331749374687206000090, .7852760736196319018404907975460122699387,
|
||||
// .24478272641769091566565919038112042471760, .7828746177370030581039755351681957186544,
|
||||
// .24783616390458124145723672882013488560910, .7804878048780487804878048780487804878049,
|
||||
// .25088030628580937353433455427875742316250, .7781155015197568389057750759878419452888,
|
||||
// .25391520998096339667426946107298135757450, .7757575757575757575757575757575757575758,
|
||||
// .25694093089750041913887912414793390780680, .7734138972809667673716012084592145015106,
|
||||
// .25995752443692604627401010475296061486000, .7710843373493975903614457831325301204819,
|
||||
// .26296504550088134477547896494797896593800, .7687687687687687687687687687687687687688,
|
||||
// .26596354849713793599974565040611196309330, .7664670658682634730538922155688622754491,
|
||||
// .26895308734550393836570947314612567424780, .7641791044776119402985074626865671641791,
|
||||
// .27193371548364175804834985683555714786050, .7619047619047619047619047619047619047619,
|
||||
// .27490548587279922676529508862586226314300, .7596439169139465875370919881305637982196,
|
||||
// .27786845100345625159121709657483734190480, .7573964497041420118343195266272189349112,
|
||||
// .28082266290088775395616949026589281857030, .7551622418879056047197640117994100294985,
|
||||
// .28376817313064456316240580235898960381750, .7529411764705882352941176470588235294118,
|
||||
// .28670503280395426282112225635501090437180, .7507331378299120234604105571847507331378,
|
||||
// .28963329258304265634293983566749375313530, .7485380116959064327485380116959064327485,
|
||||
// .29255300268637740579436012922087684273730, .7463556851311953352769679300291545189504,
|
||||
// .29546421289383584252163927885703742504130, .7441860465116279069767441860465116279070,
|
||||
// .29836697255179722709783618483925238251680, .7420289855072463768115942028985507246377,
|
||||
// .30126133057816173455023545102449133992200, .7398843930635838150289017341040462427746,
|
||||
// .30414733546729666446850615102448500692850, .7377521613832853025936599423631123919308,
|
||||
// .30702503529491181888388950937951449304830, .7356321839080459770114942528735632183908,
|
||||
// .30989447772286465854207904158101882785550, .7335243553008595988538681948424068767908,
|
||||
// .31275571000389684739317885942000430077330, .7314285714285714285714285714285714285714,
|
||||
// .31560877898630329552176476681779604405180, .7293447293447293447293447293447293447293,
|
||||
// .31845373111853458869546784626436419785030, .7272727272727272727272727272727272727273,
|
||||
// .32129061245373424782201254856772720813750, .7252124645892351274787535410764872521246,
|
||||
// .32411946865421192853773391107097268104550, .7231638418079096045197740112994350282486,
|
||||
// .32694034499585328257253991068864706903700, .7211267605633802816901408450704225352113,
|
||||
// .32975328637246797969240219572384376078850, .7191011235955056179775280898876404494382,
|
||||
// .33255833730007655635318997155991382896900, .7170868347338935574229691876750700280112,
|
||||
// .33535554192113781191153520921943709254280, .7150837988826815642458100558659217877095,
|
||||
// .33814494400871636381467055798566434532400, .7130919220055710306406685236768802228412,
|
||||
// .34092658697059319283795275623560883104800, .7111111111111111111111111111111111111111,
|
||||
// .34370051385331840121395430287520866841080, .7091412742382271468144044321329639889197,
|
||||
// .34646676734620857063262633346312213689100, .7071823204419889502762430939226519337017,
|
||||
// .34922538978528827602332285096053965389730, .7052341597796143250688705234159779614325,
|
||||
// .35197642315717814209818925519357435405250, .7032967032967032967032967032967032967033,
|
||||
// .35471990910292899856770532096561510115850, .7013698630136986301369863013698630136986,
|
||||
// .35745588892180374385176833129662554711100, .6994535519125683060109289617486338797814,
|
||||
// .36018440357500774995358483465679455548530, .6975476839237057220708446866485013623978,
|
||||
// .36290549368936841911903457003063522279280, .6956521739130434782608695652173913043478,
|
||||
// .36561919956096466943762379742111079394830, .6937669376693766937669376693766937669377,
|
||||
// .36832556115870762614150635272380895912650, .6918918918918918918918918918918918918919,
|
||||
// .37102461812787262962487488948681857436900, .6900269541778975741239892183288409703504,
|
||||
// .37371640979358405898480555151763837784530, .6881720430107526881720430107526881720430,
|
||||
// .37640097516425302659470730759494472295050, .6863270777479892761394101876675603217158,
|
||||
// .37907835293496944251145919224654790014030, .6844919786096256684491978609625668449198,
|
||||
// .38174858149084833769393299007788300514230, .6826666666666666666666666666666666666667,
|
||||
// .38441169891033200034513583887019194662580, .6808510638297872340425531914893617021277,
|
||||
// .38706774296844825844488013899535872042180, .6790450928381962864721485411140583554377,
|
||||
// .38971675114002518602873692543653305619950, .6772486772486772486772486772486772486772,
|
||||
// .39235876060286384303665840889152605086580, .6754617414248021108179419525065963060686,
|
||||
// .39499380824086893770896722344332374632350, .6736842105263157894736842105263157894737,
|
||||
// .39762193064713846624158577469643205404280, .6719160104986876640419947506561679790026,
|
||||
// .40024316412701266276741307592601515352730, .6701570680628272251308900523560209424084,
|
||||
// .40285754470108348090917615991202183067800, .6684073107049608355091383812010443864230,
|
||||
// .40546510810816432934799991016916465014230, .6666666666666666666666666666666666666667,
|
||||
// .40806588980822172674223224930756259709600, .6649350649350649350649350649350649350649,
|
||||
// .41065992498526837639616360320360399782650, .6632124352331606217616580310880829015544,
|
||||
// .41324724855021932601317757871584035456180, .6614987080103359173126614987080103359173,
|
||||
// .41582789514371093497757669865677598863850, .6597938144329896907216494845360824742268,
|
||||
// .41840189913888381489925905043492093682300, .6580976863753213367609254498714652956298,
|
||||
// .42096929464412963239894338585145305842150, .6564102564102564102564102564102564102564,
|
||||
// .42353011550580327293502591601281892508280, .6547314578005115089514066496163682864450,
|
||||
// .42608439531090003260516141381231136620050, .6530612244897959183673469387755102040816,
|
||||
// .42863216738969872610098832410585600882780, .6513994910941475826972010178117048346056,
|
||||
// .43117346481837132143866142541810404509300, .6497461928934010152284263959390862944162,
|
||||
// .43370832042155937902094819946796633303180, .6481012658227848101265822784810126582278,
|
||||
// .43623676677491801667585491486534010618930, .6464646464646464646464646464646464646465,
|
||||
// .43875883620762790027214350629947148263450, .6448362720403022670025188916876574307305,
|
||||
// .44127456080487520440058801796112675219780, .6432160804020100502512562814070351758794,
|
||||
// .44378397241030093089975139264424797147500, .6416040100250626566416040100250626566416,
|
||||
// .44628710262841947420398014401143882423650, .6400000000000000000000000000000000000000,
|
||||
// .44878398282700665555822183705458883196130, .6384039900249376558603491271820448877805,
|
||||
// .45127464413945855836729492693848442286250, .6368159203980099502487562189054726368159,
|
||||
// .45375911746712049854579618113348260521900, .6352357320099255583126550868486352357320,
|
||||
// .45623743348158757315857769754074979573500, .6336633663366336633663366336633663366337,
|
||||
// .45870962262697662081833982483658473938700, .6320987654320987654320987654320987654321,
|
||||
// .46117571512217014895185229761409573256980, .6305418719211822660098522167487684729064,
|
||||
// .46363574096303250549055974261136725544930, .6289926289926289926289926289926289926290,
|
||||
// .46608972992459918316399125615134835243230, .6274509803921568627450980392156862745098,
|
||||
// .46853771156323925639597405279346276074650, .6259168704156479217603911980440097799511,
|
||||
// .47097971521879100631480241645476780831830, .6243902439024390243902439024390243902439,
|
||||
// .47341577001667212165614273544633761048330, .6228710462287104622871046228710462287105,
|
||||
// .47584590486996386493601107758877333253630, .6213592233009708737864077669902912621359,
|
||||
// .47827014848147025860569669930555392056700, .6198547215496368038740920096852300242131,
|
||||
// .48068852934575190261057286988943815231330, .6183574879227053140096618357487922705314,
|
||||
// .48310107575113581113157579238759353756900, .6168674698795180722891566265060240963855,
|
||||
// .48550781578170076890899053978500887751580, .6153846153846153846153846153846153846154,
|
||||
// .48790877731923892879351001283794175833480, .6139088729016786570743405275779376498801,
|
||||
// .49030398804519381705802061333088204264650, .6124401913875598086124401913875598086124,
|
||||
// .49269347544257524607047571407747454941280, .6109785202863961813842482100238663484487,
|
||||
// .49507726679785146739476431321236304938800, .6095238095238095238095238095238095238095,
|
||||
// .49745538920281889838648226032091770321130, .6080760095011876484560570071258907363420,
|
||||
// .49982786955644931126130359189119189977650, .6066350710900473933649289099526066350711,
|
||||
// .50219473456671548383667413872899487614650, .6052009456264775413711583924349881796690,
|
||||
// .50455601075239520092452494282042607665050, .6037735849056603773584905660377358490566,
|
||||
// .50691172444485432801997148999362252652650, .6023529411764705882352941176470588235294,
|
||||
// .50926190178980790257412536448100581765150, .6009389671361502347417840375586854460094,
|
||||
// .51160656874906207391973111953120678663250, .5995316159250585480093676814988290398126,
|
||||
// .51394575110223428282552049495279788970950, .5981308411214953271028037383177570093458,
|
||||
// .51627947444845445623684554448118433356300, .5967365967365967365967365967365967365967,
|
||||
// .51860776420804555186805373523384332656850, .5953488372093023255813953488372093023256,
|
||||
// .52093064562418522900344441950437612831600, .5939675174013921113689095127610208816705,
|
||||
// .52324814376454775732838697877014055848100, .5925925925925925925925925925925925925926,
|
||||
// .52556028352292727401362526507000438869000, .5912240184757505773672055427251732101617,
|
||||
// .52786708962084227803046587723656557500350, .5898617511520737327188940092165898617512,
|
||||
// .53016858660912158374145519701414741575700, .5885057471264367816091954022988505747126,
|
||||
// .53246479886947173376654518506256863474850, .5871559633027522935779816513761467889908,
|
||||
// .53475575061602764748158733709715306758900, .5858123569794050343249427917620137299771,
|
||||
// .53704146589688361856929077475797384977350, .5844748858447488584474885844748858447489,
|
||||
// .53932196859560876944783558428753167390800, .5831435079726651480637813211845102505695,
|
||||
// .54159728243274429804188230264117009937750, .5818181818181818181818181818181818181818,
|
||||
// .54386743096728351609669971367111429572100, .5804988662131519274376417233560090702948,
|
||||
// .54613243759813556721383065450936555862450, .5791855203619909502262443438914027149321,
|
||||
// .54839232556557315767520321969641372561450, .5778781038374717832957110609480812641084,
|
||||
// .55064711795266219063194057525834068655950, .5765765765765765765765765765765765765766,
|
||||
// .55289683768667763352766542084282264113450, .5752808988764044943820224719101123595506,
|
||||
// .55514150754050151093110798683483153581600, .5739910313901345291479820627802690582960,
|
||||
// .55738115013400635344709144192165695130850, .5727069351230425055928411633109619686801,
|
||||
// .55961578793542265941596269840374588966350, .5714285714285714285714285714285714285714,
|
||||
// .56184544326269181269140062795486301183700, .5701559020044543429844097995545657015590,
|
||||
// .56407013828480290218436721261241473257550, .5688888888888888888888888888888888888889,
|
||||
// .56628989502311577464155334382667206227800, .5676274944567627494456762749445676274945,
|
||||
// .56850473535266865532378233183408156037350, .5663716814159292035398230088495575221239,
|
||||
// .57071468100347144680739575051120482385150, .5651214128035320088300220750551876379691,
|
||||
// .57291975356178548306473885531886480748650, .5638766519823788546255506607929515418502,
|
||||
// .57511997447138785144460371157038025558000, .5626373626373626373626373626373626373626,
|
||||
// .57731536503482350219940144597785547375700, .5614035087719298245614035087719298245614,
|
||||
// .57950594641464214795689713355386629700650, .5601750547045951859956236323851203501094,
|
||||
// .58169173963462239562716149521293118596100, .5589519650655021834061135371179039301310,
|
||||
// .58387276558098266665552955601015128195300, .5577342047930283224400871459694989106754,
|
||||
// .58604904500357812846544902640744112432000, .5565217391304347826086956521739130434783,
|
||||
// .58822059851708596855957011939608491957200, .5553145336225596529284164859002169197397,
|
||||
// .59038744660217634674381770309992134571100, .5541125541125541125541125541125541125541,
|
||||
// .59254960960667157898740242671919986605650, .5529157667386609071274298056155507559395,
|
||||
// .59470710774669277576265358220553025603300, .5517241379310344827586206896551724137931,
|
||||
// .59685996110779382384237123915227130055450, .5505376344086021505376344086021505376344,
|
||||
// .59900818964608337768851242799428291618800, .5493562231759656652360515021459227467811,
|
||||
// .60115181318933474940990890900138765573500, .5481798715203426124197002141327623126338,
|
||||
// .60329085143808425240052883964381180703650, .5470085470085470085470085470085470085470,
|
||||
// .60542532396671688843525771517306566238400, .5458422174840085287846481876332622601279,
|
||||
// .60755525022454170969155029524699784815300, .5446808510638297872340425531914893617021,
|
||||
// .60968064953685519036241657886421307921400, .5435244161358811040339702760084925690021,
|
||||
// .61180154110599282990534675263916142284850, .5423728813559322033898305084745762711864,
|
||||
// .61391794401237043121710712512140162289150, .5412262156448202959830866807610993657505,
|
||||
// .61602987721551394351138242200249806046500, .5400843881856540084388185654008438818565,
|
||||
// .61813735955507864705538167982012964785100, .5389473684210526315789473684210526315789,
|
||||
// .62024040975185745772080281312810257077200, .5378151260504201680672268907563025210084,
|
||||
// .62233904640877868441606324267922900617100, .5366876310272536687631027253668763102725,
|
||||
// .62443328801189346144440150965237990021700, .5355648535564853556485355648535564853556,
|
||||
// .62652315293135274476554741340805776417250, .5344467640918580375782881002087682672234,
|
||||
// .62860865942237409420556559780379757285100, .5333333333333333333333333333333333333333,
|
||||
// .63068982562619868570408243613201193511500, .5322245322245322245322245322245322245322,
|
||||
// .63276666957103777644277897707070223987100, .5311203319502074688796680497925311203320,
|
||||
// .63483920917301017716738442686619237065300, .5300207039337474120082815734989648033126,
|
||||
// .63690746223706917739093569252872839570050, .5289256198347107438016528925619834710744,
|
||||
// .63897144645792069983514238629140891134750, .5278350515463917525773195876288659793814,
|
||||
// .64103117942093124081992527862894348800200, .5267489711934156378600823045267489711934,
|
||||
// .64308667860302726193566513757104985415950, .5256673511293634496919917864476386036961,
|
||||
// .64513796137358470073053240412264131009600, .5245901639344262295081967213114754098361,
|
||||
// .64718504499530948859131740391603671014300, .5235173824130879345603271983640081799591,
|
||||
// .64922794662510974195157587018911726772800, .5224489795918367346938775510204081632653,
|
||||
// .65126668331495807251485530287027359008800, .5213849287169042769857433808553971486762,
|
||||
// .65330127201274557080523663898929953575150, .5203252032520325203252032520325203252033,
|
||||
// .65533172956312757406749369692988693714150, .5192697768762677484787018255578093306288,
|
||||
// .65735807270835999727154330685152672231200, .5182186234817813765182186234817813765182,
|
||||
// .65938031808912778153342060249997302889800, .5171717171717171717171717171717171717172,
|
||||
// .66139848224536490484126716182800009846700, .5161290322580645161290322580645161290323,
|
||||
// .66341258161706617713093692145776003599150, .5150905432595573440643863179074446680080,
|
||||
// .66542263254509037562201001492212526500250, .5140562248995983935742971887550200803213,
|
||||
// .66742865127195616370414654738851822912700, .5130260521042084168336673346693386773547,
|
||||
// .66943065394262923906154583164607174694550, .5120000000000000000000000000000000000000,
|
||||
// .67142865660530226534774556057527661323550, .5109780439121756487025948103792415169661,
|
||||
// .67342267521216669923234121597488410770900, .5099601593625498007968127490039840637450,
|
||||
// .67541272562017662384192817626171745359900, .5089463220675944333996023856858846918489,
|
||||
// .67739882359180603188519853574689477682100, .5079365079365079365079365079365079365079,
|
||||
// .67938098479579733801614338517538271844400, .5069306930693069306930693069306930693069,
|
||||
// .68135922480790300781450241629499942064300, .5059288537549407114624505928853754940711,
|
||||
// .68333355911162063645036823800182901322850, .5049309664694280078895463510848126232742,
|
||||
// .68530400309891936760919861626462079584600, .5039370078740157480314960629921259842520,
|
||||
// .68727057207096020619019327568821609020250, .5029469548133595284872298624754420432220,
|
||||
// .68923328123880889251040571252815425395950, .5019607843137254901960784313725490196078,
|
||||
// .69314718055994530941723212145818, 5.0e-01,
|
||||
// };
|
||||
|
||||
// #define LOGTAB_TRANSLATE(x,h) (((x) - 1.)*ifbcLogTab[(h)+1])
|
||||
// static const double ln_2 = 0.69314718055994530941723212145818;
|
||||
|
||||
// typedef union
|
||||
// {
|
||||
// struct {
|
||||
// int lo;
|
||||
// int hi;
|
||||
// } i;
|
||||
// double d;
|
||||
// } DBLINT;
|
||||
|
||||
// template<typename dump> static void Log_32f(const float *_x, float *y, int n)
|
||||
// {
|
||||
// static const float shift[] = { 0, -1.f / 512 };
|
||||
// static const float
|
||||
// A0 = 0.3333333333333333333333333f,
|
||||
// A1 = -0.5f,
|
||||
// A2 = 1.f;
|
||||
|
||||
// #undef LOGPOLY
|
||||
// #define LOGPOLY(x) (((A0*(x) + A1)*(x) + A2)*(x))
|
||||
|
||||
// int i = 0;
|
||||
// Cv32suf buf[4];
|
||||
// const int* x = (const int*)_x;
|
||||
|
||||
// for (; i <= n - 4; i += 4) {
|
||||
// double x0, x1, x2, x3;
|
||||
// double y0, y1, y2, y3;
|
||||
// int h0, h1, h2, h3;
|
||||
|
||||
// h0 = x[i];
|
||||
// h1 = x[i + 1];
|
||||
// buf[0].i = (h0 & LOGTAB_MASK2_32F) | (127 << 23);
|
||||
// buf[1].i = (h1 & LOGTAB_MASK2_32F) | (127 << 23);
|
||||
|
||||
// y0 = (((h0 >> 23) & 0xff) - 127) * ln_2;
|
||||
// y1 = (((h1 >> 23) & 0xff) - 127) * ln_2;
|
||||
|
||||
// h0 = (h0 >> (23 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
// h1 = (h1 >> (23 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
|
||||
// y0 += ifbcLogTab[h0];
|
||||
// y1 += ifbcLogTab[h1];
|
||||
|
||||
// h2 = x[i + 2];
|
||||
// h3 = x[i + 3];
|
||||
|
||||
// x0 = LOGTAB_TRANSLATE(buf[0].f, h0);
|
||||
// x1 = LOGTAB_TRANSLATE(buf[1].f, h1);
|
||||
|
||||
// buf[2].i = (h2 & LOGTAB_MASK2_32F) | (127 << 23);
|
||||
// buf[3].i = (h3 & LOGTAB_MASK2_32F) | (127 << 23);
|
||||
|
||||
// y2 = (((h2 >> 23) & 0xff) - 127) * ln_2;
|
||||
// y3 = (((h3 >> 23) & 0xff) - 127) * ln_2;
|
||||
|
||||
// h2 = (h2 >> (23 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
// h3 = (h3 >> (23 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
|
||||
// y2 += ifbcLogTab[h2];
|
||||
// y3 += ifbcLogTab[h3];
|
||||
|
||||
// x2 = LOGTAB_TRANSLATE(buf[2].f, h2);
|
||||
// x3 = LOGTAB_TRANSLATE(buf[3].f, h3);
|
||||
|
||||
// x0 += shift[h0 == 510];
|
||||
// x1 += shift[h1 == 510];
|
||||
// y0 += LOGPOLY(x0);
|
||||
// y1 += LOGPOLY(x1);
|
||||
|
||||
// y[i] = (float)y0;
|
||||
// y[i + 1] = (float)y1;
|
||||
|
||||
// x2 += shift[h2 == 510];
|
||||
// x3 += shift[h3 == 510];
|
||||
// y2 += LOGPOLY(x2);
|
||||
// y3 += LOGPOLY(x3);
|
||||
|
||||
// y[i + 2] = (float)y2;
|
||||
// y[i + 3] = (float)y3;
|
||||
// }
|
||||
|
||||
// for (; i < n; i++) {
|
||||
// int h0 = x[i];
|
||||
// double y0;
|
||||
// float x0;
|
||||
|
||||
// y0 = (((h0 >> 23) & 0xff) - 127) * ln_2;
|
||||
|
||||
// buf[0].i = (h0 & LOGTAB_MASK2_32F) | (127 << 23);
|
||||
// h0 = (h0 >> (23 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
|
||||
// y0 += ifbcLogTab[h0];
|
||||
// x0 = (float)LOGTAB_TRANSLATE(buf[0].f, h0);
|
||||
// x0 += shift[h0 == 510];
|
||||
// y0 += LOGPOLY(x0);
|
||||
|
||||
// y[i] = (float)y0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// template<typename dump> static void Log_64f(const double *x, double *y, int n)
|
||||
// {
|
||||
// static const double shift[] = { 0, -1. / 512 };
|
||||
// static const double
|
||||
// A7 = 1.0,
|
||||
// A6 = -0.5,
|
||||
// A5 = 0.333333333333333314829616256247390992939472198486328125,
|
||||
// A4 = -0.25,
|
||||
// A3 = 0.2,
|
||||
// A2 = -0.1666666666666666574148081281236954964697360992431640625,
|
||||
// A1 = 0.1428571428571428769682682968777953647077083587646484375,
|
||||
// A0 = -0.125;
|
||||
|
||||
// #undef LOGPOLY
|
||||
// #define LOGPOLY(x,k) ((x)+=shift[k], xq = (x)*(x),\
|
||||
// (((A0*xq + A2)*xq + A4)*xq + A6)*xq + \
|
||||
// (((A1*xq + A3)*xq + A5)*xq + A7)*(x))
|
||||
|
||||
// int i = 0;
|
||||
// DBLINT buf[4];
|
||||
// DBLINT *X = (DBLINT *)x;
|
||||
|
||||
// for (; i <= n - 4; i += 4) {
|
||||
// double xq;
|
||||
// double x0, x1, x2, x3;
|
||||
// double y0, y1, y2, y3;
|
||||
// int h0, h1, h2, h3;
|
||||
|
||||
// h0 = X[i].i.lo;
|
||||
// h1 = X[i + 1].i.lo;
|
||||
// buf[0].i.lo = h0;
|
||||
// buf[1].i.lo = h1;
|
||||
|
||||
// h0 = X[i].i.hi;
|
||||
// h1 = X[i + 1].i.hi;
|
||||
// buf[0].i.hi = (h0 & LOGTAB_MASK2) | (1023 << 20);
|
||||
// buf[1].i.hi = (h1 & LOGTAB_MASK2) | (1023 << 20);
|
||||
|
||||
// y0 = (((h0 >> 20) & 0x7ff) - 1023) * ln_2;
|
||||
// y1 = (((h1 >> 20) & 0x7ff) - 1023) * ln_2;
|
||||
|
||||
// h2 = X[i + 2].i.lo;
|
||||
// h3 = X[i + 3].i.lo;
|
||||
// buf[2].i.lo = h2;
|
||||
// buf[3].i.lo = h3;
|
||||
|
||||
// h0 = (h0 >> (20 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
// h1 = (h1 >> (20 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
|
||||
// y0 += ifbcLogTab[h0];
|
||||
// y1 += ifbcLogTab[h1];
|
||||
|
||||
// h2 = X[i + 2].i.hi;
|
||||
// h3 = X[i + 3].i.hi;
|
||||
|
||||
// x0 = LOGTAB_TRANSLATE(buf[0].d, h0);
|
||||
// x1 = LOGTAB_TRANSLATE(buf[1].d, h1);
|
||||
|
||||
// buf[2].i.hi = (h2 & LOGTAB_MASK2) | (1023 << 20);
|
||||
// buf[3].i.hi = (h3 & LOGTAB_MASK2) | (1023 << 20);
|
||||
|
||||
// y2 = (((h2 >> 20) & 0x7ff) - 1023) * ln_2;
|
||||
// y3 = (((h3 >> 20) & 0x7ff) - 1023) * ln_2;
|
||||
|
||||
// h2 = (h2 >> (20 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
// h3 = (h3 >> (20 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
|
||||
// y2 += ifbcLogTab[h2];
|
||||
// y3 += ifbcLogTab[h3];
|
||||
|
||||
// x2 = LOGTAB_TRANSLATE(buf[2].d, h2);
|
||||
// x3 = LOGTAB_TRANSLATE(buf[3].d, h3);
|
||||
|
||||
// y0 += LOGPOLY(x0, h0 == 510);
|
||||
// y1 += LOGPOLY(x1, h1 == 510);
|
||||
|
||||
// y[i] = y0;
|
||||
// y[i + 1] = y1;
|
||||
|
||||
// y2 += LOGPOLY(x2, h2 == 510);
|
||||
// y3 += LOGPOLY(x3, h3 == 510);
|
||||
|
||||
// y[i + 2] = y2;
|
||||
// y[i + 3] = y3;
|
||||
// }
|
||||
|
||||
// for (; i < n; i++) {
|
||||
// int h0 = X[i].i.hi;
|
||||
// double xq;
|
||||
// double x0, y0 = (((h0 >> 20) & 0x7ff) - 1023) * ln_2;
|
||||
|
||||
// buf[0].i.hi = (h0 & LOGTAB_MASK2) | (1023 << 20);
|
||||
// buf[0].i.lo = X[i].i.lo;
|
||||
// h0 = (h0 >> (20 - LOGTAB_SCALE - 1)) & LOGTAB_MASK * 2;
|
||||
|
||||
// y0 += ifbcLogTab[h0];
|
||||
// x0 = LOGTAB_TRANSLATE(buf[0].d, h0);
|
||||
// y0 += LOGPOLY(x0, h0 == 510);
|
||||
// y[i] = y0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // calculates the natural logarithm of the absolute value of every element of the input array
|
||||
// // \f[\texttt{dst} (I) = \fork{\log |\texttt{src}(I)|}{if \(\texttt{src}(I) \ne 0\) }{\texttt{C}}{otherwise}\f]
|
||||
// // support type: float/double, multi-channels
|
||||
// template <typename _Tp, int chs>
|
||||
// int log(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)
|
||||
// {
|
||||
// FBC_Assert(typeid(float).name() == typeid(_Tp).name() || typeid(double).name() == typeid(_Tp).name());
|
||||
// if (dst.empty()) {
|
||||
// dst = Mat_<_Tp, chs>(src.rows, src.cols);
|
||||
// } else {
|
||||
// FBC_Assert(src.size() == dst.size());
|
||||
// }
|
||||
|
||||
// if (src.isContinuous() == false || dst.isContinuous() == false) {
|
||||
// fprintf(stderr, "Error: src and dst must be continuous\n");
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// const Mat_<_Tp, chs>* arrays[] = { &src, &dst, 0 };
|
||||
// uchar* ptrs[2];
|
||||
// ptrs[0] = src.data;
|
||||
// ptrs[1] = dst.data;
|
||||
|
||||
// int len = (int)(src.rows * src.cols *chs);
|
||||
|
||||
// if (sizeof(_Tp) == 4) { // floal
|
||||
// Log_32f<dump>((const float*)ptrs[0], (float*)ptrs[1], len);
|
||||
// } else { // double
|
||||
// Log_64f<dump>((const double*)ptrs[0], (double*)ptrs[1], len);
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// find the minimum and maximum element values and their positions
|
||||
//// support type: single-channel
|
||||
template<typename _Tp, int chs>
|
||||
int minMaxLoc(const Mat_<_Tp, chs>& _img, double* minVal, double* maxVal = 0, Point* minLoc = 0, Point* maxLoc = 0, const Mat_<uchar, 1>& mask = Mat_<uchar, 1>())
|
||||
{
|
||||
FBC_Assert(chs == 1);
|
||||
if (!mask.empty()) {
|
||||
FBC_Assert(_img.rows == mask.rows && _img.cols == mask.cols);
|
||||
}
|
||||
|
||||
double minVal_ = INT_MAX;
|
||||
double maxVal_ = INT_MIN;
|
||||
Point minLoc_ = Point(-1, -1);
|
||||
Point maxLoc_ = Point(-1, -1);
|
||||
|
||||
if (mask.empty()) {
|
||||
for (int y = 0; y < _img.rows; y++) {
|
||||
_Tp* p = (_Tp*)_img.ptr(y);
|
||||
|
||||
for (int x = 0; x < _img.cols; x++) {
|
||||
if (p[x] > maxVal_) {
|
||||
maxVal_ = p[x];
|
||||
maxLoc_.x = x;
|
||||
maxLoc_.y = y;
|
||||
}
|
||||
|
||||
if (p[x] < minVal_) {
|
||||
minVal_ = p[x];
|
||||
minLoc_.x = x;
|
||||
minLoc_.y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int y = 0; y < _img.rows; y++) {
|
||||
_Tp* p1 = (_Tp*)_img.ptr(y);
|
||||
const uchar* p2 = mask.ptr(y);
|
||||
|
||||
for (int x = 0; x < _img.cols; x++) {
|
||||
if (p2[x] && p1[x] > maxVal_) {
|
||||
maxVal_ = p1[x];
|
||||
maxLoc_.x = x;
|
||||
maxLoc_.y = y;
|
||||
}
|
||||
|
||||
if (p2[x] && p1[x] < minVal_) {
|
||||
minVal_ = p1[x];
|
||||
minLoc_.x = x;
|
||||
minLoc_.y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*minVal = minVal_;
|
||||
if (maxVal) *maxVal = maxVal_;
|
||||
if (minLoc) *minLoc = minLoc_;
|
||||
if (maxLoc) *maxLoc = maxLoc_;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Normalizes the norm or value range of an array
|
||||
/* \f[\| \texttt{dst} \| _{L_p}= \texttt{alpha}\f]
|
||||
(where p=Inf, 1 or 2) when normType=NORM_INF, NORM_L1, or NORM_L2, respectively; or so that
|
||||
\f[\min _I \texttt{dst} (I)= \texttt{alpha} , \, \, \max _I \texttt{dst} (I)= \texttt{beta}\f] */
|
||||
// support type: float/double, multi-channels
|
||||
template<typename _Tp1, typename _Tp2, int chs>
|
||||
int normalize(const Mat_<_Tp1, chs>& _src, Mat_<_Tp2, chs>& _dst, double a = 1, double b = 0, int norm_type = NORM_L2, const Mat_<uchar, 1>& _mask = Mat_<uchar, 1>())
|
||||
{
|
||||
//FBC_Assert(typeid(float).name() == typeid(_Tp).name() || typeid(double).name() == typeid(_Tp).name());
|
||||
if (_dst.empty()) {
|
||||
_dst = Mat_<_Tp2, chs>(_src.rows, _src.cols);
|
||||
} else {
|
||||
FBC_Assert(_src.size() == _dst.size());
|
||||
}
|
||||
|
||||
double scale = 1, shift = 0;
|
||||
if (norm_type == FBC_MINMAX) {
|
||||
double smin = 0, smax = 0;
|
||||
double dmin = MIN(a, b), dmax = MAX(a, b);
|
||||
minMaxLoc(_src, &smin, &smax, 0, 0, _mask);
|
||||
scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1. / (smax - smin) : 0);
|
||||
shift = dmin - smin*scale;
|
||||
} else if (norm_type == FBC_L2 || norm_type == FBC_L1 || norm_type == FBC_C) {
|
||||
fprintf(stderr, "Error: normalize norm no impl\n");
|
||||
FBC_Assert(0); // TODO
|
||||
/*scale = norm(_src, norm_type, _mask);
|
||||
scale = scale > DBL_EPSILON ? a / scale : 0.;
|
||||
shift = 0;*/
|
||||
} else {
|
||||
FBC_Error("Unknown/unsupported norm type");
|
||||
}
|
||||
|
||||
Scalar scalar = Scalar::all(shift);
|
||||
if (_mask.empty()) {
|
||||
_src.convertTo(_dst, scale, scalar);
|
||||
} else {
|
||||
Mat_<_Tp2, chs> tmp;
|
||||
_src.convertTo(tmp, scale, scalar);
|
||||
|
||||
for (int y = 0; y < _dst.rows; y++) {
|
||||
_Tp2* p1 = (_Tp2*)_dst.ptr(y);
|
||||
const _Tp2* p2 = (_Tp2*)tmp.ptr(y);
|
||||
const uchar* p3 = _mask.ptr(y);
|
||||
|
||||
for (int x = 0; x < _dst.cols; x++) {
|
||||
if (p3[x] != 0) {
|
||||
p1[x] = p2[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_MATHFUNCS_HPP_
|
||||
@@ -0,0 +1,851 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_MATX_HPP_
|
||||
#define FBC_CV_CORE_MATX_HPP_
|
||||
|
||||
// reference: include/opencv2/core/matx.hpp
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error matx.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
#include "fbcdef.hpp"
|
||||
#include "base.hpp"
|
||||
#include "interface.hpp"
|
||||
#include "saturate.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
////////////////////////////// Small Matrix ///////////////////////////
|
||||
// Template class for small matrices whose type and size are known at compilation time
|
||||
template<typename _Tp, int m, int n> class Matx {
|
||||
public:
|
||||
enum {
|
||||
rows = m,
|
||||
cols = n,
|
||||
channels = rows*cols,
|
||||
shortdim = (m < n ? m : n)
|
||||
};
|
||||
|
||||
typedef _Tp value_type;
|
||||
typedef Matx<_Tp, m, n> mat_type;
|
||||
typedef Matx<_Tp, shortdim, 1> diag_type;
|
||||
|
||||
//! default constructor
|
||||
Matx();
|
||||
|
||||
Matx(_Tp v0); //!< 1x1 matrix
|
||||
Matx(_Tp v0, _Tp v1); //!< 1x2 or 2x1 matrix
|
||||
Matx(_Tp v0, _Tp v1, _Tp v2); //!< 1x3 or 3x1 matrix
|
||||
Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 1x4, 2x2 or 4x1 matrix
|
||||
Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 1x5 or 5x1 matrix
|
||||
Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix
|
||||
Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 1x7 or 7x1 matrix
|
||||
Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix
|
||||
Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 1x9, 3x3 or 9x1 matrix
|
||||
explicit Matx(const _Tp* vals); //!< initialize from a plain array
|
||||
|
||||
static Matx all(_Tp alpha);
|
||||
static Matx zeros();
|
||||
static Matx ones();
|
||||
static Matx eye();
|
||||
static Matx diag(const diag_type& d);
|
||||
|
||||
//! dot product computed with the default precision
|
||||
_Tp dot(const Matx<_Tp, m, n>& v) const;
|
||||
|
||||
//! dot product computed in double-precision arithmetics
|
||||
double ddot(const Matx<_Tp, m, n>& v) const;
|
||||
|
||||
//! conversion to another data type
|
||||
template<typename T2> operator Matx<T2, m, n>() const;
|
||||
|
||||
//! change the matrix shape
|
||||
template<int m1, int n1> Matx<_Tp, m1, n1> reshape() const;
|
||||
|
||||
//! extract part of the matrix
|
||||
template<int m1, int n1> Matx<_Tp, m1, n1> get_minor(int i, int j) const;
|
||||
|
||||
//! extract the matrix row
|
||||
Matx<_Tp, 1, n> row(int i) const;
|
||||
|
||||
//! extract the matrix column
|
||||
Matx<_Tp, m, 1> col(int i) const;
|
||||
|
||||
//! extract the matrix diagonal
|
||||
diag_type diag() const;
|
||||
|
||||
//! element access
|
||||
const _Tp& operator ()(int i, int j) const;
|
||||
_Tp& operator ()(int i, int j);
|
||||
|
||||
//! 1D element access
|
||||
const _Tp& operator ()(int i) const;
|
||||
_Tp& operator ()(int i);
|
||||
|
||||
_Tp val[m*n]; //< matrix elements
|
||||
};
|
||||
|
||||
typedef Matx<float, 1, 2> Matx12f;
|
||||
typedef Matx<double, 1, 2> Matx12d;
|
||||
typedef Matx<float, 1, 3> Matx13f;
|
||||
typedef Matx<double, 1, 3> Matx13d;
|
||||
typedef Matx<float, 1, 4> Matx14f;
|
||||
typedef Matx<double, 1, 4> Matx14d;
|
||||
typedef Matx<float, 1, 6> Matx16f;
|
||||
typedef Matx<double, 1, 6> Matx16d;
|
||||
|
||||
typedef Matx<float, 2, 1> Matx21f;
|
||||
typedef Matx<double, 2, 1> Matx21d;
|
||||
typedef Matx<float, 3, 1> Matx31f;
|
||||
typedef Matx<double, 3, 1> Matx31d;
|
||||
typedef Matx<float, 4, 1> Matx41f;
|
||||
typedef Matx<double, 4, 1> Matx41d;
|
||||
typedef Matx<float, 6, 1> Matx61f;
|
||||
typedef Matx<double, 6, 1> Matx61d;
|
||||
|
||||
typedef Matx<float, 2, 2> Matx22f;
|
||||
typedef Matx<double, 2, 2> Matx22d;
|
||||
typedef Matx<float, 2, 3> Matx23f;
|
||||
typedef Matx<double, 2, 3> Matx23d;
|
||||
typedef Matx<float, 3, 2> Matx32f;
|
||||
typedef Matx<double, 3, 2> Matx32d;
|
||||
|
||||
typedef Matx<float, 3, 3> Matx33f;
|
||||
typedef Matx<double, 3, 3> Matx33d;
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx()
|
||||
{
|
||||
for (int i = 0; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0)
|
||||
{
|
||||
val[0] = v0;
|
||||
for (int i = 1; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 2, "Matx should have at least 2 elements.");
|
||||
val[0] = v0; val[1] = v1;
|
||||
for (int i = 2; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 3, "Matx should have at least 3 elements.");
|
||||
val[0] = v0; val[1] = v1; val[2] = v2;
|
||||
for (int i = 3; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 4, "Matx should have at least 4 elements.");
|
||||
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
|
||||
for (int i = 4; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 5, "Matx should have at least 5 elements.");
|
||||
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4;
|
||||
for (int i = 5; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 6, "Matx should have at least 6 elements.");
|
||||
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
|
||||
val[4] = v4; val[5] = v5;
|
||||
for (int i = 6; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 7, "Matx should have at least 7 elements.");
|
||||
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
|
||||
val[4] = v4; val[5] = v5; val[6] = v6;
|
||||
for (int i = 7; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 8, "Matx should have at least 8 elements.");
|
||||
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
|
||||
val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
|
||||
for (int i = 8; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8)
|
||||
{
|
||||
FBC_StaticAssert(channels >= 9, "Matx should have at least 9 elements.");
|
||||
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
|
||||
val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
|
||||
val[8] = v8;
|
||||
for (int i = 9; i < channels; i++) val[i] = _Tp(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n>::Matx(const _Tp* values)
|
||||
{
|
||||
for (int i = 0; i < channels; i++) val[i] = values[i];
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++) M.val[i] = alpha;
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n> Matx<_Tp, m, n>::zeros()
|
||||
{
|
||||
return all(0);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n> Matx<_Tp, m, n>::ones()
|
||||
{
|
||||
return all(1);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n> Matx<_Tp, m, n>::eye()
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < shortdim; i++)
|
||||
M(i, i) = 1;
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, n> Matx<_Tp, m, n>::diag(const typename Matx<_Tp, m, n>::diag_type& d)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < shortdim; i++)
|
||||
M(i, i) = d(i, 0);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
_Tp Matx<_Tp, m, n>::dot(const Matx<_Tp, m, n>& M) const
|
||||
{
|
||||
_Tp s = 0;
|
||||
for (int i = 0; i < channels; i++) s += val[i] * M.val[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
double Matx<_Tp, m, n>::ddot(const Matx<_Tp, m, n>& M) const
|
||||
{
|
||||
double s = 0;
|
||||
for (int i = 0; i < channels; i++) s += (double)val[i] * M.val[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> template<typename T2>
|
||||
inline Matx<_Tp, m, n>::operator Matx<T2, m, n>() const
|
||||
{
|
||||
Matx<T2, m, n> M;
|
||||
for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<T2>(val[i]);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> template<int m1, int n1> inline
|
||||
Matx<_Tp, m1, n1> Matx<_Tp, m, n>::reshape() const
|
||||
{
|
||||
FBC_StaticAssert(m1*n1 == m*n, "Input and destnarion matrices must have the same number of elements");
|
||||
return (const Matx<_Tp, m1, n1>&)*this;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n>
|
||||
template<int m1, int n1> inline
|
||||
Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const
|
||||
{
|
||||
FBC_Assert(0 <= i && i + m1 <= m && 0 <= j && j + n1 <= n);
|
||||
Matx<_Tp, m1, n1> s;
|
||||
for (int di = 0; di < m1; di++)
|
||||
for (int dj = 0; dj < n1; dj++)
|
||||
s(di, dj) = (*this)(i + di, j + dj);
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, 1, n> Matx<_Tp, m, n>::row(int i) const
|
||||
{
|
||||
FBC_Assert((unsigned)i < (unsigned)m);
|
||||
return Matx<_Tp, 1, n>(&val[i*n]);
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, m, 1> Matx<_Tp, m, n>::col(int j) const
|
||||
{
|
||||
FBC_Assert((unsigned)j < (unsigned)n);
|
||||
Matx<_Tp, m, 1> v;
|
||||
for (int i = 0; i < m; i++)
|
||||
v.val[i] = val[i*n + j];
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
typename Matx<_Tp, m, n>::diag_type Matx<_Tp, m, n>::diag() const
|
||||
{
|
||||
diag_type d;
|
||||
for (int i = 0; i < shortdim; i++)
|
||||
d.val[i] = val[i*n + i];
|
||||
return d;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
const _Tp& Matx<_Tp, m, n>::operator()(int i, int j) const
|
||||
{
|
||||
FBC_Assert((unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n);
|
||||
return this->val[i*n + j];
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
_Tp& Matx<_Tp, m, n>::operator ()(int i, int j)
|
||||
{
|
||||
FBC_Assert((unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n);
|
||||
return val[i*n + j];
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
const _Tp& Matx<_Tp, m, n>::operator ()(int i) const
|
||||
{
|
||||
FBC_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row");
|
||||
FBC_Assert((unsigned)i < (unsigned)(m + n - 1));
|
||||
return val[i];
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
_Tp& Matx<_Tp, m, n>::operator ()(int i)
|
||||
{
|
||||
FBC_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row");
|
||||
FBC_Assert((unsigned)i < (unsigned)(m + n - 1));
|
||||
return val[i];
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
double norm(const Matx<_Tp, m, n>& M)
|
||||
{
|
||||
return std::sqrt(normL2Sqr<_Tp, double>(M.val, m*n));
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
double norm(const Matx<_Tp, m, n>& M, int normType)
|
||||
{
|
||||
switch (normType) {
|
||||
case NORM_INF:
|
||||
return (double)normInf<_Tp, _Tp>(M.val, m*n);
|
||||
case NORM_L1:
|
||||
return (double)normL1<_Tp, _Tp>(M.val, m*n);
|
||||
case NORM_L2SQR:
|
||||
return (double)normL2Sqr<_Tp, _Tp>(M.val, m*n);
|
||||
default:
|
||||
case NORM_L2:
|
||||
return std::sqrt((double)normL2Sqr<_Tp, _Tp>(M.val, m*n));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////// Matx out-of-class operators ////////////////////////////////
|
||||
template<typename _Tp1, typename _Tp2, int m, int n> static inline
|
||||
Matx<_Tp1, m, n>& operator += (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b)
|
||||
{
|
||||
for (int i = 0; i < m*n; i++)
|
||||
a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp1, typename _Tp2, int m, int n> static inline
|
||||
Matx<_Tp1, m, n>& operator -= (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b)
|
||||
{
|
||||
for (int i = 0; i < m*n; i++)
|
||||
a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, int alpha)
|
||||
{
|
||||
for (int i = 0; i < m*n; i++)
|
||||
a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, float alpha)
|
||||
{
|
||||
for (int i = 0; i < m*n; i++)
|
||||
a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, double alpha)
|
||||
{
|
||||
for (int i = 0; i < m*n; i++)
|
||||
a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, int alpha)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
Matx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m*n; i++)
|
||||
M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n, int l> static inline
|
||||
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b)
|
||||
{
|
||||
Matx<_Tp, m, n> M;
|
||||
for (int i = 0; i < m; i++)
|
||||
for (int j = 0; j < n; j++)
|
||||
{
|
||||
_Tp s = 0;
|
||||
for (int k = 0; k < l; k++)
|
||||
s += a(i, k) * b(k, j);
|
||||
M.val[i*n + j] = s;
|
||||
}
|
||||
return M;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
bool operator == (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
|
||||
{
|
||||
for (int i = 0; i < m*n; i++)
|
||||
if (a.val[i] != b.val[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
bool operator != (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
///////////////////////////////////////// Vec ///////////////////////////////////
|
||||
// Template class for short numerical vectors, a partial case of Matx
|
||||
template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1> {
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
enum {
|
||||
channels = cn
|
||||
};
|
||||
|
||||
//! default constructor
|
||||
Vec();
|
||||
|
||||
Vec(_Tp v0); //!< 1-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor
|
||||
Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor
|
||||
explicit Vec(const _Tp* values);
|
||||
|
||||
Vec(const Vec<_Tp, cn>& v);
|
||||
|
||||
static Vec all(_Tp alpha);
|
||||
|
||||
//! per-element multiplication
|
||||
Vec mul(const Vec<_Tp, cn>& v) const;
|
||||
|
||||
//! conversion to another data type
|
||||
template<typename T2> operator Vec<T2, cn>() const;
|
||||
|
||||
/*! element access */
|
||||
const _Tp& operator [](int i) const;
|
||||
_Tp& operator[](int i);
|
||||
const _Tp& operator ()(int i) const;
|
||||
_Tp& operator ()(int i);
|
||||
};
|
||||
|
||||
typedef Vec<uchar, 2> Vec2b;
|
||||
typedef Vec<uchar, 3> Vec3b;
|
||||
typedef Vec<uchar, 4> Vec4b;
|
||||
|
||||
typedef Vec<short, 2> Vec2s;
|
||||
typedef Vec<short, 3> Vec3s;
|
||||
typedef Vec<short, 4> Vec4s;
|
||||
|
||||
typedef Vec<ushort, 2> Vec2w;
|
||||
typedef Vec<ushort, 3> Vec3w;
|
||||
typedef Vec<ushort, 4> Vec4w;
|
||||
|
||||
typedef Vec<int, 2> Vec2i;
|
||||
typedef Vec<int, 3> Vec3i;
|
||||
typedef Vec<int, 4> Vec4i;
|
||||
typedef Vec<int, 6> Vec6i;
|
||||
|
||||
typedef Vec<float, 2> Vec2f;
|
||||
typedef Vec<float, 3> Vec3f;
|
||||
typedef Vec<float, 4> Vec4f;
|
||||
typedef Vec<float, 6> Vec6f;
|
||||
|
||||
typedef Vec<double, 2> Vec2d;
|
||||
typedef Vec<double, 3> Vec3d;
|
||||
typedef Vec<double, 4> Vec4d;
|
||||
typedef Vec<double, 6> Vec6d;
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec() {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0)
|
||||
: Matx<_Tp, cn, 1>(v0) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1)
|
||||
: Matx<_Tp, cn, 1>(v0, v1) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2)
|
||||
: Matx<_Tp, cn, 1>(v0, v1, v2) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3)
|
||||
: Matx<_Tp, cn, 1>(v0, v1, v2, v3) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4)
|
||||
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5)
|
||||
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6)
|
||||
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7)
|
||||
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8)
|
||||
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(const _Tp* values)
|
||||
: Matx<_Tp, cn, 1>(values) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m)
|
||||
: Matx<_Tp, cn, 1>(m.val) {}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn> Vec<_Tp, cn>::all(_Tp alpha)
|
||||
{
|
||||
Vec v;
|
||||
for (int i = 0; i < cn; i++) v.val[i] = alpha;
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
Vec<_Tp, cn> Vec<_Tp, cn>::mul(const Vec<_Tp, cn>& v) const
|
||||
{
|
||||
Vec<_Tp, cn> w;
|
||||
for (int i = 0; i < cn; i++) w.val[i] = saturate_cast<_Tp>(this->val[i] * v.val[i]);
|
||||
return w;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> template<typename T2> inline
|
||||
Vec<_Tp, cn>::operator Vec<T2, cn>() const
|
||||
{
|
||||
Vec<T2, cn> v;
|
||||
for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<T2>(this->val[i]);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
const _Tp& Vec<_Tp, cn>::operator [](int i) const
|
||||
{
|
||||
FBC_Assert((unsigned)i < (unsigned)cn);
|
||||
return this->val[i];
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
_Tp& Vec<_Tp, cn>::operator [](int i)
|
||||
{
|
||||
FBC_Assert((unsigned)i < (unsigned)cn);
|
||||
return this->val[i];
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
const _Tp& Vec<_Tp, cn>::operator ()(int i) const
|
||||
{
|
||||
FBC_Assert((unsigned)i < (unsigned)cn);
|
||||
return this->val[i];
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> inline
|
||||
_Tp& Vec<_Tp, cn>::operator ()(int i)
|
||||
{
|
||||
FBC_Assert((unsigned)i < (unsigned)cn);
|
||||
return this->val[i];
|
||||
}
|
||||
|
||||
////////////////////////////// Vec out-of-class operators ////////////////////////////////
|
||||
template<typename _Tp1, typename _Tp2, int cn> static inline
|
||||
Vec<_Tp1, cn>& operator += (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b)
|
||||
{
|
||||
for (int i = 0; i < cn; i++)
|
||||
a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp1, typename _Tp2, int cn> static inline
|
||||
Vec<_Tp1, cn>& operator -= (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b)
|
||||
{
|
||||
for (int i = 0; i < cn; i++)
|
||||
a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator + (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, int alpha)
|
||||
{
|
||||
for (int i = 0; i < cn; i++)
|
||||
a[i] = saturate_cast<_Tp>(a[i] * alpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, float alpha)
|
||||
{
|
||||
for (int i = 0; i < cn; i++)
|
||||
a[i] = saturate_cast<_Tp>(a[i] * alpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, double alpha)
|
||||
{
|
||||
for (int i = 0; i < cn; i++)
|
||||
a[i] = saturate_cast<_Tp>(a[i] * alpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, int alpha)
|
||||
{
|
||||
double ialpha = 1. / alpha;
|
||||
for (int i = 0; i < cn; i++)
|
||||
a[i] = saturate_cast<_Tp>(a[i] * ialpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, float alpha)
|
||||
{
|
||||
float ialpha = 1.f / alpha;
|
||||
for (int i = 0; i < cn; i++)
|
||||
a[i] = saturate_cast<_Tp>(a[i] * ialpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, double alpha)
|
||||
{
|
||||
double ialpha = 1. / alpha;
|
||||
for (int i = 0; i < cn; i++)
|
||||
a[i] = saturate_cast<_Tp>(a[i] * ialpha);
|
||||
return a;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, int alpha)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator * (int alpha, const Vec<_Tp, cn>& a)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, float alpha)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator * (float alpha, const Vec<_Tp, cn>& a)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, double alpha)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator * (double alpha, const Vec<_Tp, cn>& a)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, int alpha)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
double ialpha = 1. / alpha;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * ialpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, float alpha)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
float ialpha = 1.f / alpha;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * ialpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, double alpha)
|
||||
{
|
||||
Vec<_Tp, cn> v;
|
||||
double ialpha = 1. / alpha;
|
||||
for (int i = 0; i < cn; i++)
|
||||
v.val[i] = saturate_cast<_Tp>(a.val[i] * ialpha);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename _Tp, int cn> static inline
|
||||
Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a)
|
||||
{
|
||||
Vec<_Tp, cn> t;
|
||||
for (int i = 0; i < cn; i++) t.val[i] = saturate_cast<_Tp>(-a.val[i]);
|
||||
return t;
|
||||
}
|
||||
|
||||
} //yt_tinycv
|
||||
#endif //FBC_CV_CORE_MATX_HPP_
|
||||
@@ -0,0 +1,470 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_RESIZE_HPP_
|
||||
#define FBC_CV_RESIZE_HPP_
|
||||
|
||||
/* reference: imgproc/include/opencv2/imgproc.hpp
|
||||
imgproc/src/imgwarp.cpp
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
#include "mat.hpp"
|
||||
#include "base.hpp"
|
||||
#include "saturate.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "imgproc.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
static const int MAX_ESIZE = 16;
|
||||
|
||||
// interpolation formulas and tables
|
||||
const int INTER_RESIZE_COEF_BITS = 11;
|
||||
const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
|
||||
|
||||
template<typename _Tp, int chs> static int resize_nearest(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);
|
||||
template<typename _Tp, int chs> static int resize_linear(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst);
|
||||
|
||||
// resize the image src down to or up to the specified size
|
||||
// support type: uchar/float
|
||||
template<typename _Tp, int chs>
|
||||
int resize(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, int interpolation = INTER_LINEAR)
|
||||
{
|
||||
FBC_Assert((interpolation >= 0) && (interpolation < 5));
|
||||
FBC_Assert((src.rows >= 4 && src.cols >= 4) && (dst.rows >= 4 && dst.cols >= 4));
|
||||
FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float
|
||||
|
||||
Size ssize = src.size();
|
||||
Size dsize = dst.size();
|
||||
|
||||
if (dsize == ssize) {
|
||||
// Source and destination are of same size. Use simple copy.
|
||||
src.copyTo(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (interpolation) {
|
||||
case 0: {
|
||||
resize_nearest(src, dst);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
resize_linear(src, dst);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename ST, typename DT> struct Cast
|
||||
{
|
||||
typedef ST type1;
|
||||
typedef DT rtype;
|
||||
|
||||
DT operator()(ST val) const { return saturate_cast<DT>(val); }
|
||||
};
|
||||
|
||||
template<typename ST, typename DT, int bits> struct FixedPtCast
|
||||
{
|
||||
typedef ST type1;
|
||||
typedef DT rtype;
|
||||
enum { SHIFT = bits, DELTA = 1 << (bits - 1) };
|
||||
|
||||
DT operator()(ST val) const { return saturate_cast<DT>((val + DELTA) >> SHIFT); }
|
||||
};
|
||||
|
||||
template<typename type>
|
||||
static type clip(type x, type a, type b)
|
||||
{
|
||||
return x >= a ? (x < b ? x : b - 1) : a;
|
||||
}
|
||||
|
||||
template<typename T, typename WT, typename AT>
|
||||
struct HResizeLinear
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef WT buf_type;
|
||||
typedef AT alpha_type;
|
||||
|
||||
void operator()(const T** src, WT** dst, int count,
|
||||
const int* xofs, const AT* alpha,
|
||||
int swidth, int dwidth, int cn, int xmin, int xmax, int ONE) const
|
||||
{
|
||||
int dx, k;
|
||||
int dx0 = 0;
|
||||
|
||||
for (k = 0; k <= count - 2; k++) {
|
||||
const T *S0 = src[k], *S1 = src[k + 1];
|
||||
WT *D0 = dst[k], *D1 = dst[k + 1];
|
||||
for (dx = dx0; dx < xmax; dx++) {
|
||||
int sx = xofs[dx];
|
||||
WT a0 = alpha[dx * 2], a1 = alpha[dx * 2 + 1];
|
||||
WT t0 = S0[sx] * a0 + S0[sx + cn] * a1;
|
||||
WT t1 = S1[sx] * a0 + S1[sx + cn] * a1;
|
||||
D0[dx] = t0; D1[dx] = t1;
|
||||
}
|
||||
|
||||
for (; dx < dwidth; dx++) {
|
||||
int sx = xofs[dx];
|
||||
D0[dx] = WT(S0[sx] * ONE); D1[dx] = WT(S1[sx] * ONE);
|
||||
}
|
||||
}
|
||||
|
||||
for (; k < count; k++) {
|
||||
const T *S = src[k];
|
||||
WT *D = dst[k];
|
||||
for (dx = 0; dx < xmax; dx++) {
|
||||
int sx = xofs[dx];
|
||||
D[dx] = S[sx] * alpha[dx * 2] + S[sx + cn] * alpha[dx * 2 + 1];
|
||||
}
|
||||
|
||||
for (; dx < dwidth; dx++) {
|
||||
D[dx] = WT(S[xofs[dx]] * ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename WT, typename AT, class CastOp>
|
||||
struct VResizeLinear
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef WT buf_type;
|
||||
typedef AT alpha_type;
|
||||
|
||||
void operator()(const WT** src, T* dst, const AT* beta, int width) const
|
||||
{
|
||||
WT b0 = beta[0], b1 = beta[1];
|
||||
const WT *S0 = src[0], *S1 = src[1];
|
||||
CastOp castOp;
|
||||
int x = 0;
|
||||
|
||||
for (; x <= width - 4; x += 4) {
|
||||
WT t0, t1;
|
||||
t0 = S0[x] * b0 + S1[x] * b1;
|
||||
t1 = S0[x + 1] * b0 + S1[x + 1] * b1;
|
||||
dst[x] = castOp(t0); dst[x + 1] = castOp(t1);
|
||||
t0 = S0[x + 2] * b0 + S1[x + 2] * b1;
|
||||
t1 = S0[x + 3] * b0 + S1[x + 3] * b1;
|
||||
dst[x + 2] = castOp(t0); dst[x + 3] = castOp(t1);
|
||||
}
|
||||
|
||||
for (; x < width; x++) {
|
||||
dst[x] = castOp(S0[x] * b0 + S1[x] * b1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct VResizeLinear<uchar, int, short, FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS * 2>>
|
||||
{
|
||||
typedef uchar value_type;
|
||||
typedef int buf_type;
|
||||
typedef short alpha_type;
|
||||
|
||||
void operator()(const buf_type** src, value_type* dst, const alpha_type* beta, int width) const
|
||||
{
|
||||
alpha_type b0 = beta[0], b1 = beta[1];
|
||||
const buf_type *S0 = src[0], *S1 = src[1];
|
||||
int x = 0;
|
||||
|
||||
for (; x <= width - 4; x += 4) {
|
||||
dst[x + 0] = uchar((((b0 * (S0[x + 0] >> 4)) >> 16) + ((b1 * (S1[x + 0] >> 4)) >> 16) + 2) >> 2);
|
||||
dst[x + 1] = uchar((((b0 * (S0[x + 1] >> 4)) >> 16) + ((b1 * (S1[x + 1] >> 4)) >> 16) + 2) >> 2);
|
||||
dst[x + 2] = uchar((((b0 * (S0[x + 2] >> 4)) >> 16) + ((b1 * (S1[x + 2] >> 4)) >> 16) + 2) >> 2);
|
||||
dst[x + 3] = uchar((((b0 * (S0[x + 3] >> 4)) >> 16) + ((b1 * (S1[x + 3] >> 4)) >> 16) + 2) >> 2);
|
||||
}
|
||||
|
||||
for (; x < width; x++) {
|
||||
dst[x] = uchar((((b0 * (S0[x] >> 4)) >> 16) + ((b1 * (S1[x] >> 4)) >> 16) + 2) >> 2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp, typename value_type, typename buf_type, typename alpha_type, int chs>
|
||||
static void resizeGeneric_Linear(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst,
|
||||
const int* xofs, const void* _alpha, const int* yofs, const void* _beta, int xmin, int xmax, int ksize, int ONE)
|
||||
{
|
||||
Size ssize = src.size(), dsize = dst.size();
|
||||
int dy, cn = src.channels;
|
||||
ssize.width *= cn;
|
||||
dsize.width *= cn;
|
||||
xmin *= cn;
|
||||
xmax *= cn;
|
||||
// image resize is a separable operation. In case of not too strong
|
||||
|
||||
Range range(0, dsize.height);
|
||||
|
||||
int bufstep = (int)alignSize(dsize.width, 16);
|
||||
AutoBuffer<buf_type> _buffer(bufstep*ksize);
|
||||
const value_type* srows[MAX_ESIZE] = { 0 };
|
||||
buf_type* rows[MAX_ESIZE] = { 0 };
|
||||
int prev_sy[MAX_ESIZE];
|
||||
|
||||
for (int k = 0; k < ksize; k++) {
|
||||
prev_sy[k] = -1;
|
||||
rows[k] = (buf_type*)_buffer + bufstep*k;
|
||||
}
|
||||
|
||||
const alpha_type* beta = (const alpha_type*)_beta + ksize * range.start;
|
||||
|
||||
HResizeLinear<value_type, buf_type, alpha_type> hresize;
|
||||
VResizeLinear<value_type, buf_type, alpha_type, FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS * 2>> vresize1;
|
||||
VResizeLinear<value_type, buf_type, alpha_type, Cast<float, float>> vresize2;
|
||||
|
||||
for (dy = range.start; dy < range.end; dy++, beta += ksize) {
|
||||
int sy0 = yofs[dy], k0 = ksize, k1 = 0, ksize2 = ksize / 2;
|
||||
|
||||
for (int k = 0; k < ksize; k++) {
|
||||
int sy = clip<int>(sy0 - ksize2 + 1 + k, 0, ssize.height);
|
||||
for (k1 = std::max(k1, k); k1 < ksize; k1++) {
|
||||
if (sy == prev_sy[k1]) { // if the sy-th row has been computed already, reuse it.
|
||||
if (k1 > k) {
|
||||
memcpy(rows[k], rows[k1], bufstep*sizeof(rows[0][0]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k1 == ksize) {
|
||||
k0 = std::min(k0, k); // remember the first row that needs to be computed
|
||||
}
|
||||
srows[k] = (const value_type*)src.ptr(sy);
|
||||
prev_sy[k] = sy;
|
||||
}
|
||||
|
||||
if (k0 < ksize) {
|
||||
hresize((const value_type**)(srows + k0), (buf_type**)(rows + k0), ksize - k0, xofs, (const alpha_type*)(_alpha),
|
||||
ssize.width, dsize.width, cn, xmin, xmax, ONE);
|
||||
}
|
||||
if (sizeof(_Tp) == 1) { // uchar
|
||||
vresize1((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);
|
||||
} else { // float
|
||||
vresize2((const buf_type**)rows, (value_type*)(dst.data + dst.step*dy), beta, dsize.width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
static int resize_nearest(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)
|
||||
{
|
||||
Size ssize = src.size();
|
||||
Size dsize = dst.size();
|
||||
|
||||
double fx = (double)dsize.width / ssize.width;
|
||||
double fy = (double)dsize.height / ssize.height;
|
||||
|
||||
AutoBuffer<int> _x_ofs(dsize.width);
|
||||
int* x_ofs = _x_ofs;
|
||||
int pix_size = (int)src.elemSize();
|
||||
int pix_size4 = (int)(pix_size / sizeof(int));
|
||||
double ifx = 1. / fx, ify = 1. / fy;
|
||||
|
||||
for (int x = 0; x < dsize.width; x++) {
|
||||
int sx = fbcFloor(x*ifx);
|
||||
x_ofs[x] = std::min(sx, ssize.width - 1)*pix_size;
|
||||
}
|
||||
|
||||
Range range(0, dsize.height);
|
||||
int x, y;
|
||||
|
||||
for (y = range.start; y < range.end; y++) {
|
||||
uchar* D = dst.data + dst.step*y;
|
||||
int sy = std::min(fbcFloor(y*ify), ssize.height - 1);
|
||||
const uchar* S = src.ptr(sy);
|
||||
|
||||
switch (pix_size) {
|
||||
case 1:
|
||||
for (x = 0; x <= dsize.width - 2; x += 2) {
|
||||
uchar t0 = S[x_ofs[x]];
|
||||
uchar t1 = S[x_ofs[x + 1]];
|
||||
D[x] = t0;
|
||||
D[x + 1] = t1;
|
||||
}
|
||||
|
||||
for (; x < dsize.width; x++) {
|
||||
D[x] = S[x_ofs[x]];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (x = 0; x < dsize.width; x++) {
|
||||
*(ushort*)(D + x * 2) = *(ushort*)(S + x_ofs[x]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (x = 0; x < dsize.width; x++, D += 3) {
|
||||
const uchar* _tS = S + x_ofs[x];
|
||||
D[0] = _tS[0]; D[1] = _tS[1]; D[2] = _tS[2];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (x = 0; x < dsize.width; x++) {
|
||||
*(int*)(D + x * 4) = *(int*)(S + x_ofs[x]);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
for (x = 0; x < dsize.width; x++, D += 6) {
|
||||
const ushort* _tS = (const ushort*)(S + x_ofs[x]);
|
||||
ushort* _tD = (ushort*)D;
|
||||
_tD[0] = _tS[0]; _tD[1] = _tS[1]; _tD[2] = _tS[2];
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
for (x = 0; x < dsize.width; x++, D += 8) {
|
||||
const int* _tS = (const int*)(S + x_ofs[x]);
|
||||
int* _tD = (int*)D;
|
||||
_tD[0] = _tS[0]; _tD[1] = _tS[1];
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
for (x = 0; x < dsize.width; x++, D += 12) {
|
||||
const int* _tS = (const int*)(S + x_ofs[x]);
|
||||
int* _tD = (int*)D;
|
||||
_tD[0] = _tS[0]; _tD[1] = _tS[1]; _tD[2] = _tS[2];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (x = 0; x < dsize.width; x++, D += pix_size) {
|
||||
const int* _tS = (const int*)(S + x_ofs[x]);
|
||||
int* _tD = (int*)D;
|
||||
for (int k = 0; k < pix_size4; k++)
|
||||
_tD[k] = _tS[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename _Tp, int chs>
|
||||
static int resize_linear(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst)
|
||||
{
|
||||
Size ssize = src.size();
|
||||
Size dsize = dst.size();
|
||||
|
||||
double inv_scale_x = (double)dsize.width / ssize.width;
|
||||
double inv_scale_y = (double)dsize.height / ssize.height;
|
||||
double scale_x = 1. / inv_scale_x, scale_y = 1. / inv_scale_y;
|
||||
|
||||
int iscale_x = saturate_cast<int>(scale_x);
|
||||
int iscale_y = saturate_cast<int>(scale_y);
|
||||
|
||||
bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON && std::abs(scale_y - iscale_y) < DBL_EPSILON;
|
||||
// in case of scale_x && scale_y is equal to 2
|
||||
// INTER_AREA (fast) also is equal to INTER_LINEAR
|
||||
// if (is_area_fast && iscale_x == 2 && iscale_y == 2) {
|
||||
// resize_area(src, dst);
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
int cn = dst.channels;
|
||||
int k, sx, sy, dx, dy;
|
||||
int xmin = 0, xmax = dsize.width, width = dsize.width*cn;
|
||||
bool fixpt = sizeof(_Tp) == 1 ? true : false;
|
||||
float fx, fy;
|
||||
int ksize = 2, ksize2;
|
||||
ksize2 = ksize / 2;
|
||||
|
||||
AutoBuffer<uchar> _buffer((width + dsize.height)*(sizeof(int) + sizeof(float)*ksize));
|
||||
int* xofs = (int*)(uchar*)_buffer;
|
||||
int* yofs = xofs + width;
|
||||
float* alpha = (float*)(yofs + dsize.height);
|
||||
short* ialpha = (short*)alpha;
|
||||
float* beta = alpha + width*ksize;
|
||||
short* ibeta = ialpha + width*ksize;
|
||||
float cbuf[MAX_ESIZE];
|
||||
|
||||
for (dx = 0; dx < dsize.width; dx++) {
|
||||
fx = (float)((dx + 0.5)*scale_x - 0.5);
|
||||
sx = fbcFloor(fx);
|
||||
fx -= sx;
|
||||
|
||||
if (sx < ksize2 - 1) {
|
||||
xmin = dx + 1;
|
||||
if (sx < 0) {
|
||||
fx = 0, sx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (sx + ksize2 >= ssize.width) {
|
||||
xmax = std::min(xmax, dx);
|
||||
if (sx >= ssize.width - 1) {
|
||||
fx = 0, sx = ssize.width - 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (k = 0, sx *= cn; k < cn; k++) {
|
||||
xofs[dx*cn + k] = sx + k;
|
||||
}
|
||||
|
||||
cbuf[0] = 1.f - fx;
|
||||
cbuf[1] = fx;
|
||||
|
||||
if (fixpt) {
|
||||
for (k = 0; k < ksize; k++) {
|
||||
ialpha[dx*cn*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);
|
||||
}
|
||||
for (; k < cn*ksize; k++) {
|
||||
ialpha[dx*cn*ksize + k] = ialpha[dx*cn*ksize + k - ksize];
|
||||
}
|
||||
} else {
|
||||
for (k = 0; k < ksize; k++) {
|
||||
alpha[dx*cn*ksize + k] = cbuf[k];
|
||||
}
|
||||
for (; k < cn*ksize; k++) {
|
||||
alpha[dx*cn*ksize + k] = alpha[dx*cn*ksize + k - ksize];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (dy = 0; dy < dsize.height; dy++) {
|
||||
fy = (float)((dy + 0.5)*scale_y - 0.5);
|
||||
sy = fbcFloor(fy);
|
||||
fy -= sy;
|
||||
|
||||
yofs[dy] = sy;
|
||||
cbuf[0] = 1.f - fy;
|
||||
cbuf[1] = fy;
|
||||
|
||||
if (fixpt) {
|
||||
for (k = 0; k < ksize; k++) {
|
||||
ibeta[dy*ksize + k] = saturate_cast<short>(cbuf[k] * INTER_RESIZE_COEF_SCALE);
|
||||
}
|
||||
} else {
|
||||
for (k = 0; k < ksize; k++) {
|
||||
beta[dy*ksize + k] = cbuf[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sizeof(_Tp) == 1) { // uchar
|
||||
typedef uchar value_type; // HResizeLinear/VResizeLinear
|
||||
typedef int buf_type;
|
||||
typedef short alpha_type;
|
||||
int ONE = INTER_RESIZE_COEF_SCALE;
|
||||
|
||||
resizeGeneric_Linear<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,
|
||||
xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize, ONE);
|
||||
} else if (sizeof(_Tp) == 4) { // float
|
||||
typedef float value_type; // HResizeLinear/VResizeLinear
|
||||
typedef float buf_type;
|
||||
typedef float alpha_type;
|
||||
int ONE = 1;
|
||||
|
||||
resizeGeneric_Linear<_Tp, value_type, buf_type, alpha_type, chs>(src, dst,
|
||||
xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs, fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize, ONE);
|
||||
} else {
|
||||
fprintf(stderr, "not support type\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace yt_tinycv
|
||||
|
||||
#endif // FBC_CV_RESIZE_HPP_
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_SATURATE_HPP_
|
||||
#define FBC_CV_CORE_SATURATE_HPP_
|
||||
|
||||
// reference: include/opencv2/core/saturate.hpp
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
|
||||
#include "fbcdef.hpp"
|
||||
#include "interface.hpp"
|
||||
#include "fast_math.hpp"
|
||||
|
||||
namespace yt_tinycv
|
||||
{
|
||||
template<typename _Tp> static inline _Tp saturate_cast(uchar v) { return _Tp(v); }
|
||||
template<typename _Tp> static inline _Tp saturate_cast(schar v) { return _Tp(v); }
|
||||
template<typename _Tp> static inline _Tp saturate_cast(ushort v) { return _Tp(v); }
|
||||
template<typename _Tp> static inline _Tp saturate_cast(short v) { return _Tp(v); }
|
||||
template<typename _Tp> static inline _Tp saturate_cast(unsigned int v) { return _Tp(v); }
|
||||
template<typename _Tp> static inline _Tp saturate_cast(int v) { return _Tp(v); }
|
||||
template<typename _Tp> static inline _Tp saturate_cast(float v) { return _Tp(v); }
|
||||
template<typename _Tp> static inline _Tp saturate_cast(double v) { return _Tp(v); }
|
||||
|
||||
template<> inline uchar saturate_cast<uchar>(schar v) { return (uchar)std::max((int)v, 0); }
|
||||
template<> inline uchar saturate_cast<uchar>(ushort v) { return (uchar)std::min((unsigned)v, (unsigned)UCHAR_MAX); }
|
||||
template<> inline uchar saturate_cast<uchar>(int v) { return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); }
|
||||
template<> inline uchar saturate_cast<uchar>(short v) { return saturate_cast<uchar>((int)v); }
|
||||
template<> inline uchar saturate_cast<uchar>(unsigned int v) { return (uchar)std::min(v, (unsigned)UCHAR_MAX); }
|
||||
template<> inline uchar saturate_cast<uchar>(float v) { int iv = fbcRound(v); return saturate_cast<uchar>(iv); }
|
||||
template<> inline uchar saturate_cast<uchar>(double v) { int iv = fbcRound(v); return saturate_cast<uchar>(iv); }
|
||||
|
||||
template<> inline schar saturate_cast<schar>(uchar v) { return (schar)std::min((int)v, SCHAR_MAX); }
|
||||
template<> inline schar saturate_cast<schar>(ushort v) { return (schar)std::min((unsigned)v, (unsigned)SCHAR_MAX); }
|
||||
template<> inline schar saturate_cast<schar>(int v) { return (schar)((unsigned)(v-SCHAR_MIN) <= (unsigned)UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN); }
|
||||
template<> inline schar saturate_cast<schar>(short v) { return saturate_cast<schar>((int)v); }
|
||||
template<> inline schar saturate_cast<schar>(unsigned v) { return (schar)std::min(v, (unsigned)SCHAR_MAX); }
|
||||
template<> inline schar saturate_cast<schar>(float v) { int iv = fbcRound(v); return saturate_cast<schar>(iv); }
|
||||
template<> inline schar saturate_cast<schar>(double v) { int iv = fbcRound(v); return saturate_cast<schar>(iv); }
|
||||
|
||||
template<> inline ushort saturate_cast<ushort>(schar v) { return (ushort)std::max((int)v, 0); }
|
||||
template<> inline ushort saturate_cast<ushort>(short v) { return (ushort)std::max((int)v, 0); }
|
||||
template<> inline ushort saturate_cast<ushort>(int v) { return (ushort)((unsigned)v <= (unsigned)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); }
|
||||
template<> inline ushort saturate_cast<ushort>(unsigned v) { return (ushort)std::min(v, (unsigned)USHRT_MAX); }
|
||||
template<> inline ushort saturate_cast<ushort>(float v) { int iv = fbcRound(v); return saturate_cast<ushort>(iv); }
|
||||
template<> inline ushort saturate_cast<ushort>(double v) { int iv = fbcRound(v); return saturate_cast<ushort>(iv); }
|
||||
|
||||
template<> inline short saturate_cast<short>(ushort v) { return (short)std::min((int)v, SHRT_MAX); }
|
||||
template<> inline short saturate_cast<short>(int v) { return (short)((unsigned)(v - SHRT_MIN) <= (unsigned)USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN); }
|
||||
template<> inline short saturate_cast<short>(unsigned v) { return (short)std::min(v, (unsigned)SHRT_MAX); }
|
||||
template<> inline short saturate_cast<short>(float v) { int iv = fbcRound(v); return saturate_cast<short>(iv); }
|
||||
template<> inline short saturate_cast<short>(double v) { int iv = fbcRound(v); return saturate_cast<short>(iv); }
|
||||
|
||||
template<> inline int saturate_cast<int>(float v) { return fbcRound(v); }
|
||||
template<> inline int saturate_cast<int>(double v) { return fbcRound(v); }
|
||||
|
||||
template<> inline unsigned saturate_cast<unsigned>(float v) { return fbcRound(v); }
|
||||
template<> inline unsigned saturate_cast<unsigned>(double v) { return fbcRound(v); }
|
||||
|
||||
} // yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_SATURATE_HPP_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,189 @@
|
||||
// fbc_cv is free software and uses the same licence as OpenCV
|
||||
// Email: fengbingchun@163.com
|
||||
|
||||
#ifndef FBC_CV_CORE_UTILITY_HPP_
|
||||
#define FBC_CV_CORE_UTILITY_HPP_
|
||||
|
||||
// reference: include/opencv2/core/utility.hpp
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error utility.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
#include "fbcdef.hpp"
|
||||
#include "base.hpp"
|
||||
|
||||
namespace yt_tinycv {
|
||||
|
||||
// The function returns the aligned pointer of the same type as the input pointer
|
||||
template<typename _Tp> static inline _Tp* alignPtr(_Tp* ptr, int n = (int)sizeof(_Tp))
|
||||
{
|
||||
return (_Tp*)(((size_t)ptr + n - 1) & -n);
|
||||
}
|
||||
|
||||
// The function returns the minimum number that is greater or equal to sz and is divisible by n
|
||||
static inline size_t alignSize(size_t sz, int n)
|
||||
{
|
||||
FBC_Assert((n & (n - 1)) == 0); // n is a power of 2
|
||||
return (sz + n - 1) & -n;
|
||||
}
|
||||
|
||||
// Automatically Allocated Buffer Class
|
||||
// The class is used for temporary buffers in functions and methods.
|
||||
template<typename _Tp, size_t fixed_size = 1024 / sizeof(_Tp) + 8> class AutoBuffer {
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
|
||||
// the default constructor
|
||||
AutoBuffer();
|
||||
// constructor taking the real buffer size
|
||||
AutoBuffer(size_t _size);
|
||||
|
||||
// the copy constructor
|
||||
AutoBuffer(const AutoBuffer<_Tp, fixed_size>& buf);
|
||||
// the assignment operator
|
||||
AutoBuffer<_Tp, fixed_size>& operator = (const AutoBuffer<_Tp, fixed_size>& buf);
|
||||
|
||||
// destructor. calls deallocate()
|
||||
~AutoBuffer();
|
||||
|
||||
// allocates the new buffer of size _size. if the _size is small enough, stack-allocated buffer is used
|
||||
void allocate(size_t _size);
|
||||
// deallocates the buffer if it was dynamically allocated
|
||||
void deallocate();
|
||||
// resizes the buffer and preserves the content
|
||||
void resize(size_t _size);
|
||||
// returns the current buffer size
|
||||
size_t size() const;
|
||||
// returns pointer to the real buffer, stack-allocated or head-allocated
|
||||
operator _Tp* ();
|
||||
// returns read-only pointer to the real buffer, stack-allocated or head-allocated
|
||||
operator const _Tp* () const;
|
||||
|
||||
protected:
|
||||
// pointer to the real buffer, can point to buf if the buffer is small enough
|
||||
_Tp* ptr;
|
||||
// size of the real buffer
|
||||
size_t sz;
|
||||
//! pre-allocated buffer. At least 1 element to confirm C++ standard reqirements
|
||||
_Tp buf[(fixed_size > 0) ? fixed_size : 1];
|
||||
};
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::AutoBuffer()
|
||||
{
|
||||
ptr = buf;
|
||||
sz = fixed_size;
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size)
|
||||
{
|
||||
ptr = buf;
|
||||
sz = fixed_size;
|
||||
allocate(_size);
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::AutoBuffer(const AutoBuffer<_Tp, fixed_size>& abuf)
|
||||
{
|
||||
ptr = buf;
|
||||
sz = fixed_size;
|
||||
allocate(abuf.size());
|
||||
for (size_t i = 0; i < sz; i++) {
|
||||
ptr[i] = abuf.ptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>&
|
||||
AutoBuffer<_Tp, fixed_size>::operator = (const AutoBuffer<_Tp, fixed_size>& abuf)
|
||||
{
|
||||
if (this != &abuf) {
|
||||
deallocate();
|
||||
allocate(abuf.size());
|
||||
for (size_t i = 0; i < sz; i++) {
|
||||
ptr[i] = abuf.ptr[i];
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::~AutoBuffer()
|
||||
{
|
||||
deallocate();
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline void
|
||||
AutoBuffer<_Tp, fixed_size>::allocate(size_t _size)
|
||||
{
|
||||
if (_size <= sz) {
|
||||
sz = _size;
|
||||
return;
|
||||
}
|
||||
|
||||
deallocate();
|
||||
if (_size > fixed_size) {
|
||||
ptr = new _Tp[_size];
|
||||
sz = _size;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline void
|
||||
AutoBuffer<_Tp, fixed_size>::deallocate()
|
||||
{
|
||||
if (ptr != buf) {
|
||||
delete[] ptr;
|
||||
ptr = buf;
|
||||
sz = fixed_size;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline void
|
||||
AutoBuffer<_Tp, fixed_size>::resize(size_t _size)
|
||||
{
|
||||
if (_size <= sz) {
|
||||
sz = _size;
|
||||
return;
|
||||
}
|
||||
size_t i, prevsize = sz, minsize = MIN(prevsize, _size);
|
||||
_Tp* prevptr = ptr;
|
||||
|
||||
ptr = _size > fixed_size ? new _Tp[_size] : buf;
|
||||
sz = _size;
|
||||
|
||||
if (ptr != prevptr) {
|
||||
for (i = 0; i < minsize; i++) {
|
||||
ptr[i] = prevptr[i];
|
||||
}
|
||||
}
|
||||
for (i = prevsize; i < _size; i++) {
|
||||
ptr[i] = _Tp();
|
||||
}
|
||||
|
||||
if (prevptr != buf) {
|
||||
delete[] prevptr;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline size_t
|
||||
AutoBuffer<_Tp, fixed_size>::size() const
|
||||
{
|
||||
return sz;
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::operator _Tp* ()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
} // yt_tinycv
|
||||
|
||||
#endif // FBC_CV_CORE_UTILITY_HPP_
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>YTCv</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.tencent.youtu.cv</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>YTCv</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>v0.0.7-2-g3bdc755</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>v0.0.7-2-g3bdc755</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
TencentCloudHuiyanSDKFace_framework/Libs/YTCv.framework/YTCv
Normal file
BIN
TencentCloudHuiyanSDKFace_framework/Libs/YTCv.framework/YTCv
Normal file
Binary file not shown.
Reference in New Issue
Block a user