vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
static void bilateralFilterProcess(uchar* dst_data, size_t dst_step, uchar* pad_data, size_t pad_step,
|
||||
int width, int height, int cn, int radius, int maxk,
|
||||
int* space_ofs, float *space_weight, float *color_weight)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for( i = 0; i < height; i++ )
|
||||
{
|
||||
const uchar* sptr = pad_data + (i + radius) * pad_step + radius * cn;
|
||||
uchar* dptr = dst_data + i * dst_step;
|
||||
|
||||
if( cn == 1 )
|
||||
{
|
||||
std::vector<float> buf(width + width, 0.0);
|
||||
float *sum = &buf[0];
|
||||
float *wsum = sum + width;
|
||||
k = 0;
|
||||
for(; k <= maxk-4; k+=4)
|
||||
{
|
||||
const uchar* ksptr0 = sptr + space_ofs[k];
|
||||
const uchar* ksptr1 = sptr + space_ofs[k+1];
|
||||
const uchar* ksptr2 = sptr + space_ofs[k+2];
|
||||
const uchar* ksptr3 = sptr + space_ofs[k+3];
|
||||
j = 0;
|
||||
for (; j < width; j++)
|
||||
{
|
||||
int rval = sptr[j];
|
||||
|
||||
int val = ksptr0[j];
|
||||
float w = space_weight[k] * color_weight[std::abs(val - rval)];
|
||||
wsum[j] += w;
|
||||
sum[j] += val * w;
|
||||
|
||||
val = ksptr1[j];
|
||||
w = space_weight[k+1] * color_weight[std::abs(val - rval)];
|
||||
wsum[j] += w;
|
||||
sum[j] += val * w;
|
||||
|
||||
val = ksptr2[j];
|
||||
w = space_weight[k+2] * color_weight[std::abs(val - rval)];
|
||||
wsum[j] += w;
|
||||
sum[j] += val * w;
|
||||
|
||||
val = ksptr3[j];
|
||||
w = space_weight[k+3] * color_weight[std::abs(val - rval)];
|
||||
wsum[j] += w;
|
||||
sum[j] += val * w;
|
||||
}
|
||||
}
|
||||
for(; k < maxk; k++)
|
||||
{
|
||||
const uchar* ksptr = sptr + space_ofs[k];
|
||||
j = 0;
|
||||
for (; j < width; j++)
|
||||
{
|
||||
int val = ksptr[j];
|
||||
float w = space_weight[k] * color_weight[std::abs(val - sptr[j])];
|
||||
wsum[j] += w;
|
||||
sum[j] += val * w;
|
||||
}
|
||||
}
|
||||
j = 0;
|
||||
for (; j < width; j++)
|
||||
{
|
||||
// overflow is not possible here => there is no need to use cv::saturate_cast
|
||||
ndsrvp_assert(fabs(wsum[j]) > 0);
|
||||
dptr[j] = (uchar)(sum[j] / wsum[j] + 0.5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ndsrvp_assert( cn == 3 );
|
||||
std::vector<float> buf(width * 3 + width);
|
||||
float *sum_b = &buf[0];
|
||||
float *sum_g = sum_b + width;
|
||||
float *sum_r = sum_g + width;
|
||||
float *wsum = sum_r + width;
|
||||
k = 0;
|
||||
for(; k <= maxk-4; k+=4)
|
||||
{
|
||||
const uchar* ksptr0 = sptr + space_ofs[k];
|
||||
const uchar* ksptr1 = sptr + space_ofs[k+1];
|
||||
const uchar* ksptr2 = sptr + space_ofs[k+2];
|
||||
const uchar* ksptr3 = sptr + space_ofs[k+3];
|
||||
const uchar* rsptr = sptr;
|
||||
j = 0;
|
||||
for(; j < width; j++, rsptr += 3, ksptr0 += 3, ksptr1 += 3, ksptr2 += 3, ksptr3 += 3)
|
||||
{
|
||||
int rb = rsptr[0], rg = rsptr[1], rr = rsptr[2];
|
||||
|
||||
int b = ksptr0[0], g = ksptr0[1], r = ksptr0[2];
|
||||
float w = space_weight[k] * color_weight[std::abs(b - rb) + std::abs(g - rg) + std::abs(r - rr)];
|
||||
wsum[j] += w;
|
||||
sum_b[j] += b * w; sum_g[j] += g * w; sum_r[j] += r * w;
|
||||
|
||||
b = ksptr1[0]; g = ksptr1[1]; r = ksptr1[2];
|
||||
w = space_weight[k+1] * color_weight[std::abs(b - rb) + std::abs(g - rg) + std::abs(r - rr)];
|
||||
wsum[j] += w;
|
||||
sum_b[j] += b * w; sum_g[j] += g * w; sum_r[j] += r * w;
|
||||
|
||||
b = ksptr2[0]; g = ksptr2[1]; r = ksptr2[2];
|
||||
w = space_weight[k+2] * color_weight[std::abs(b - rb) + std::abs(g - rg) + std::abs(r - rr)];
|
||||
wsum[j] += w;
|
||||
sum_b[j] += b * w; sum_g[j] += g * w; sum_r[j] += r * w;
|
||||
|
||||
b = ksptr3[0]; g = ksptr3[1]; r = ksptr3[2];
|
||||
w = space_weight[k+3] * color_weight[std::abs(b - rb) + std::abs(g - rg) + std::abs(r - rr)];
|
||||
wsum[j] += w;
|
||||
sum_b[j] += b * w; sum_g[j] += g * w; sum_r[j] += r * w;
|
||||
}
|
||||
}
|
||||
for(; k < maxk; k++)
|
||||
{
|
||||
const uchar* ksptr = sptr + space_ofs[k];
|
||||
const uchar* rsptr = sptr;
|
||||
j = 0;
|
||||
for(; j < width; j++, ksptr += 3, rsptr += 3)
|
||||
{
|
||||
int b = ksptr[0], g = ksptr[1], r = ksptr[2];
|
||||
float w = space_weight[k] * color_weight[std::abs(b - rsptr[0]) + std::abs(g - rsptr[1]) + std::abs(r - rsptr[2])];
|
||||
wsum[j] += w;
|
||||
sum_b[j] += b * w; sum_g[j] += g * w; sum_r[j] += r * w;
|
||||
}
|
||||
}
|
||||
j = 0;
|
||||
for(; j < width; j++)
|
||||
{
|
||||
ndsrvp_assert(fabs(wsum[j]) > 0);
|
||||
wsum[j] = 1.f / wsum[j];
|
||||
*(dptr++) = (uchar)(sum_b[j] * wsum[j] + 0.5);
|
||||
*(dptr++) = (uchar)(sum_g[j] * wsum[j] + 0.5);
|
||||
*(dptr++) = (uchar)(sum_r[j] * wsum[j] + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int bilateralFilter(const uchar* src_data, size_t src_step,
|
||||
uchar* dst_data, size_t dst_step, int width, int height, int depth,
|
||||
int cn, int d, double sigma_color, double sigma_space, int border_type)
|
||||
{
|
||||
if( depth != CV_8U || !(cn == 1 || cn == 3) || src_data == dst_data)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
int i, j, maxk, radius;
|
||||
|
||||
constexpr double eps = 1e-6;
|
||||
if( sigma_color <= eps || sigma_space <= eps )
|
||||
{
|
||||
const size_t row_size = width * cn * sizeof(uchar);
|
||||
for (int y = 0; y < height; y++)
|
||||
memcpy(dst_data + y * dst_step, src_data + y * src_step, row_size);
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
double gauss_color_coeff = -0.5/(sigma_color * sigma_color);
|
||||
double gauss_space_coeff = -0.5/(sigma_space * sigma_space);
|
||||
|
||||
if( d <= 0 )
|
||||
radius = (int)(sigma_space * 1.5 + 0.5);
|
||||
else
|
||||
radius = d / 2;
|
||||
|
||||
radius = MAX(radius, 1);
|
||||
d = radius * 2 + 1;
|
||||
|
||||
// no enough submatrix info
|
||||
// fetch original image data
|
||||
const uchar *ogn_data = src_data;
|
||||
int ogn_step = src_step;
|
||||
|
||||
// ROI fully used in the computation
|
||||
int cal_width = width + d - 1;
|
||||
int cal_height = height + d - 1;
|
||||
int cal_x = 0 - radius; // negative if left border exceeded
|
||||
int cal_y = 0 - radius; // negative if top border exceeded
|
||||
|
||||
// calculate source border
|
||||
std::vector<uchar> padding;
|
||||
padding.resize(cal_width * cal_height * cn);
|
||||
uchar* pad_data = &padding[0];
|
||||
int pad_step = cal_width * cn;
|
||||
|
||||
uchar* pad_ptr;
|
||||
const uchar* ogn_ptr;
|
||||
std::vector<uchar> vec_zeros(cn, 0);
|
||||
for(i = 0; i < cal_height; i++)
|
||||
{
|
||||
int y = borderInterpolate(i + cal_y, height, border_type);
|
||||
if(y < 0) {
|
||||
memset(pad_data + i * pad_step, 0, cn * cal_width);
|
||||
continue;
|
||||
}
|
||||
|
||||
// left border
|
||||
j = 0;
|
||||
for(; j + cal_x < 0; j++)
|
||||
{
|
||||
int x = borderInterpolate(j + cal_x, width, border_type);
|
||||
if(x < 0) // border constant return value -1
|
||||
ogn_ptr = &vec_zeros[0];
|
||||
else
|
||||
ogn_ptr = ogn_data + y * ogn_step + x * cn;
|
||||
pad_ptr = pad_data + i * pad_step + j * cn;
|
||||
memcpy(pad_ptr, ogn_ptr, cn);
|
||||
}
|
||||
|
||||
// center
|
||||
int rborder = MIN(cal_width, width - cal_x);
|
||||
ogn_ptr = ogn_data + y * ogn_step + (j + cal_x) * cn;
|
||||
pad_ptr = pad_data + i * pad_step + j * cn;
|
||||
memcpy(pad_ptr, ogn_ptr, cn * (rborder - j));
|
||||
|
||||
// right border
|
||||
j = rborder;
|
||||
for(; j < cal_width; j++)
|
||||
{
|
||||
int x = borderInterpolate(j + cal_x, width, border_type);
|
||||
if(x < 0) // border constant return value -1
|
||||
ogn_ptr = &vec_zeros[0];
|
||||
else
|
||||
ogn_ptr = ogn_data + y * ogn_step + x * cn;
|
||||
pad_ptr = pad_data + i * pad_step + j * cn;
|
||||
memcpy(pad_ptr, ogn_ptr, cn);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float> _color_weight(cn * 256);
|
||||
std::vector<float> _space_weight(d * d);
|
||||
std::vector<int> _space_ofs(d * d);
|
||||
float* color_weight = &_color_weight[0];
|
||||
float* space_weight = &_space_weight[0];
|
||||
int* space_ofs = &_space_ofs[0];
|
||||
|
||||
// initialize color-related bilateral filter coefficients
|
||||
|
||||
for( i = 0; i < 256 * cn; i++ )
|
||||
color_weight[i] = (float)std::exp(i * i * gauss_color_coeff);
|
||||
|
||||
// initialize space-related bilateral filter coefficients
|
||||
for( i = -radius, maxk = 0; i <= radius; i++ )
|
||||
{
|
||||
j = -radius;
|
||||
|
||||
for( ; j <= radius; j++ )
|
||||
{
|
||||
double r = std::sqrt((double)i * i + (double)j * j);
|
||||
if( r > radius )
|
||||
continue;
|
||||
space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff);
|
||||
space_ofs[maxk++] = (int)(i * pad_step + j * cn);
|
||||
}
|
||||
}
|
||||
|
||||
bilateralFilterProcess(dst_data, dst_step, pad_data, pad_step, width, height, cn, radius, maxk, space_ofs, space_weight, color_weight);
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,112 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
// fastMalloc
|
||||
|
||||
// [0][1][2][3][4][5][6][7][8][9]
|
||||
// ^udata
|
||||
// ^adata
|
||||
// ^adata[-1] == udata
|
||||
|
||||
void* fastMalloc(size_t size)
|
||||
{
|
||||
uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);
|
||||
if(!udata)
|
||||
ndsrvp_error(Error::StsNoMem, "fastMalloc(): Not enough memory");
|
||||
uchar** adata = (uchar**)align((size_t)((uchar**)udata + 1), CV_MALLOC_ALIGN);
|
||||
adata[-1] = udata;
|
||||
return adata;
|
||||
}
|
||||
|
||||
void fastFree(void* ptr)
|
||||
{
|
||||
if(ptr)
|
||||
{
|
||||
uchar* udata = ((uchar**)ptr)[-1];
|
||||
if(!(udata < (uchar*)ptr && ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*) + CV_MALLOC_ALIGN)))
|
||||
ndsrvp_error(Error::StsBadArg, "fastFree(): Invalid memory block");
|
||||
free(udata);
|
||||
}
|
||||
}
|
||||
|
||||
// borderInterpolate
|
||||
|
||||
int borderInterpolate(int p, int len, int borderType)
|
||||
{
|
||||
if( (unsigned)p < (unsigned)len )
|
||||
;
|
||||
else if( borderType == CV_HAL_BORDER_REPLICATE )
|
||||
p = p < 0 ? 0 : len - 1;
|
||||
else if( borderType == CV_HAL_BORDER_REFLECT || borderType == CV_HAL_BORDER_REFLECT_101 )
|
||||
{
|
||||
int delta = borderType == CV_HAL_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 == CV_HAL_BORDER_WRAP )
|
||||
{
|
||||
ndsrvp_assert(len > 0);
|
||||
if( p < 0 )
|
||||
p -= ((p - len + 1) / len) * len;
|
||||
if( p >= len )
|
||||
p %= len;
|
||||
}
|
||||
else if( borderType == CV_HAL_BORDER_CONSTANT )
|
||||
p = -1;
|
||||
else
|
||||
ndsrvp_error(Error::StsBadArg, "borderInterpolate(): Unknown/unsupported border type");
|
||||
return p;
|
||||
}
|
||||
|
||||
int16x4_t borderInterpolate_vector(int16x4_t vp, short len, int borderType)
|
||||
{
|
||||
int16x4_t vzero = (int16x4_t){0, 0, 0, 0};
|
||||
int16x4_t vone = (int16x4_t){1, 1, 1, 1};
|
||||
int16x4_t vlen = (int16x4_t){len, len, len, len};
|
||||
if(borderType == CV_HAL_BORDER_REPLICATE)
|
||||
vp = (int16x4_t)__nds__bpick(0, __nds__bpick((long)(vlen - 1), (long)vp, (long)(vp >= vlen)), (long)(vp < 0));
|
||||
else if(borderType == CV_HAL_BORDER_REFLECT || borderType == CV_HAL_BORDER_REFLECT_101)
|
||||
{
|
||||
int16x4_t vdelta = (borderType == CV_HAL_BORDER_REFLECT_101) ? vone : vzero;
|
||||
if(len == 1)
|
||||
return vzero;
|
||||
do
|
||||
{
|
||||
int16x4_t vneg = -vp - 1 + vdelta;
|
||||
int16x4_t vpos = vlen - 1 - (vp - vlen) - vdelta;
|
||||
vp = (int16x4_t)__nds__bpick((long)vneg, __nds__bpick((long)vpos, (long)vp, (long)(vp >= vlen)), (long)(vp < 0));
|
||||
}
|
||||
while( (long)(vp >= vlen) || (long)(vp < 0) );
|
||||
}
|
||||
else if(borderType == CV_HAL_BORDER_WRAP)
|
||||
{
|
||||
ndsrvp_assert(len > 0);
|
||||
int16x4_t vneg = vp - ((vp - vlen + 1) / vlen) * vlen;
|
||||
int16x4_t vpos = vp % vlen;
|
||||
vp = (int16x4_t)__nds__bpick((long)vneg, __nds__bpick((long)vpos, (long)vp, (long)(vp >= vlen)), (long)(vp < 0));
|
||||
}
|
||||
else if(borderType == CV_HAL_BORDER_CONSTANT)
|
||||
vp = (int16x4_t)__nds__bpick((long)-vone, (long)vp, (long)(vp < 0 || vp >= vlen));
|
||||
else
|
||||
ndsrvp_error(Error::StsBadArg, "borderInterpolate_vector(): Unknown/unsupported border type");
|
||||
return vp;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,268 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#ifndef OPENCV_NDSRVP_CVUTILS_HPP
|
||||
#define OPENCV_NDSRVP_CVUTILS_HPP
|
||||
|
||||
#include <nds_intrinsic.h>
|
||||
|
||||
#include "opencv2/core/hal/interface.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <climits>
|
||||
#include <algorithm>
|
||||
|
||||
// misc functions that not exposed to public interface
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
void* fastMalloc(size_t size);
|
||||
void fastFree(void* ptr);
|
||||
int borderInterpolate(int p, int len, int borderType);
|
||||
int16x4_t borderInterpolate_vector(int16x4_t vp, short len, int borderType);
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) ((a) > (b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#define CV_MAT_CN_MASK ((CV_CN_MAX - 1) << CV_CN_SHIFT)
|
||||
#define CV_MAT_CN(flags) ((((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1)
|
||||
|
||||
#define CV_ELEM_SIZE1(type) ((0x28442211 >> CV_MAT_DEPTH(type)*4) & 15)
|
||||
#define CV_ELEM_SIZE(type) (CV_MAT_CN(type)*CV_ELEM_SIZE1(type))
|
||||
|
||||
#define CV_MALLOC_ALIGN 64
|
||||
|
||||
inline size_t getElemSize(int type) { return (size_t)CV_ELEM_SIZE(type); }
|
||||
|
||||
// error codes
|
||||
|
||||
enum Error{
|
||||
StsNoMem = -4,
|
||||
StsBadArg = -5,
|
||||
StsAssert = -215
|
||||
};
|
||||
|
||||
// output error
|
||||
|
||||
#define ndsrvp_assert(expr) { if(!(expr)) ndsrvp_error(Error::StsAssert, std::string(#expr)); }
|
||||
|
||||
inline void ndsrvp_error(int code, std::string msg = "")
|
||||
{
|
||||
std::cerr << "NDSRVP Error: code " << code << std::endl;
|
||||
if(!msg.empty())
|
||||
std::cerr << msg << std::endl;
|
||||
if(code < 0)
|
||||
throw code;
|
||||
}
|
||||
|
||||
// clip & vclip
|
||||
|
||||
inline int clip(int x, int a, int b)
|
||||
{
|
||||
return x >= a ? (x < b ? x : b - 1) : a;
|
||||
}
|
||||
|
||||
inline int32x2_t vclip(int32x2_t x, int32x2_t a, int32x2_t b)
|
||||
{
|
||||
return (int32x2_t)__nds__bpick((long)a, __nds__bpick((long)(b - 1), (long)x, (long)(x < b)), (long)(x >= a));
|
||||
}
|
||||
|
||||
// expand
|
||||
|
||||
/*
|
||||
[0] [1] [2] [3] [4] [5] [6] [7]
|
||||
810 [ 0 ] [ 1 ] [ 4 ] [ 5 ]
|
||||
832 [ 2 ] [ 3 ] [ 6 ] [ 7 ]
|
||||
bb [ 0 ] [ 1 ] [ 2 ] [ 3 ]
|
||||
tt [ 4 ] [ 5 ] [ 6 ] [ 7 ]
|
||||
*/
|
||||
|
||||
inline void ndsrvp_u8_u16_expand8(const unsigned long vs, ushort* dst)
|
||||
{
|
||||
unsigned long vs810 = __nds__zunpkd810(vs);
|
||||
unsigned long vs832 = __nds__zunpkd832(vs);
|
||||
*(unsigned long*)dst = __nds__pkbb32(vs832, vs810);
|
||||
*(unsigned long*)(dst + 4) = __nds__pktt32(vs832, vs810);
|
||||
}
|
||||
|
||||
/*
|
||||
[0] [1] [2] [3] [4] [5] [6] [7]
|
||||
820 [ 0 ] [ 2 ] [ 4 ] [ 6 ]
|
||||
831 [ 1 ] [ 3 ] [ 5 ] [ 7 ]
|
||||
bb [ 0 ] [ 2 ] [ 1 ] [ 3 ]
|
||||
tt [ 4 ] [ 6 ] [ 5 ] [ 7 ]
|
||||
*/
|
||||
|
||||
inline void ndsrvp_u8_u16_eswap8(const unsigned long vs, ushort* dst)
|
||||
{
|
||||
unsigned long vs820 = __nds__zunpkd820(vs);
|
||||
unsigned long vs831 = __nds__zunpkd831(vs);
|
||||
*(unsigned long*)dst = __nds__pkbb32(vs831, vs820);
|
||||
*(unsigned long*)(dst + 4) = __nds__pktt32(vs831, vs820);
|
||||
}
|
||||
|
||||
/*
|
||||
[0] [1] [2] [3] [4] [5] [6] [7]
|
||||
820 [ 0 ] [ 2 ] [ 4 ] [ 6 ]
|
||||
831 [ 1 ] [ 3 ] [ 5 ] [ 7 ]
|
||||
bb [ 0 ] [ 2 ] [ 1 ] [ 3 ]
|
||||
tt [ 4 ] [ 6 ] [ 5 ] [ 7 ]
|
||||
bbbb[ 0 ] [ 1 ]
|
||||
bbtt[ 2 ] [ 3 ]
|
||||
ttbb[ 4 ] [ 5 ]
|
||||
tttt[ 6 ] [ 7 ]
|
||||
*/
|
||||
|
||||
|
||||
inline void ndsrvp_u8_u32_expand8(const unsigned long vs, uint* dst)
|
||||
{
|
||||
unsigned long vs820 = __nds__zunpkd820(vs);
|
||||
unsigned long vs831 = __nds__zunpkd831(vs);
|
||||
unsigned long vsbb = __nds__pkbb32(vs831, vs820);
|
||||
unsigned long vstt = __nds__pktt32(vs831, vs820);
|
||||
*(unsigned long*)dst = __nds__pkbb16(0, vsbb);
|
||||
*(unsigned long*)(dst + 2) = __nds__pktt16(0, vsbb);
|
||||
*(unsigned long*)(dst + 4) = __nds__pkbb16(0, vstt);
|
||||
*(unsigned long*)(dst + 6) = __nds__pktt16(0, vstt);
|
||||
}
|
||||
|
||||
// float replacement
|
||||
|
||||
inline void ndsrvp_f32_add8(const float* a, const float* b, float* c)
|
||||
{
|
||||
c[0] = a[0] + b[0];
|
||||
c[1] = a[1] + b[1];
|
||||
c[2] = a[2] + b[2];
|
||||
c[3] = a[3] + b[3];
|
||||
c[4] = a[4] + b[4];
|
||||
c[5] = a[5] + b[5];
|
||||
c[6] = a[6] + b[6];
|
||||
c[7] = a[7] + b[7];
|
||||
}
|
||||
|
||||
/*
|
||||
[1] [8] [23]
|
||||
[24] [8]
|
||||
*/
|
||||
|
||||
inline void ndsrvp_f32_u8_mul8(const float* a, const unsigned long b, float* c) // experimental, not bit exact
|
||||
{
|
||||
const int mask_frac = 0x007FFFFF;
|
||||
const int mask_sign = 0x7FFFFFFF;
|
||||
const int mask_lead = 0x40000000;
|
||||
const int ofs_exp = 23;
|
||||
|
||||
uint32x2_t va01 = *(uint32x2_t*)a;
|
||||
uint32x2_t va23 = *(uint32x2_t*)(a + 2);
|
||||
uint32x2_t va45 = *(uint32x2_t*)(a + 4);
|
||||
uint32x2_t va67 = *(uint32x2_t*)(a + 6);
|
||||
|
||||
uint32x2_t vaexp01 = va01 >> ofs_exp;
|
||||
uint32x2_t vaexp23 = va23 >> ofs_exp;
|
||||
uint32x2_t vaexp45 = va45 >> ofs_exp;
|
||||
uint32x2_t vaexp67 = va67 >> ofs_exp;
|
||||
|
||||
uint32x2_t vafrac01 = ((va01 << 7) & mask_sign) | mask_lead;
|
||||
uint32x2_t vafrac23 = ((va23 << 7) & mask_sign) | mask_lead;
|
||||
uint32x2_t vafrac45 = ((va45 << 7) & mask_sign) | mask_lead;
|
||||
uint32x2_t vafrac67 = ((va67 << 7) & mask_sign) | mask_lead;
|
||||
|
||||
int16x4_t vb[2]; // fake signed for signed multiply
|
||||
ndsrvp_u8_u16_eswap8(b, (ushort*)vb);
|
||||
|
||||
vafrac01 = (uint32x2_t)__nds__kmmwb2_u((long)vafrac01, (unsigned long)vb[0]);
|
||||
vafrac23 = (uint32x2_t)__nds__kmmwt2_u((long)vafrac23, (unsigned long)vb[0]);
|
||||
vafrac45 = (uint32x2_t)__nds__kmmwb2_u((long)vafrac45, (unsigned long)vb[1]);
|
||||
vafrac67 = (uint32x2_t)__nds__kmmwt2_u((long)vafrac67, (unsigned long)vb[1]);
|
||||
|
||||
uint32x2_t vaclz01 = __nds__v_clz32(vafrac01) - 8;
|
||||
uint32x2_t vaclz23 = __nds__v_clz32(vafrac23) - 8;
|
||||
uint32x2_t vaclz45 = __nds__v_clz32(vafrac45) - 8;
|
||||
uint32x2_t vaclz67 = __nds__v_clz32(vafrac67) - 8;
|
||||
|
||||
vaexp01 += 8 - vaclz01;
|
||||
vaexp23 += 8 - vaclz23;
|
||||
vaexp45 += 8 - vaclz45;
|
||||
vaexp67 += 8 - vaclz67;
|
||||
|
||||
vafrac01 <<= vaclz01;
|
||||
vafrac23 <<= vaclz23;
|
||||
vafrac45 <<= vaclz45;
|
||||
vafrac67 <<= vaclz67;
|
||||
|
||||
*(uint32x2_t*)c = (vaexp01 << ofs_exp) | (vafrac01 & mask_frac);
|
||||
*(uint32x2_t*)(c + 2) = (vaexp23 << ofs_exp) | (vafrac23 & mask_frac);
|
||||
*(uint32x2_t*)(c + 4) = (vaexp45 << ofs_exp) | (vafrac45 & mask_frac);
|
||||
*(uint32x2_t*)(c + 6) = (vaexp67 << ofs_exp) | (vafrac67 & mask_frac);
|
||||
}
|
||||
|
||||
// saturate
|
||||
|
||||
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>(int v) { return __nds__uclip32(v, 8); }
|
||||
template<> inline uchar saturate_cast<uchar>(float v) { return saturate_cast<uchar>((int)lrintf(v)); }
|
||||
template<> inline uchar saturate_cast<uchar>(double v) { return saturate_cast<uchar>((int)lrint(v)); }
|
||||
|
||||
template<> inline char saturate_cast<char>(int v) { return __nds__sclip32(v, 7); }
|
||||
template<> inline char saturate_cast<char>(float v) { return saturate_cast<char>((int)lrintf(v)); }
|
||||
template<> inline char saturate_cast<char>(double v) { return saturate_cast<char>((int)lrint(v)); }
|
||||
|
||||
template<> inline ushort saturate_cast<ushort>(int v) { return __nds__uclip32(v, 16); }
|
||||
template<> inline ushort saturate_cast<ushort>(float v) { return saturate_cast<ushort>((int)lrintf(v)); }
|
||||
template<> inline ushort saturate_cast<ushort>(double v) { return saturate_cast<ushort>((int)lrint(v)); }
|
||||
|
||||
template<> inline short saturate_cast<short>(int v) { return __nds__sclip32(v, 15); }
|
||||
template<> inline short saturate_cast<short>(float v) { return saturate_cast<short>((int)lrintf(v)); }
|
||||
template<> inline short saturate_cast<short>(double v) { return saturate_cast<short>((int)lrint(v)); }
|
||||
|
||||
template<> inline int saturate_cast<int>(float v) { return (int)lrintf(v); }
|
||||
template<> inline int saturate_cast<int>(double v) { return (int)lrint(v); }
|
||||
|
||||
inline double cast_ptr_to_double(const uchar* v, int depth) {
|
||||
switch (depth) {
|
||||
case CV_8U: return (double)*(uchar*)v;
|
||||
case CV_8S: return (double)*(char*)v;
|
||||
case CV_16U: return (double)*(ushort*)v;
|
||||
case CV_16S: return (double)*(short*)v;
|
||||
case CV_32S: return (double)*(int*)v;
|
||||
case CV_32F: return (double)*(float*)v;
|
||||
case CV_64F: return (double)*(double*)v;
|
||||
case CV_16F: return (double)*(float*)v;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _Tp data_at(const uchar* data, int step, int y, int x, int cn)
|
||||
{
|
||||
return ((_Tp*)(data + y * step))[x * cn];
|
||||
}
|
||||
|
||||
// align
|
||||
|
||||
inline long align(size_t v, int n)
|
||||
{
|
||||
return (v + n - 1) & -n;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,330 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
class FilterData
|
||||
{
|
||||
public:
|
||||
FilterData(uchar *_kernel_data, size_t _kernel_step, int _kernel_type, int _src_type, int _dst_type, int _borderType,
|
||||
int _kernel_width, int _kernel_height, int _max_width, int _max_height, double _delta, int _anchor_x, int _anchor_y)
|
||||
: kernel_data(_kernel_data), kernel_step(_kernel_step), kernel_type(_kernel_type), src_type(_src_type), dst_type(_dst_type), borderType(_borderType),
|
||||
kernel_width(_kernel_width), kernel_height(_kernel_height), max_width(_max_width), max_height(_max_height), delta(_delta), anchor_x(_anchor_x), anchor_y(_anchor_y)
|
||||
{
|
||||
}
|
||||
|
||||
uchar *kernel_data;
|
||||
size_t kernel_step; // bytes between rows(height)
|
||||
int kernel_type, src_type, dst_type, borderType;
|
||||
int kernel_width, kernel_height;
|
||||
int max_width, max_height;
|
||||
double delta;
|
||||
int anchor_x, anchor_y;
|
||||
std::vector<uchar> coords;
|
||||
std::vector<float> coeffs;
|
||||
int nz;
|
||||
std::vector<uchar> padding;
|
||||
};
|
||||
|
||||
static int countNonZero(const FilterData* ctx)
|
||||
{
|
||||
int i, j, nz = 0;
|
||||
const uchar* ker_row = ctx->kernel_data;
|
||||
for( i = 0; i < ctx->kernel_height; i++, ker_row += ctx->kernel_step )
|
||||
{
|
||||
for( j = 0; j < ctx->kernel_width; j++ )
|
||||
{
|
||||
if( ((float*)ker_row)[j] != 0.0 )
|
||||
nz++;
|
||||
}
|
||||
}
|
||||
return nz;
|
||||
}
|
||||
|
||||
static void preprocess2DKernel(FilterData* ctx)
|
||||
{
|
||||
int i, j, k, nz = countNonZero(ctx), ktype = ctx->kernel_type;
|
||||
if(nz == 0)
|
||||
nz = 1; // (0, 0) == 0 by default
|
||||
ndsrvp_assert( ktype == CV_32F );
|
||||
|
||||
ctx->coords.resize(nz * 2);
|
||||
ctx->coeffs.resize(nz);
|
||||
|
||||
const uchar* ker_row = ctx->kernel_data;
|
||||
for( i = k = 0; i < ctx->kernel_height; i++, ker_row += ctx->kernel_step )
|
||||
{
|
||||
for( j = 0; j < ctx->kernel_width; j++ )
|
||||
{
|
||||
float val = ((float*)ker_row)[j];
|
||||
if( val == 0.0 )
|
||||
continue;
|
||||
ctx->coords[k * 2] = j;
|
||||
ctx->coords[k * 2 + 1] = i;
|
||||
ctx->coeffs[k++] = val;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->nz = k;
|
||||
}
|
||||
|
||||
int filterInit(cvhalFilter2D **context,
|
||||
uchar *kernel_data, size_t kernel_step,
|
||||
int kernel_type, int kernel_width,
|
||||
int kernel_height, int max_width, int max_height,
|
||||
int src_type, int dst_type, int borderType,
|
||||
double delta, int anchor_x, int anchor_y,
|
||||
bool allowSubmatrix, bool allowInplace)
|
||||
{
|
||||
int sdepth = CV_MAT_DEPTH(src_type), ddepth = CV_MAT_DEPTH(dst_type);
|
||||
int cn = CV_MAT_CN(src_type), kdepth = kernel_type;
|
||||
|
||||
(void)allowSubmatrix;
|
||||
(void)allowInplace;
|
||||
|
||||
if(delta - (int)delta != 0.0)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(kdepth != CV_32F || (sdepth != CV_8U && sdepth != CV_16U) || ddepth != sdepth)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(anchor_x < 0 || anchor_x >= kernel_width || anchor_y < 0 || anchor_y >= kernel_height)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
borderType &= ~CV_HAL_BORDER_ISOLATED;
|
||||
|
||||
FilterData *ctx = new FilterData(kernel_data, kernel_step, kernel_type, src_type, dst_type, borderType,
|
||||
kernel_width, kernel_height, max_width, max_height, delta, anchor_x, anchor_y);
|
||||
|
||||
*context = (cvhalFilter2D*)ctx;
|
||||
|
||||
ndsrvp_assert(cn == CV_MAT_CN(dst_type) && ddepth >= sdepth);
|
||||
|
||||
preprocess2DKernel(ctx);
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
int filter(cvhalFilter2D *context,
|
||||
const uchar *src_data, size_t src_step,
|
||||
uchar *dst_data, size_t dst_step,
|
||||
int width, int height,
|
||||
int full_width, int full_height,
|
||||
int offset_x, int offset_y)
|
||||
{
|
||||
FilterData *ctx = (FilterData*)context;
|
||||
|
||||
int cn = CV_MAT_CN(ctx->src_type);
|
||||
int cnes = CV_ELEM_SIZE(ctx->src_type);
|
||||
int ddepth = CV_MAT_DEPTH(ctx->dst_type);
|
||||
float delta_sat = (uchar)(ctx->delta);
|
||||
if(ddepth == CV_8U)
|
||||
delta_sat = (float)saturate_cast<uchar>(ctx->delta);
|
||||
else if(ddepth == CV_16U)
|
||||
delta_sat = (float)saturate_cast<ushort>(ctx->delta);
|
||||
|
||||
// fetch original image data
|
||||
const uchar *ogn_data = src_data - offset_y * src_step - offset_x * cnes;
|
||||
int ogn_step = src_step;
|
||||
|
||||
// ROI fully used in the computation
|
||||
int cal_width = width + ctx->kernel_width - 1;
|
||||
int cal_height = height + ctx->kernel_height - 1;
|
||||
int cal_x = offset_x - ctx->anchor_x; // negative if left border exceeded
|
||||
int cal_y = offset_y - ctx->anchor_y; // negative if top border exceeded
|
||||
|
||||
// calculate source border
|
||||
ctx->padding.resize(cal_width * cal_height * cnes);
|
||||
uchar* pad_data = &ctx->padding[0];
|
||||
int pad_step = cal_width * cnes;
|
||||
|
||||
uchar* pad_ptr;
|
||||
const uchar* ogn_ptr;
|
||||
std::vector<uchar> vec_zeros(cnes, 0);
|
||||
for(int i = 0; i < cal_height; i++)
|
||||
{
|
||||
int y = borderInterpolate(i + cal_y, full_height, ctx->borderType);
|
||||
if(y < 0) {
|
||||
memset(pad_data + i * pad_step, 0, cnes * cal_width);
|
||||
continue;
|
||||
}
|
||||
|
||||
// left border
|
||||
int j = 0;
|
||||
int16x4_t vj = {0, 1, 2, 3};
|
||||
vj += saturate_cast<short>(cal_x);
|
||||
for(; j + cal_x < -4; j += 4, vj += 4)
|
||||
{
|
||||
int16x4_t vx = borderInterpolate_vector(vj, full_width, ctx->borderType);
|
||||
for(int k = 0; k < 4; k++) {
|
||||
if(vx[k] < 0) // border constant return value -1
|
||||
ogn_ptr = &vec_zeros[0];
|
||||
else
|
||||
ogn_ptr = ogn_data + y * ogn_step + vx[k] * cnes;
|
||||
pad_ptr = pad_data + i * pad_step + (j + k) * cnes;
|
||||
memcpy(pad_ptr, ogn_ptr, cnes);
|
||||
}
|
||||
}
|
||||
for(; j + cal_x < 0; j++)
|
||||
{
|
||||
int x = borderInterpolate(j + cal_x, full_width, ctx->borderType);
|
||||
if(x < 0) // border constant return value -1
|
||||
ogn_ptr = &vec_zeros[0];
|
||||
else
|
||||
ogn_ptr = ogn_data + y * ogn_step + x * cnes;
|
||||
pad_ptr = pad_data + i * pad_step + j * cnes;
|
||||
memcpy(pad_ptr, ogn_ptr, cnes);
|
||||
}
|
||||
|
||||
// center
|
||||
int rborder = MIN(cal_width, full_width - cal_x);
|
||||
const int center_width = rborder - j;
|
||||
if (center_width > 0)
|
||||
{
|
||||
ogn_ptr = ogn_data + y * ogn_step + (j + cal_x) * cnes;
|
||||
pad_ptr = pad_data + i * pad_step + j * cnes;
|
||||
memcpy(pad_ptr, ogn_ptr, (size_t)cnes * center_width);
|
||||
}
|
||||
|
||||
// right border
|
||||
j = rborder;
|
||||
vj = (int16x4_t){0, 1, 2, 3} + saturate_cast<short>(cal_x + rborder);
|
||||
for(; j <= cal_width - 4; j += 4, vj += 4)
|
||||
{
|
||||
int16x4_t vx = borderInterpolate_vector(vj, full_width, ctx->borderType);
|
||||
for(int k = 0; k < 4; k++) {
|
||||
if(vx[k] < 0) // border constant return value -1
|
||||
ogn_ptr = &vec_zeros[0];
|
||||
else
|
||||
ogn_ptr = ogn_data + y * ogn_step + vx[k] * cnes;
|
||||
pad_ptr = pad_data + i * pad_step + (j + k) * cnes;
|
||||
memcpy(pad_ptr, ogn_ptr, cnes);
|
||||
}
|
||||
}
|
||||
for(; j < cal_width; j++)
|
||||
{
|
||||
int x = borderInterpolate(j + cal_x, full_width, ctx->borderType);
|
||||
if(x < 0) // border constant return value -1
|
||||
ogn_ptr = &vec_zeros[0];
|
||||
else
|
||||
ogn_ptr = ogn_data + y * ogn_step + x * cnes;
|
||||
pad_ptr = pad_data + i * pad_step + j * cnes;
|
||||
memcpy(pad_ptr, ogn_ptr, cnes);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the pointers
|
||||
int i, k, count, nz = ctx->nz;
|
||||
const uchar* ker_pts = &ctx->coords[0];
|
||||
const float* ker_cfs = &ctx->coeffs[0];
|
||||
|
||||
if( ddepth == CV_8U )
|
||||
{
|
||||
std::vector<uchar*> src_ptrarr;
|
||||
src_ptrarr.resize(nz);
|
||||
uchar** src_ptrs = &src_ptrarr[0];
|
||||
uchar* dst_row = dst_data;
|
||||
uchar* pad_row = pad_data;
|
||||
|
||||
for( count = 0; count < height; count++, dst_row += dst_step, pad_row += pad_step )
|
||||
{
|
||||
for( k = 0; k < nz; k++ )
|
||||
src_ptrs[k] = (uchar*)pad_row + ker_pts[k * 2 + 1] * pad_step + ker_pts[k * 2] * cnes;
|
||||
|
||||
i = 0;
|
||||
for( ; i <= width * cnes - 8; i += 8 )
|
||||
{
|
||||
float vs0[8] = {delta_sat, delta_sat, delta_sat, delta_sat, delta_sat, delta_sat, delta_sat, delta_sat};
|
||||
for( k = 0; k < nz; k++ ) {
|
||||
float vker_cfs[8] = {ker_cfs[k], ker_cfs[k], ker_cfs[k], ker_cfs[k], ker_cfs[k], ker_cfs[k], ker_cfs[k], ker_cfs[k]};
|
||||
// experimental code
|
||||
// ndsrvp_f32_u8_mul8(vker_cfs, *(unsigned long*)(src_ptrs[k] + i), vker_cfs);
|
||||
// ndsrvp_f32_add8(vs0, vker_cfs, vs0);
|
||||
vs0[0] += vker_cfs[0] * src_ptrs[k][i];
|
||||
vs0[1] += vker_cfs[1] * src_ptrs[k][i + 1];
|
||||
vs0[2] += vker_cfs[2] * src_ptrs[k][i + 2];
|
||||
vs0[3] += vker_cfs[3] * src_ptrs[k][i + 3];
|
||||
vs0[4] += vker_cfs[4] * src_ptrs[k][i + 4];
|
||||
vs0[5] += vker_cfs[5] * src_ptrs[k][i + 5];
|
||||
vs0[6] += vker_cfs[6] * src_ptrs[k][i + 6];
|
||||
vs0[7] += vker_cfs[7] * src_ptrs[k][i + 7];
|
||||
}
|
||||
dst_row[i] = saturate_cast<uchar>(vs0[0]);
|
||||
dst_row[i + 1] = saturate_cast<uchar>(vs0[1]);
|
||||
dst_row[i + 2] = saturate_cast<uchar>(vs0[2]);
|
||||
dst_row[i + 3] = saturate_cast<uchar>(vs0[3]);
|
||||
dst_row[i + 4] = saturate_cast<uchar>(vs0[4]);
|
||||
dst_row[i + 5] = saturate_cast<uchar>(vs0[5]);
|
||||
dst_row[i + 6] = saturate_cast<uchar>(vs0[6]);
|
||||
dst_row[i + 7] = saturate_cast<uchar>(vs0[7]);
|
||||
}
|
||||
for( ; i < width * cnes; i++ )
|
||||
{
|
||||
float s0 = delta_sat;
|
||||
for( k = 0; k < nz; k++ ) {
|
||||
s0 += ker_cfs[k] * src_ptrs[k][i];
|
||||
}
|
||||
dst_row[i] = saturate_cast<uchar>(s0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( ddepth == CV_16U )
|
||||
{
|
||||
std::vector<ushort*> src_ptrarr;
|
||||
src_ptrarr.resize(nz);
|
||||
ushort** src_ptrs = &src_ptrarr[0];
|
||||
uchar* dst_row = dst_data;
|
||||
uchar* pad_row = pad_data;
|
||||
|
||||
for( count = 0; count < height; count++, dst_row += dst_step, pad_row += pad_step )
|
||||
{
|
||||
for( k = 0; k < nz; k++ )
|
||||
src_ptrs[k] = (ushort*)((uchar*)pad_row + ker_pts[k * 2 + 1] * pad_step + ker_pts[k * 2] * cnes);
|
||||
|
||||
i = 0;
|
||||
for( ; i <= width * cn - 4; i += 4 )
|
||||
{
|
||||
float vs0[8] = {delta_sat, delta_sat, delta_sat, delta_sat};
|
||||
for( k = 0; k < nz; k++ ) {
|
||||
float vker_cfs[8] = {ker_cfs[k], ker_cfs[k], ker_cfs[k], ker_cfs[k]};
|
||||
vs0[0] += vker_cfs[0] * src_ptrs[k][i];
|
||||
vs0[1] += vker_cfs[1] * src_ptrs[k][i + 1];
|
||||
vs0[2] += vker_cfs[2] * src_ptrs[k][i + 2];
|
||||
vs0[3] += vker_cfs[3] * src_ptrs[k][i + 3];
|
||||
}
|
||||
ushort* dst_row_ptr = (ushort*)dst_row;
|
||||
dst_row_ptr[i] = saturate_cast<ushort>(vs0[0]);
|
||||
dst_row_ptr[i + 1] = saturate_cast<ushort>(vs0[1]);
|
||||
dst_row_ptr[i + 2] = saturate_cast<ushort>(vs0[2]);
|
||||
dst_row_ptr[i + 3] = saturate_cast<ushort>(vs0[3]);
|
||||
}
|
||||
for( ; i < width * cn; i++ )
|
||||
{
|
||||
float s0 = delta_sat;
|
||||
for( k = 0; k < nz; k++ ) {
|
||||
s0 += ker_cfs[k] * src_ptrs[k][i];
|
||||
}
|
||||
((ushort*)dst_row)[i] = saturate_cast<ushort>(s0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
int filterFree(cvhalFilter2D *context) {
|
||||
FilterData *ctx = (FilterData*)context;
|
||||
delete ctx;
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,212 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
int integral(int depth, int sdepth, int sqdepth,
|
||||
const uchar* src, size_t _srcstep,
|
||||
uchar* _sum, size_t _sumstep,
|
||||
uchar* _sqsum, size_t,
|
||||
uchar* _tilted, size_t,
|
||||
int width, int height, int cn)
|
||||
{
|
||||
// 8-bit unsigned integer, 32-bit signed integer only
|
||||
if (!(depth == CV_8U && sdepth == CV_32S))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// too small image
|
||||
if (!(width >> 8 || height >> 8 || cn == 4))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
int* sum = (int*)_sum;
|
||||
double* sqsum = (double*)_sqsum;
|
||||
int* tilted = (int*)_tilted;
|
||||
|
||||
if (sqsum || tilted || cn > 4)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
sqdepth = sqdepth;
|
||||
width *= cn;
|
||||
|
||||
memset(sum, 0, (width + cn) * sizeof(int));
|
||||
|
||||
if (cn == 1) {
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const uchar* src_row = src + _srcstep * i;
|
||||
int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn;
|
||||
int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn;
|
||||
|
||||
sum_row[-1] = 0;
|
||||
|
||||
int32x2_t prev = { 0, 0 };
|
||||
int j = 0;
|
||||
|
||||
for (; j + 8 <= width; j += 8) {
|
||||
unsigned long vs8x8 = *(unsigned long*)(src_row + j);
|
||||
|
||||
unsigned long vs810 = __nds__zunpkd810(vs8x8);
|
||||
unsigned long vs832 = __nds__zunpkd832(vs8x8);
|
||||
|
||||
int16x4_t vs16x4 = (int16x4_t)__nds__pkbb32(vs832, vs810);
|
||||
|
||||
vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 16); // gcc vector extension
|
||||
vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 32); // '+' is add16
|
||||
|
||||
//*(int32x2_t*)(sum_row + j) = (int32x2_t) { vs16x4[0], vs16x4[1] } + *(int32x2_t*)(prev_sum_row + j) + prev;
|
||||
//*(int32x2_t*)(sum_row + j + 2) = (int32x2_t) { vs16x4[2], vs16x4[3] } + *(int32x2_t*)(prev_sum_row + j + 2) + prev;
|
||||
// performance loss for unknown reason, commented out, use the following code instead
|
||||
|
||||
sum_row[j] = prev_sum_row[j] + prev[0] + vs16x4[0];
|
||||
sum_row[j + 1] = prev_sum_row[j + 1] + prev[1] + vs16x4[1];
|
||||
sum_row[j + 2] = prev_sum_row[j + 2] + prev[0] + vs16x4[2];
|
||||
sum_row[j + 3] = prev_sum_row[j + 3] + prev[1] + vs16x4[3];
|
||||
|
||||
prev += vs16x4[3]; // prev += (int32x2_t){vs16x4[3], vs16x4[3]};
|
||||
|
||||
vs16x4 = (int16x4_t)__nds__pktt32(vs832, vs810);
|
||||
|
||||
vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 16);
|
||||
vs16x4 += (int16x4_t)((unsigned long)vs16x4 << 32);
|
||||
|
||||
//*(int32x2_t*)(sum_row + j + 4) = (int32x2_t) { vs16x4[0], vs16x4[1] } + *(int32x2_t*)(prev_sum_row + j + 4) + prev;
|
||||
//*(int32x2_t*)(sum_row + j + 6) = (int32x2_t) { vs16x4[2], vs16x4[3] } + *(int32x2_t*)(prev_sum_row + j + 6) + prev;
|
||||
// performance loss for unknown reason, commented out, use the following code instead
|
||||
|
||||
sum_row[j + 4] = prev_sum_row[j + 4] + prev[0] + vs16x4[0];
|
||||
sum_row[j + 5] = prev_sum_row[j + 5] + prev[1] + vs16x4[1];
|
||||
sum_row[j + 6] = prev_sum_row[j + 6] + prev[0] + vs16x4[2];
|
||||
sum_row[j + 7] = prev_sum_row[j + 7] + prev[1] + vs16x4[3];
|
||||
|
||||
prev += vs16x4[3];
|
||||
}
|
||||
|
||||
for (int v = sum_row[j - 1] - prev_sum_row[j - 1]; j < width; ++j)
|
||||
sum_row[j] = (v += src_row[j]) + prev_sum_row[j];
|
||||
}
|
||||
} else if (cn == 2) {
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const uchar* src_row = src + _srcstep * i;
|
||||
int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn;
|
||||
int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn;
|
||||
|
||||
sum_row[-1] = sum_row[-2] = 0;
|
||||
|
||||
int32x2_t prev = { 0, 0 };
|
||||
int j = 0;
|
||||
for (; j + 8 <= width; j += 8) {
|
||||
uint8x8_t vs8x8 = *(uint8x8_t*)(src_row + j);
|
||||
|
||||
uint16x4_t vs16x4_1 = __nds__v_zunpkd820(vs8x8);
|
||||
uint16x4_t vs16x4_2 = __nds__v_zunpkd831(vs8x8);
|
||||
|
||||
vs16x4_1 += (int16x4_t)((unsigned long)vs16x4_1 << 16);
|
||||
vs16x4_1 += (int16x4_t)((unsigned long)vs16x4_1 << 32);
|
||||
|
||||
vs16x4_2 += (int16x4_t)((unsigned long)vs16x4_2 << 16);
|
||||
vs16x4_2 += (int16x4_t)((unsigned long)vs16x4_2 << 32);
|
||||
|
||||
*(int32x2_t*)(sum_row + j) = (int32x2_t) { vs16x4_1[0], vs16x4_2[0] } + *(int32x2_t*)(prev_sum_row + j) + prev;
|
||||
*(int32x2_t*)(sum_row + j + 2) = (int32x2_t) { vs16x4_1[1], vs16x4_2[1] } + *(int32x2_t*)(prev_sum_row + j + 2) + prev;
|
||||
*(int32x2_t*)(sum_row + j + 2 * 2) = (int32x2_t) { vs16x4_1[2], vs16x4_2[2] } + *(int32x2_t*)(prev_sum_row + j + 2 * 2) + prev;
|
||||
*(int32x2_t*)(sum_row + j + 2 * 3) = (int32x2_t) { vs16x4_1[3], vs16x4_2[3] } + *(int32x2_t*)(prev_sum_row + j + 2 * 3) + prev;
|
||||
|
||||
prev += (int32x2_t) { vs16x4_1[3], vs16x4_2[3] };
|
||||
}
|
||||
|
||||
for (int v2 = sum_row[j - 1] - prev_sum_row[j - 1],
|
||||
v1 = sum_row[j - 2] - prev_sum_row[j - 2];
|
||||
j < width; j += 2) {
|
||||
sum_row[j] = (v1 += src_row[j]) + prev_sum_row[j];
|
||||
sum_row[j + 1] = (v2 += src_row[j + 1]) + prev_sum_row[j + 1];
|
||||
}
|
||||
}
|
||||
} else if (cn == 3) {
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
/* disabled because of unaligned memory access, difficulty in vectorization, etc.
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const uchar* src_row = src + _srcstep * i;
|
||||
int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn;
|
||||
int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn;
|
||||
|
||||
sum_row[-1] = sum_row[-2] = sum_row[-3] = 0;
|
||||
|
||||
int32x2_t prev_ptr[2] = { { 0, 0 }, { 0, 0 } };
|
||||
int j = 0;
|
||||
for (; j + 3 <= width; j += 3) {
|
||||
//uint8x4_t vs8x4 = *(uint8x4_t*)(src_row + j);
|
||||
// performance loss for unknown reason, commented out, use the following code instead
|
||||
|
||||
uint8x4_t vs8x4 = (uint8x4_t){ src_row[j], src_row[j + 1], src_row[j + 2], 0};
|
||||
|
||||
// [ 0 | 2 | 1 | 3 ]
|
||||
int16x4_t vs16x4 = (int16x4_t)__nds__pkbb32(__nds__zunpkd831((unsigned int)vs8x4), __nds__zunpkd820((unsigned int)vs8x4));
|
||||
|
||||
// [ b | t | b | t ]
|
||||
prev_ptr[0] += (int32x2_t)__nds__pkbb16(0, (unsigned long)vs16x4);
|
||||
prev_ptr[1] += (int32x2_t)__nds__pktt16(0, (unsigned long)vs16x4);
|
||||
|
||||
//*(int32x4_t*)(sum_row + j) = *(int32x4_t*)(prev_sum_row + j) + *(int32x4_t*)prev_ptr;
|
||||
// performance loss for unknown reason, commented out, use the following code instead
|
||||
|
||||
sum_row[j] = prev_sum_row[j] + prev_ptr[0][0];
|
||||
sum_row[j + 1] = prev_sum_row[j + 1] + prev_ptr[0][1];
|
||||
sum_row[j + 2] = prev_sum_row[j + 2] + prev_ptr[1][0];
|
||||
}
|
||||
|
||||
for (int v3 = sum_row[j - 1] - prev_sum_row[j - 1],
|
||||
v2 = sum_row[j - 2] - prev_sum_row[j - 2],
|
||||
v1 = sum_row[j - 3] - prev_sum_row[j - 3];
|
||||
j < width; j += 3) {
|
||||
sum_row[j] = (v1 += src_row[j]) + prev_sum_row[j];
|
||||
sum_row[j + 1] = (v2 += src_row[j + 1]) + prev_sum_row[j + 1];
|
||||
sum_row[j + 2] = (v3 += src_row[j + 2]) + prev_sum_row[j + 2];
|
||||
}
|
||||
}*/
|
||||
} else if (cn == 4) {
|
||||
for (int i = 0; i < height; ++i) {
|
||||
const uchar* src_row = src + _srcstep * i;
|
||||
int* prev_sum_row = (int*)((uchar*)sum + _sumstep * i) + cn;
|
||||
int* sum_row = (int*)((uchar*)sum + _sumstep * (i + 1)) + cn;
|
||||
|
||||
sum_row[-1] = sum_row[-2] = sum_row[-3] = sum_row[-4] = 0;
|
||||
|
||||
int32x2_t prev_ptr[2] = { { 0, 0 }, { 0, 0 } };
|
||||
int j = 0;
|
||||
for (; j + 4 <= width; j += 4) {
|
||||
uint8x4_t vs8x4 = *(uint8x4_t*)(src_row + j);
|
||||
|
||||
// [ 0 | 2 | 1 | 3 ]
|
||||
int16x4_t vs16x4 = (int16x4_t)__nds__pkbb32(__nds__zunpkd831((unsigned int)vs8x4), __nds__zunpkd820((unsigned int)vs8x4));
|
||||
|
||||
// [ b | t | b | t ]
|
||||
prev_ptr[0] += (int32x2_t)__nds__pkbb16(0, (unsigned long)vs16x4);
|
||||
prev_ptr[1] += (int32x2_t)__nds__pktt16(0, (unsigned long)vs16x4);
|
||||
|
||||
*(int32x4_t*)(sum_row + j) = *(int32x4_t*)(prev_sum_row + j) + *(int32x4_t*)prev_ptr;
|
||||
}
|
||||
|
||||
for (int v4 = sum_row[j - 1] - prev_sum_row[j - 1],
|
||||
v3 = sum_row[j - 2] - prev_sum_row[j - 2],
|
||||
v2 = sum_row[j - 3] - prev_sum_row[j - 3],
|
||||
v1 = sum_row[j - 4] - prev_sum_row[j - 4];
|
||||
j < width; j += 4) {
|
||||
sum_row[j] = (v1 += src_row[j]) + prev_sum_row[j];
|
||||
sum_row[j + 1] = (v2 += src_row[j + 1]) + prev_sum_row[j + 1];
|
||||
sum_row[j + 2] = (v3 += src_row[j + 2]) + prev_sum_row[j + 2];
|
||||
sum_row[j + 3] = (v4 += src_row[j + 3]) + prev_sum_row[j + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,300 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
struct operators_minmax_t {
|
||||
inline void vector(uint8x8_t & a, uint8x8_t & b) const {
|
||||
uint8x8_t t = a;
|
||||
a = __nds__v_umin8(a, b);
|
||||
b = __nds__v_umax8(t, b);
|
||||
}
|
||||
inline void scalar(uchar & a, uchar & b) const {
|
||||
uchar t = a;
|
||||
a = __nds__umin8(a, b);
|
||||
b = __nds__umax8(t, b);
|
||||
}
|
||||
inline void vector(int8x8_t & a, int8x8_t & b) const {
|
||||
int8x8_t t = a;
|
||||
a = __nds__v_smin8(a, b);
|
||||
b = __nds__v_smax8(t, b);
|
||||
}
|
||||
inline void scalar(schar & a, schar & b) const {
|
||||
schar t = a;
|
||||
a = __nds__smin8(a, b);
|
||||
b = __nds__smax8(t, b);
|
||||
}
|
||||
inline void vector(uint16x4_t & a, uint16x4_t & b) const {
|
||||
uint16x4_t t = a;
|
||||
a = __nds__v_umin16(a, b);
|
||||
b = __nds__v_umax16(t, b);
|
||||
}
|
||||
inline void scalar(ushort & a, ushort & b) const {
|
||||
ushort t = a;
|
||||
a = __nds__umin16(a, b);
|
||||
b = __nds__umax16(t, b);
|
||||
}
|
||||
inline void vector(int16x4_t & a, int16x4_t & b) const {
|
||||
int16x4_t t = a;
|
||||
a = __nds__v_smin16(a, b);
|
||||
b = __nds__v_smax16(t, b);
|
||||
}
|
||||
inline void scalar(short & a, short & b) const {
|
||||
short t = a;
|
||||
a = __nds__smin16(a, b);
|
||||
b = __nds__smax16(t, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename WT, typename VT> // type, widen type, vector type
|
||||
static void
|
||||
medianBlur_SortNet( const uchar* src_data, size_t src_step,
|
||||
uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int cn, int ksize )
|
||||
{
|
||||
const T* src = (T*)src_data;
|
||||
T* dst = (T*)dst_data;
|
||||
int sstep = (int)(src_step / sizeof(T));
|
||||
int dstep = (int)(dst_step / sizeof(T));
|
||||
int i, j, k;
|
||||
operators_minmax_t op;
|
||||
|
||||
if( ksize == 3 )
|
||||
{
|
||||
if( width == 1 || height == 1 )
|
||||
{
|
||||
int len = width + height - 1;
|
||||
int sdelta = height == 1 ? cn : sstep;
|
||||
int sdelta0 = height == 1 ? 0 : sstep - cn;
|
||||
int ddelta = height == 1 ? cn : dstep;
|
||||
|
||||
for( i = 0; i < len; i++, src += sdelta0, dst += ddelta )
|
||||
for( j = 0; j < cn; j++, src++ )
|
||||
{
|
||||
T p0 = src[i > 0 ? -sdelta : 0];
|
||||
T p1 = src[0];
|
||||
T p2 = src[i < len - 1 ? sdelta : 0];
|
||||
|
||||
op.scalar(p0, p1); op.scalar(p1, p2); op.scalar(p0, p1);
|
||||
dst[j] = (T)p1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
width *= cn;
|
||||
for( i = 0; i < height; i++, dst += dstep )
|
||||
{
|
||||
const T* row0 = src + std::max(i - 1, 0)*sstep;
|
||||
const T* row1 = src + i*sstep;
|
||||
const T* row2 = src + std::min(i + 1, height-1)*sstep;
|
||||
int limit = cn;
|
||||
|
||||
for(j = 0;; )
|
||||
{
|
||||
for( ; j < limit; j++ )
|
||||
{
|
||||
int j0 = j >= cn ? j - cn : j;
|
||||
int j2 = j < width - cn ? j + cn : j;
|
||||
T p0 = row0[j0], p1 = row0[j], p2 = row0[j2];
|
||||
T p3 = row1[j0], p4 = row1[j], p5 = row1[j2];
|
||||
T p6 = row2[j0], p7 = row2[j], p8 = row2[j2];
|
||||
|
||||
op.scalar(p1, p2); op.scalar(p4, p5); op.scalar(p7, p8); op.scalar(p0, p1);
|
||||
op.scalar(p3, p4); op.scalar(p6, p7); op.scalar(p1, p2); op.scalar(p4, p5);
|
||||
op.scalar(p7, p8); op.scalar(p0, p3); op.scalar(p5, p8); op.scalar(p4, p7);
|
||||
op.scalar(p3, p6); op.scalar(p1, p4); op.scalar(p2, p5); op.scalar(p4, p7);
|
||||
op.scalar(p4, p2); op.scalar(p6, p4); op.scalar(p4, p2);
|
||||
dst[j] = (T)p4;
|
||||
}
|
||||
|
||||
if( limit == width )
|
||||
break;
|
||||
|
||||
int nlanes = 8 / sizeof(T);
|
||||
|
||||
for( ; (cn % nlanes == 0) && (j <= width - nlanes - cn); j += nlanes ) // alignment
|
||||
{
|
||||
VT p0 = *(VT*)(row0+j-cn), p1 = *(VT*)(row0+j), p2 = *(VT*)(row0+j+cn);
|
||||
VT p3 = *(VT*)(row1+j-cn), p4 = *(VT*)(row1+j), p5 = *(VT*)(row1+j+cn);
|
||||
VT p6 = *(VT*)(row2+j-cn), p7 = *(VT*)(row2+j), p8 = *(VT*)(row2+j+cn);
|
||||
|
||||
op.vector(p1, p2); op.vector(p4, p5); op.vector(p7, p8); op.vector(p0, p1);
|
||||
op.vector(p3, p4); op.vector(p6, p7); op.vector(p1, p2); op.vector(p4, p5);
|
||||
op.vector(p7, p8); op.vector(p0, p3); op.vector(p5, p8); op.vector(p4, p7);
|
||||
op.vector(p3, p6); op.vector(p1, p4); op.vector(p2, p5); op.vector(p4, p7);
|
||||
op.vector(p4, p2); op.vector(p6, p4); op.vector(p4, p2);
|
||||
*(VT*)(dst+j) = p4;
|
||||
}
|
||||
|
||||
limit = width;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( ksize == 5 )
|
||||
{
|
||||
if( width == 1 || height == 1 )
|
||||
{
|
||||
int len = width + height - 1;
|
||||
int sdelta = height == 1 ? cn : sstep;
|
||||
int sdelta0 = height == 1 ? 0 : sstep - cn;
|
||||
int ddelta = height == 1 ? cn : dstep;
|
||||
|
||||
for( i = 0; i < len; i++, src += sdelta0, dst += ddelta )
|
||||
for( j = 0; j < cn; j++, src++ )
|
||||
{
|
||||
int i1 = i > 0 ? -sdelta : 0;
|
||||
int i0 = i > 1 ? -sdelta*2 : i1;
|
||||
int i3 = i < len-1 ? sdelta : 0;
|
||||
int i4 = i < len-2 ? sdelta*2 : i3;
|
||||
T p0 = src[i0], p1 = src[i1], p2 = src[0], p3 = src[i3], p4 = src[i4];
|
||||
|
||||
op.scalar(p0, p1); op.scalar(p3, p4); op.scalar(p2, p3); op.scalar(p3, p4); op.scalar(p0, p2);
|
||||
op.scalar(p2, p4); op.scalar(p1, p3); op.scalar(p1, p2);
|
||||
dst[j] = (T)p2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
width *= cn;
|
||||
for( i = 0; i < height; i++, dst += dstep )
|
||||
{
|
||||
const T* row[5];
|
||||
row[0] = src + std::max(i - 2, 0)*sstep;
|
||||
row[1] = src + std::max(i - 1, 0)*sstep;
|
||||
row[2] = src + i*sstep;
|
||||
row[3] = src + std::min(i + 1, height-1)*sstep;
|
||||
row[4] = src + std::min(i + 2, height-1)*sstep;
|
||||
int limit = cn*2;
|
||||
|
||||
for(j = 0;; )
|
||||
{
|
||||
for( ; j < limit; j++ )
|
||||
{
|
||||
T p[25];
|
||||
int j1 = j >= cn ? j - cn : j;
|
||||
int j0 = j >= cn*2 ? j - cn*2 : j1;
|
||||
int j3 = j < width - cn ? j + cn : j;
|
||||
int j4 = j < width - cn*2 ? j + cn*2 : j3;
|
||||
for( k = 0; k < 5; k++ )
|
||||
{
|
||||
const T* rowk = row[k];
|
||||
p[k*5] = rowk[j0]; p[k*5+1] = rowk[j1];
|
||||
p[k*5+2] = rowk[j]; p[k*5+3] = rowk[j3];
|
||||
p[k*5+4] = rowk[j4];
|
||||
}
|
||||
|
||||
op.scalar(p[1], p[2]); op.scalar(p[0], p[1]); op.scalar(p[1], p[2]); op.scalar(p[4], p[5]); op.scalar(p[3], p[4]);
|
||||
op.scalar(p[4], p[5]); op.scalar(p[0], p[3]); op.scalar(p[2], p[5]); op.scalar(p[2], p[3]); op.scalar(p[1], p[4]);
|
||||
op.scalar(p[1], p[2]); op.scalar(p[3], p[4]); op.scalar(p[7], p[8]); op.scalar(p[6], p[7]); op.scalar(p[7], p[8]);
|
||||
op.scalar(p[10], p[11]); op.scalar(p[9], p[10]); op.scalar(p[10], p[11]); op.scalar(p[6], p[9]); op.scalar(p[8], p[11]);
|
||||
op.scalar(p[8], p[9]); op.scalar(p[7], p[10]); op.scalar(p[7], p[8]); op.scalar(p[9], p[10]); op.scalar(p[0], p[6]);
|
||||
op.scalar(p[4], p[10]); op.scalar(p[4], p[6]); op.scalar(p[2], p[8]); op.scalar(p[2], p[4]); op.scalar(p[6], p[8]);
|
||||
op.scalar(p[1], p[7]); op.scalar(p[5], p[11]); op.scalar(p[5], p[7]); op.scalar(p[3], p[9]); op.scalar(p[3], p[5]);
|
||||
op.scalar(p[7], p[9]); op.scalar(p[1], p[2]); op.scalar(p[3], p[4]); op.scalar(p[5], p[6]); op.scalar(p[7], p[8]);
|
||||
op.scalar(p[9], p[10]); op.scalar(p[13], p[14]); op.scalar(p[12], p[13]); op.scalar(p[13], p[14]); op.scalar(p[16], p[17]);
|
||||
op.scalar(p[15], p[16]); op.scalar(p[16], p[17]); op.scalar(p[12], p[15]); op.scalar(p[14], p[17]); op.scalar(p[14], p[15]);
|
||||
op.scalar(p[13], p[16]); op.scalar(p[13], p[14]); op.scalar(p[15], p[16]); op.scalar(p[19], p[20]); op.scalar(p[18], p[19]);
|
||||
op.scalar(p[19], p[20]); op.scalar(p[21], p[22]); op.scalar(p[23], p[24]); op.scalar(p[21], p[23]); op.scalar(p[22], p[24]);
|
||||
op.scalar(p[22], p[23]); op.scalar(p[18], p[21]); op.scalar(p[20], p[23]); op.scalar(p[20], p[21]); op.scalar(p[19], p[22]);
|
||||
op.scalar(p[22], p[24]); op.scalar(p[19], p[20]); op.scalar(p[21], p[22]); op.scalar(p[23], p[24]); op.scalar(p[12], p[18]);
|
||||
op.scalar(p[16], p[22]); op.scalar(p[16], p[18]); op.scalar(p[14], p[20]); op.scalar(p[20], p[24]); op.scalar(p[14], p[16]);
|
||||
op.scalar(p[18], p[20]); op.scalar(p[22], p[24]); op.scalar(p[13], p[19]); op.scalar(p[17], p[23]); op.scalar(p[17], p[19]);
|
||||
op.scalar(p[15], p[21]); op.scalar(p[15], p[17]); op.scalar(p[19], p[21]); op.scalar(p[13], p[14]); op.scalar(p[15], p[16]);
|
||||
op.scalar(p[17], p[18]); op.scalar(p[19], p[20]); op.scalar(p[21], p[22]); op.scalar(p[23], p[24]); op.scalar(p[0], p[12]);
|
||||
op.scalar(p[8], p[20]); op.scalar(p[8], p[12]); op.scalar(p[4], p[16]); op.scalar(p[16], p[24]); op.scalar(p[12], p[16]);
|
||||
op.scalar(p[2], p[14]); op.scalar(p[10], p[22]); op.scalar(p[10], p[14]); op.scalar(p[6], p[18]); op.scalar(p[6], p[10]);
|
||||
op.scalar(p[10], p[12]); op.scalar(p[1], p[13]); op.scalar(p[9], p[21]); op.scalar(p[9], p[13]); op.scalar(p[5], p[17]);
|
||||
op.scalar(p[13], p[17]); op.scalar(p[3], p[15]); op.scalar(p[11], p[23]); op.scalar(p[11], p[15]); op.scalar(p[7], p[19]);
|
||||
op.scalar(p[7], p[11]); op.scalar(p[11], p[13]); op.scalar(p[11], p[12]);
|
||||
dst[j] = (T)p[12];
|
||||
}
|
||||
|
||||
if( limit == width )
|
||||
break;
|
||||
|
||||
int nlanes = 8 / sizeof(T);
|
||||
|
||||
for( ; (cn % nlanes == 0) && (j <= width - nlanes - cn*2); j += nlanes )
|
||||
{
|
||||
VT p0 = *(VT*)(row[0]+j-cn*2), p5 = *(VT*)(row[1]+j-cn*2), p10 = *(VT*)(row[2]+j-cn*2), p15 = *(VT*)(row[3]+j-cn*2), p20 = *(VT*)(row[4]+j-cn*2);
|
||||
VT p1 = *(VT*)(row[0]+j-cn*1), p6 = *(VT*)(row[1]+j-cn*1), p11 = *(VT*)(row[2]+j-cn*1), p16 = *(VT*)(row[3]+j-cn*1), p21 = *(VT*)(row[4]+j-cn*1);
|
||||
VT p2 = *(VT*)(row[0]+j-cn*0), p7 = *(VT*)(row[1]+j-cn*0), p12 = *(VT*)(row[2]+j-cn*0), p17 = *(VT*)(row[3]+j-cn*0), p22 = *(VT*)(row[4]+j-cn*0);
|
||||
VT p3 = *(VT*)(row[0]+j+cn*1), p8 = *(VT*)(row[1]+j+cn*1), p13 = *(VT*)(row[2]+j+cn*1), p18 = *(VT*)(row[3]+j+cn*1), p23 = *(VT*)(row[4]+j+cn*1);
|
||||
VT p4 = *(VT*)(row[0]+j+cn*2), p9 = *(VT*)(row[1]+j+cn*2), p14 = *(VT*)(row[2]+j+cn*2), p19 = *(VT*)(row[3]+j+cn*2), p24 = *(VT*)(row[4]+j+cn*2);
|
||||
|
||||
op.vector(p1, p2); op.vector(p0, p1); op.vector(p1, p2); op.vector(p4, p5); op.vector(p3, p4);
|
||||
op.vector(p4, p5); op.vector(p0, p3); op.vector(p2, p5); op.vector(p2, p3); op.vector(p1, p4);
|
||||
op.vector(p1, p2); op.vector(p3, p4); op.vector(p7, p8); op.vector(p6, p7); op.vector(p7, p8);
|
||||
op.vector(p10, p11); op.vector(p9, p10); op.vector(p10, p11); op.vector(p6, p9); op.vector(p8, p11);
|
||||
op.vector(p8, p9); op.vector(p7, p10); op.vector(p7, p8); op.vector(p9, p10); op.vector(p0, p6);
|
||||
op.vector(p4, p10); op.vector(p4, p6); op.vector(p2, p8); op.vector(p2, p4); op.vector(p6, p8);
|
||||
op.vector(p1, p7); op.vector(p5, p11); op.vector(p5, p7); op.vector(p3, p9); op.vector(p3, p5);
|
||||
op.vector(p7, p9); op.vector(p1, p2); op.vector(p3, p4); op.vector(p5, p6); op.vector(p7, p8);
|
||||
op.vector(p9, p10); op.vector(p13, p14); op.vector(p12, p13); op.vector(p13, p14); op.vector(p16, p17);
|
||||
op.vector(p15, p16); op.vector(p16, p17); op.vector(p12, p15); op.vector(p14, p17); op.vector(p14, p15);
|
||||
op.vector(p13, p16); op.vector(p13, p14); op.vector(p15, p16); op.vector(p19, p20); op.vector(p18, p19);
|
||||
op.vector(p19, p20); op.vector(p21, p22); op.vector(p23, p24); op.vector(p21, p23); op.vector(p22, p24);
|
||||
op.vector(p22, p23); op.vector(p18, p21); op.vector(p20, p23); op.vector(p20, p21); op.vector(p19, p22);
|
||||
op.vector(p22, p24); op.vector(p19, p20); op.vector(p21, p22); op.vector(p23, p24); op.vector(p12, p18);
|
||||
op.vector(p16, p22); op.vector(p16, p18); op.vector(p14, p20); op.vector(p20, p24); op.vector(p14, p16);
|
||||
op.vector(p18, p20); op.vector(p22, p24); op.vector(p13, p19); op.vector(p17, p23); op.vector(p17, p19);
|
||||
op.vector(p15, p21); op.vector(p15, p17); op.vector(p19, p21); op.vector(p13, p14); op.vector(p15, p16);
|
||||
op.vector(p17, p18); op.vector(p19, p20); op.vector(p21, p22); op.vector(p23, p24); op.vector(p0, p12);
|
||||
op.vector(p8, p20); op.vector(p8, p12); op.vector(p4, p16); op.vector(p16, p24); op.vector(p12, p16);
|
||||
op.vector(p2, p14); op.vector(p10, p22); op.vector(p10, p14); op.vector(p6, p18); op.vector(p6, p10);
|
||||
op.vector(p10, p12); op.vector(p1, p13); op.vector(p9, p21); op.vector(p9, p13); op.vector(p5, p17);
|
||||
op.vector(p13, p17); op.vector(p3, p15); op.vector(p11, p23); op.vector(p11, p15); op.vector(p7, p19);
|
||||
op.vector(p7, p11); op.vector(p11, p13); op.vector(p11, p12);
|
||||
*(VT*)(dst+j) = p12;
|
||||
}
|
||||
|
||||
limit = width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int medianBlur(const uchar* src_data, size_t src_step,
|
||||
uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int depth, int cn, int ksize)
|
||||
{
|
||||
bool useSortNet = ((ksize == 3) || (ksize == 5 && ( depth > CV_8U || cn == 2 || cn > 4 )));
|
||||
|
||||
if( useSortNet )
|
||||
{
|
||||
uchar* src_data_rep;
|
||||
if( dst_data == src_data ) {
|
||||
std::vector<uchar> src_data_copy(src_step * height);
|
||||
memcpy(src_data_copy.data(), src_data, src_step * height);
|
||||
src_data_rep = &src_data_copy[0];
|
||||
}
|
||||
else {
|
||||
src_data_rep = (uchar*)src_data;
|
||||
}
|
||||
|
||||
if( depth == CV_8U )
|
||||
medianBlur_SortNet<uchar, int, uint8x8_t>( src_data_rep, src_step, dst_data, dst_step, width, height, cn, ksize );
|
||||
else if( depth == CV_8S )
|
||||
medianBlur_SortNet<schar, int, int8x8_t>( src_data_rep, src_step, dst_data, dst_step, width, height, cn, ksize );
|
||||
else if( depth == CV_16U )
|
||||
medianBlur_SortNet<ushort, int, uint16x4_t>( src_data_rep, src_step, dst_data, dst_step, width, height, cn, ksize );
|
||||
else if( depth == CV_16S )
|
||||
medianBlur_SortNet<short, int, int16x4_t>( src_data_rep, src_step, dst_data, dst_step, width, height, cn, ksize );
|
||||
else
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
else return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,188 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
int remap32f(int src_type, const uchar* src_data, size_t src_step, int src_width, int src_height,
|
||||
uchar* dst_data, size_t dst_step, int dst_width, int dst_height, float* mapx, size_t mapx_step,
|
||||
float* mapy, size_t mapy_step, int interpolation, int border_type, const double border_value[4])
|
||||
{
|
||||
const bool isRelative = ((interpolation & CV_HAL_WARP_RELATIVE_MAP) != 0);
|
||||
interpolation &= ~CV_HAL_WARP_RELATIVE_MAP;
|
||||
|
||||
if( interpolation == CV_HAL_INTER_AREA )
|
||||
interpolation = CV_HAL_INTER_LINEAR;
|
||||
|
||||
if( interpolation != CV_HAL_INTER_NEAREST )
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// only CV_8U
|
||||
if( (src_type & CV_MAT_DEPTH_MASK) != CV_8U )
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
int cn = CV_MAT_CN(src_type);
|
||||
|
||||
src_step /= sizeof(uchar);
|
||||
dst_step /= sizeof(uchar);
|
||||
|
||||
// mapping CV_32FC1
|
||||
mapx_step /= sizeof(float);
|
||||
mapy_step /= sizeof(float);
|
||||
|
||||
// border
|
||||
uchar border_const[CV_CN_MAX];
|
||||
for( int k = 0; k < CV_CN_MAX; k++ )
|
||||
border_const[k] = saturate_cast<uchar>(border_value[k & 3]);
|
||||
|
||||
// divide into blocks
|
||||
const int BLOCK_SIZE = 1024;
|
||||
int x, y, x1, y1;
|
||||
std::array<short, BLOCK_SIZE * BLOCK_SIZE * 2> aXY;
|
||||
short* XY = aXY.data();
|
||||
size_t XY_step = BLOCK_SIZE * 2;
|
||||
|
||||
// vectorize
|
||||
const int32x2_t src_wh = {src_width, src_height};
|
||||
const int32x2_t arr_index = {cn, (int)src_step};
|
||||
|
||||
for (y = 0; y < dst_height; y += BLOCK_SIZE)
|
||||
{
|
||||
int dy = std::min(BLOCK_SIZE, dst_height - y);
|
||||
for (x = 0; x < dst_width; x += BLOCK_SIZE)
|
||||
{
|
||||
const int off_y = isRelative ? y : 0;
|
||||
const int off_x = isRelative ? x : 0;
|
||||
const int32x2_t voff = {off_x, off_y};
|
||||
|
||||
int dx = std::min(BLOCK_SIZE, dst_width - x);
|
||||
// prepare mapping data XY
|
||||
for (y1 = 0; y1 < dy; y1++)
|
||||
{
|
||||
short* rXY = XY + y1 * XY_step;
|
||||
const float* sX = mapx + (y + y1) * mapx_step + x;
|
||||
const float* sY = mapy + (y + y1) * mapy_step + x;
|
||||
for (x1 = 0; x1 < dx; x1++)
|
||||
{
|
||||
rXY[x1 * 2] = saturate_cast<short>(sX[x1]);
|
||||
rXY[x1 * 2 + 1] = saturate_cast<short>(sY[x1]);
|
||||
}
|
||||
}
|
||||
|
||||
// precalulate offset
|
||||
if(isRelative)
|
||||
{
|
||||
int16x8_t voff_x;
|
||||
int16x8_t voff_y = {0, 0, 1, 0, 2, 0, 3, 0};
|
||||
int16x8_t vones_x = {4, 0, 4, 0, 4, 0, 4, 0};
|
||||
int16x8_t vones_y = {0, 1, 0, 1, 0, 1, 0, 1};
|
||||
for(y1 = 0; y1 < BLOCK_SIZE; y1++, voff_y += vones_y)
|
||||
{
|
||||
int16x8_t* vrXY = (int16x8_t*)(XY + y1 * XY_step);
|
||||
for(x1 = 0, voff_x = voff_y; x1 < BLOCK_SIZE; x1 += 4, vrXY++, voff_x += vones_x)
|
||||
{
|
||||
*vrXY += voff_x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process the block
|
||||
for( y1 = 0; y1 < dy; y1++ )
|
||||
{
|
||||
uchar* dst_row = dst_data + (y + y1) * dst_step + x * cn;
|
||||
const short* rXY = XY + y1 * XY_step;
|
||||
if( cn == 1 )
|
||||
{
|
||||
for( x1 = 0; x1 < dx; x1++ )
|
||||
{
|
||||
int32x2_t vsxy = (int32x2_t){rXY[x1 * 2], rXY[x1 * 2 + 1]} + voff;
|
||||
if( (long)((uint32x2_t)vsxy < (uint32x2_t)src_wh) == -1 )
|
||||
dst_row[x1] = src_data[__nds__v_smar64(0, vsxy, arr_index)];
|
||||
else
|
||||
{
|
||||
if( border_type == CV_HAL_BORDER_REPLICATE )
|
||||
{
|
||||
vsxy = vclip(vsxy, (int32x2_t){0, 0}, src_wh);
|
||||
dst_row[x1] = src_data[__nds__v_smar64(0, vsxy, arr_index)];
|
||||
}
|
||||
else if( border_type == CV_HAL_BORDER_CONSTANT )
|
||||
dst_row[x1] = border_const[0];
|
||||
else if( border_type != CV_HAL_BORDER_TRANSPARENT )
|
||||
{
|
||||
vsxy[0] = borderInterpolate(vsxy[0], src_width, border_type);
|
||||
vsxy[1] = borderInterpolate(vsxy[1], src_height, border_type);
|
||||
dst_row[x1] = src_data[__nds__v_smar64(0, vsxy, arr_index)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uchar* dst_ptr = dst_row;
|
||||
for(x1 = 0; x1 < dx; x1++, dst_ptr += cn )
|
||||
{
|
||||
int32x2_t vsxy = (int32x2_t){rXY[x1 * 2], rXY[x1 * 2 + 1]} + voff;
|
||||
const uchar *src_ptr;
|
||||
if( (long)((uint32x2_t)vsxy < (uint32x2_t)src_wh) == -1 )
|
||||
{
|
||||
if( cn == 3 )
|
||||
{
|
||||
src_ptr = (uchar*)__nds__v_smar64((long)src_data, vsxy, arr_index);
|
||||
dst_ptr[0] = src_ptr[0]; dst_ptr[1] = src_ptr[1]; dst_ptr[2] = src_ptr[2];
|
||||
// performance loss, commented out
|
||||
// *(unsigned*)dst_ptr = __nds__bpick(*(unsigned*)dst_ptr, *(unsigned*)src_ptr, 0xFF000000);
|
||||
}
|
||||
else if( cn == 4 )
|
||||
{
|
||||
src_ptr = (uchar*)__nds__v_smar64((long)src_data, vsxy, arr_index);
|
||||
*(uint8x4_t*)dst_ptr = *(uint8x4_t*)src_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_ptr = (uchar*)__nds__v_smar64((long)src_data, vsxy, arr_index);
|
||||
int k = cn;
|
||||
for(; k >= 8; k -= 8, dst_ptr += 8, src_ptr += 8)
|
||||
*(uint8x8_t*)dst_ptr = *(uint8x8_t*)src_ptr;
|
||||
while( k-- )
|
||||
dst_ptr[k] = src_ptr[k];
|
||||
}
|
||||
}
|
||||
else if( border_type != CV_HAL_BORDER_TRANSPARENT )
|
||||
{
|
||||
if( border_type == CV_HAL_BORDER_REPLICATE )
|
||||
{
|
||||
vsxy = vclip(vsxy, (int32x2_t){0, 0}, src_wh);
|
||||
src_ptr = (uchar*)__nds__v_smar64((long)src_data, vsxy, arr_index);
|
||||
}
|
||||
else if( border_type == CV_HAL_BORDER_CONSTANT )
|
||||
src_ptr = &border_const[0];
|
||||
else
|
||||
{
|
||||
vsxy[0] = borderInterpolate(vsxy[0], src_width, border_type);
|
||||
vsxy[1] = borderInterpolate(vsxy[1], src_height, border_type);
|
||||
src_ptr = (uchar*)__nds__v_smar64((long)src_data, vsxy, arr_index);
|
||||
}
|
||||
int k = cn;
|
||||
for(; k >= 8; k -= 8, dst_ptr += 8, src_ptr += 8)
|
||||
*(uint8x8_t*)dst_ptr = *(uint8x8_t*)src_ptr;
|
||||
while( k-- )
|
||||
dst_ptr[k] = src_ptr[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,164 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
template <typename type, typename vtype>
|
||||
struct opThreshBinary_t {
|
||||
inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval)
|
||||
{
|
||||
return (vtype)__nds__bpick((long)maxval, (long)0, (long)(src > thresh));
|
||||
}
|
||||
inline type scalar(const type& src, const type& thresh, const type& maxval)
|
||||
{
|
||||
return src > thresh ? maxval : 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename type, typename vtype>
|
||||
struct opThreshBinaryInv_t {
|
||||
inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval)
|
||||
{
|
||||
return (vtype)__nds__bpick((long)0, (long)maxval, (long)(src > thresh));
|
||||
}
|
||||
inline type scalar(const type& src, const type& thresh, const type& maxval)
|
||||
{
|
||||
return src > thresh ? 0 : maxval;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename type, typename vtype>
|
||||
struct opThreshTrunc_t {
|
||||
inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval)
|
||||
{
|
||||
(void)maxval;
|
||||
return (vtype)__nds__bpick((long)thresh, (long)src, (long)(src > thresh));
|
||||
}
|
||||
inline type scalar(const type& src, const type& thresh, const type& maxval)
|
||||
{
|
||||
(void)maxval;
|
||||
return src > thresh ? thresh : src;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename type, typename vtype>
|
||||
struct opThreshToZero_t {
|
||||
inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval)
|
||||
{
|
||||
(void)maxval;
|
||||
return (vtype)__nds__bpick((long)src, (long)0, (long)(src > thresh));
|
||||
}
|
||||
inline type scalar(const type& src, const type& thresh, const type& maxval)
|
||||
{
|
||||
(void)maxval;
|
||||
return src > thresh ? src : 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename type, typename vtype>
|
||||
struct opThreshToZeroInv_t {
|
||||
inline vtype vector(const vtype& src, const vtype& thresh, const vtype& maxval)
|
||||
{
|
||||
(void)maxval;
|
||||
return (vtype)__nds__bpick((long)0, (long)src, (long)(src > thresh));
|
||||
}
|
||||
inline type scalar(const type& src, const type& thresh, const type& maxval)
|
||||
{
|
||||
(void)maxval;
|
||||
return src > thresh ? 0 : src;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename type, typename vtype, int nlane,
|
||||
template <typename ttype, typename vttype> typename opThresh_t>
|
||||
static inline void threshold_op(const uchar* src, size_t src_step,
|
||||
uchar* dst, size_t dst_step,
|
||||
int width, int height, int cn,
|
||||
double thresh_d, double maxval_d)
|
||||
{
|
||||
int i, j;
|
||||
width *= cn;
|
||||
|
||||
type* src_data = (type*)src;
|
||||
type* dst_data = (type*)dst;
|
||||
src_step /= sizeof(type);
|
||||
dst_step /= sizeof(type);
|
||||
|
||||
type thresh = saturate_cast<type>(thresh_d);
|
||||
type maxval = saturate_cast<type>(maxval_d);
|
||||
vtype vthresh;
|
||||
vtype vmaxval;
|
||||
for (i = 0; i < nlane; i++) {
|
||||
vthresh[i] = thresh;
|
||||
vmaxval[i] = maxval;
|
||||
}
|
||||
|
||||
opThresh_t<type, vtype> opThresh;
|
||||
|
||||
for (i = 0; i < height; i++, src_data += src_step, dst_data += dst_step) {
|
||||
for (j = 0; j <= width - nlane; j += nlane) {
|
||||
*(vtype*)(dst_data + j) = opThresh.vector(*(vtype*)(src_data + j), vthresh, vmaxval);
|
||||
}
|
||||
for (; j < width; j++) {
|
||||
dst_data[j] = opThresh.scalar(src_data[j], thresh, maxval);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
typedef void (*ThreshFunc)(const uchar* src_data, size_t src_step,
|
||||
uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int cn,
|
||||
double thresh, double maxval);
|
||||
|
||||
int threshold(const uchar* src_data, size_t src_step,
|
||||
uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int depth, int cn,
|
||||
double thresh, double maxValue, int thresholdType)
|
||||
{
|
||||
static ThreshFunc thfuncs[4][5] =
|
||||
{
|
||||
{
|
||||
threshold_op<uchar, uint8x8_t, 8, opThreshBinary_t>,
|
||||
threshold_op<uchar, uint8x8_t, 8, opThreshBinaryInv_t>,
|
||||
threshold_op<uchar, uint8x8_t, 8, opThreshTrunc_t>,
|
||||
threshold_op<uchar, uint8x8_t, 8, opThreshToZero_t>,
|
||||
threshold_op<uchar, uint8x8_t, 8, opThreshToZeroInv_t> },
|
||||
{
|
||||
threshold_op<char, int8x8_t, 8, opThreshBinary_t>,
|
||||
threshold_op<char, int8x8_t, 8, opThreshBinaryInv_t>,
|
||||
threshold_op<char, int8x8_t, 8, opThreshTrunc_t>,
|
||||
threshold_op<char, int8x8_t, 8, opThreshToZero_t>,
|
||||
threshold_op<char, int8x8_t, 8, opThreshToZeroInv_t> },
|
||||
{
|
||||
threshold_op<ushort, uint16x4_t, 4, opThreshBinary_t>,
|
||||
threshold_op<ushort, uint16x4_t, 4, opThreshBinaryInv_t>,
|
||||
threshold_op<ushort, uint16x4_t, 4, opThreshTrunc_t>,
|
||||
threshold_op<ushort, uint16x4_t, 4, opThreshToZero_t>,
|
||||
threshold_op<ushort, uint16x4_t, 4, opThreshToZeroInv_t> },
|
||||
{
|
||||
threshold_op<short, int16x4_t, 4, opThreshBinary_t>,
|
||||
threshold_op<short, int16x4_t, 4, opThreshBinaryInv_t>,
|
||||
threshold_op<short, int16x4_t, 4, opThreshTrunc_t>,
|
||||
threshold_op<short, int16x4_t, 4, opThreshToZero_t>,
|
||||
threshold_op<short, int16x4_t, 4, opThreshToZeroInv_t> }
|
||||
};
|
||||
|
||||
if(depth < 0 || depth > 3 || thresholdType < 0 || thresholdType > 4 || (width < 256 && height < 256))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
thfuncs[depth][thresholdType](src_data, src_step, dst_data, dst_step, width, height, cn, thresh, maxValue);
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,73 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
int warpAffineBlocklineNN(int *adelta, int *bdelta, short* xy, int X0, int Y0, int bw)
|
||||
{
|
||||
const int AB_BITS = MAX(10, (int)INTER_BITS);
|
||||
int x1 = 0;
|
||||
|
||||
for (; x1 < bw; x1 += 2) {
|
||||
int32x2_t vX = { X0 + adelta[x1], X0 + adelta[x1 + 1] };
|
||||
int32x2_t vY = { Y0 + bdelta[x1], Y0 + bdelta[x1 + 1] };
|
||||
|
||||
vX = __nds__v_sclip32(__nds__v_sra32(vX, AB_BITS), 15);
|
||||
vY = __nds__v_sclip32(__nds__v_sra32(vY, AB_BITS), 15);
|
||||
|
||||
*(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vY, (unsigned long)vX);
|
||||
}
|
||||
|
||||
for (; x1 < bw; x1++) {
|
||||
int X = X0 + adelta[x1];
|
||||
int Y = Y0 + bdelta[x1];
|
||||
xy[x1 * 2] = saturate_cast<short>(X);
|
||||
xy[x1 * 2 + 1] = saturate_cast<short>(Y);
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
int warpAffineBlockline(int *adelta, int *bdelta, short* xy, short* alpha, int X0, int Y0, int bw)
|
||||
{
|
||||
const int AB_BITS = MAX(10, (int)INTER_BITS);
|
||||
int x1 = 0;
|
||||
|
||||
const int INTER_MASK = INTER_TAB_SIZE - 1;
|
||||
const uint32x2_t vmask = { INTER_MASK, INTER_MASK };
|
||||
for (; x1 < bw; x1 += 2) {
|
||||
int32x2_t vX = { X0 + adelta[x1], X0 + adelta[x1 + 1] };
|
||||
int32x2_t vY = { Y0 + bdelta[x1], Y0 + bdelta[x1 + 1] };
|
||||
vX = __nds__v_sra32(vX, (AB_BITS - INTER_BITS));
|
||||
vY = __nds__v_sra32(vY, (AB_BITS - INTER_BITS));
|
||||
|
||||
int32x2_t vx = __nds__v_sclip32(__nds__v_sra32(vX, INTER_BITS), 15);
|
||||
int32x2_t vy = __nds__v_sclip32(__nds__v_sra32(vY, INTER_BITS), 15);
|
||||
|
||||
*(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vy, (unsigned long)vx);
|
||||
|
||||
uint32x2_t valpha = __nds__v_uadd32(__nds__v_sll32((uint32x2_t)(vY & vmask), INTER_BITS), (uint32x2_t)(vX & vmask));
|
||||
*(int16x2_t*)(alpha + x1) = (int16x2_t) { (short)(valpha[0]), (short)(valpha[1]) };
|
||||
}
|
||||
|
||||
for (; x1 < bw; x1++) {
|
||||
int X = X0 + adelta[x1];
|
||||
int Y = Y0 + bdelta[x1];
|
||||
xy[x1 * 2] = saturate_cast<short>(X >> INTER_BITS);
|
||||
xy[x1 * 2 + 1] = saturate_cast<short>(Y >> INTER_BITS);
|
||||
alpha[x1] = (short)((Y & INTER_MASK) * INTER_TAB_SIZE + (X & INTER_MASK));
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
@@ -0,0 +1,95 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "ndsrvp_hal.hpp"
|
||||
#include "opencv2/imgproc/hal/interface.h"
|
||||
#include "cvutils.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace ndsrvp {
|
||||
|
||||
int warpPerspectiveBlocklineNN(const double *M, short* xy, double X0, double Y0, double W0, int bw)
|
||||
{
|
||||
int x1 = 0;
|
||||
|
||||
for (; x1 < bw; x1 += 2) {
|
||||
double W1 = W0 + M[6] * x1, W2 = W1 + M[6];
|
||||
W1 = W1 ? 1. / W1 : 0;
|
||||
W2 = W2 ? 1. / W2 : 0;
|
||||
double fX1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W1));
|
||||
double fX2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * (x1 + 1)) * W2));
|
||||
double fY1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W1));
|
||||
double fY2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * (x1 + 1)) * W2));
|
||||
|
||||
int32x2_t vX = {saturate_cast<int>(fX1), saturate_cast<int>(fX2)};
|
||||
int32x2_t vY = {saturate_cast<int>(fY1), saturate_cast<int>(fY2)};
|
||||
|
||||
vX = __nds__v_sclip32(vX, 15);
|
||||
vY = __nds__v_sclip32(vY, 15);
|
||||
|
||||
*(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vY, (unsigned long)vX);
|
||||
}
|
||||
|
||||
for (; x1 < bw; x1++) {
|
||||
double W = W0 + M[6] * x1;
|
||||
W = W ? 1. / W : 0;
|
||||
double fX = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W));
|
||||
double fY = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W));
|
||||
int X = saturate_cast<int>(fX);
|
||||
int Y = saturate_cast<int>(fY);
|
||||
|
||||
xy[x1 * 2] = saturate_cast<short>(X);
|
||||
xy[x1 * 2 + 1] = saturate_cast<short>(Y);
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
int warpPerspectiveBlockline(const double *M, short* xy, short* alpha, double X0, double Y0, double W0, int bw)
|
||||
{
|
||||
int x1 = 0;
|
||||
|
||||
const int INTER_MASK = INTER_TAB_SIZE - 1;
|
||||
const uint32x2_t vmask = { INTER_MASK, INTER_MASK };
|
||||
for (; x1 < bw; x1 += 2) {
|
||||
double W1 = W0 + M[6] * x1, W2 = W1 + M[6];
|
||||
W1 = W1 ? INTER_TAB_SIZE / W1 : 0;
|
||||
W2 = W2 ? INTER_TAB_SIZE / W2 : 0;
|
||||
double fX1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W1));
|
||||
double fX2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * (x1 + 1)) * W2));
|
||||
double fY1 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W1));
|
||||
double fY2 = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * (x1 + 1)) * W2));
|
||||
|
||||
int32x2_t vX = {saturate_cast<int>(fX1), saturate_cast<int>(fX2)};
|
||||
int32x2_t vY = {saturate_cast<int>(fY1), saturate_cast<int>(fY2)};
|
||||
|
||||
int32x2_t vx = __nds__v_sclip32(__nds__v_sra32(vX, INTER_BITS), 15);
|
||||
int32x2_t vy = __nds__v_sclip32(__nds__v_sra32(vY, INTER_BITS), 15);
|
||||
|
||||
*(uint16x4_t*)(xy + x1 * 2) = (uint16x4_t)__nds__pkbb16((unsigned long)vy, (unsigned long)vx);
|
||||
|
||||
uint32x2_t valpha = __nds__v_uadd32(__nds__v_sll32((uint32x2_t)(vY & vmask), INTER_BITS), (uint32x2_t)(vX & vmask));
|
||||
*(int16x2_t*)(alpha + x1) = (int16x2_t) { (short)(valpha[0]), (short)(valpha[1]) };
|
||||
}
|
||||
|
||||
for (; x1 < bw; x1++) {
|
||||
double W = W0 + M[6] * x1;
|
||||
W = W ? INTER_TAB_SIZE / W : 0;
|
||||
double fX = std::max((double)INT_MIN, std::min((double)INT_MAX, (X0 + M[0] * x1) * W));
|
||||
double fY = std::max((double)INT_MIN, std::min((double)INT_MAX, (Y0 + M[3] * x1) * W));
|
||||
int X = saturate_cast<int>(fX);
|
||||
int Y = saturate_cast<int>(fY);
|
||||
|
||||
xy[x1 * 2] = saturate_cast<short>(X >> INTER_BITS);
|
||||
xy[x1 * 2 + 1] = saturate_cast<short>(Y >> INTER_BITS);
|
||||
alpha[x1] = (short)((Y & INTER_MASK) * INTER_TAB_SIZE + (X & INTER_MASK));
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
} // namespace ndsrvp
|
||||
|
||||
} // namespace cv
|
||||
Reference in New Issue
Block a user