Skip to content

Commit a615d79

Browse files
committed
Merge pull request opencv#7768 from terfendail:ovx_remap
2 parents f7d956e + 3c5eb51 commit a615d79

File tree

2 files changed

+308
-0
lines changed

2 files changed

+308
-0
lines changed

3rdparty/openvx/include/ivx.hpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,15 @@ template <> struct RefTypeTraits <vx_distribution>
361361
static vx_status release(vxType& ref) { return vxReleaseDistribution(&ref); }
362362
};
363363

364+
class Remap;
365+
template <> struct RefTypeTraits <vx_remap>
366+
{
367+
typedef vx_remap vxType;
368+
typedef Remap wrapperType;
369+
static const vx_enum vxTypeEnum = VX_TYPE_REMAP;
370+
static vx_status release(vxType& ref) { return vxReleaseRemap(&ref); }
371+
};
372+
364373
#ifdef IVX_USE_CXX98
365374

366375
/// Casting to vx_reference with compile-time check
@@ -918,6 +927,34 @@ class Context : public RefWrapper<vx_context>
918927
void setImmediateBorder(vx_enum mode, const vx_pixel_value_t& val)
919928
{ border_t bm = {mode, val}; setImmediateBorder(bm); }
920929

930+
/// vxSetContextAttribute(BORDER) wrapper
931+
template <typename T>
932+
void setImmediateBorder(vx_enum mode, const T& _val)
933+
{
934+
vx_pixel_value_t val;
935+
switch (TypeToEnum<T>::value)
936+
{
937+
case VX_TYPE_UINT8:
938+
val.U8 = _val;
939+
break;
940+
case VX_TYPE_INT16:
941+
val.S16 = _val;
942+
break;
943+
case VX_TYPE_UINT16:
944+
val.U16 = _val;
945+
break;
946+
case VX_TYPE_INT32:
947+
val.S32 = _val;
948+
break;
949+
case VX_TYPE_UINT32:
950+
val.U32 = _val;
951+
break;
952+
default:
953+
throw WrapperError("Unsupported constant border value type");
954+
}
955+
setImmediateBorder(mode, val);
956+
}
957+
921958
/// vxSetContextAttribute(BORDER) wrapper
922959
void setImmediateBorder(vx_enum mode)
923960
{ vx_pixel_value_t val = {}; setImmediateBorder(mode, val); }
@@ -1273,6 +1310,34 @@ static const vx_enum
12731310
void setBorder(vx_enum mode, const vx_pixel_value_t& val)
12741311
{ vx_border_t bm = {mode, val}; setBorder(bm); }
12751312

1313+
/// vxSetNodeAttribute(BORDER) wrapper
1314+
template <typename T>
1315+
void setBorder(vx_enum mode, const T& _val)
1316+
{
1317+
vx_pixel_value_t val;
1318+
switch (TypeToEnum<T>::value)
1319+
{
1320+
case VX_TYPE_UINT8:
1321+
val.U8 = _val;
1322+
break;
1323+
case VX_TYPE_INT16:
1324+
val.S16 = _val;
1325+
break;
1326+
case VX_TYPE_UINT16:
1327+
val.U16 = _val;
1328+
break;
1329+
case VX_TYPE_INT32:
1330+
val.S32 = _val;
1331+
break;
1332+
case VX_TYPE_UINT32:
1333+
val.U32 = _val;
1334+
break;
1335+
default:
1336+
throw WrapperError("Unsupported constant border value type");
1337+
}
1338+
setBorder(mode, val);
1339+
}
1340+
12761341
/// vxSetNodeAttribute(BORDER) wrapper
12771342
void setBorder(vx_enum mode)
12781343
{ vx_pixel_value_t val = {}; setBorder(mode, val); }
@@ -2999,6 +3064,148 @@ class Distribution : public RefWrapper<vx_distribution>
29993064
#endif //IVX_USE_OPENCV
30003065
};
30013066

3067+
/*
3068+
* Remap
3069+
*/
3070+
class Remap : public RefWrapper<vx_remap>
3071+
{
3072+
public:
3073+
IVX_REF_STD_CTORS_AND_ASSIGNMENT(Remap);
3074+
3075+
static Remap create(vx_context context, vx_uint32 src_width, vx_uint32 src_height, vx_uint32 dst_width, vx_uint32 dst_height)
3076+
{
3077+
return Remap(vxCreateRemap(context, src_width, src_height, dst_width, dst_height));
3078+
}
3079+
3080+
#ifndef VX_VERSION_1_1
3081+
static const vx_enum
3082+
VX_REMAP_SOURCE_WIDTH = VX_REMAP_ATTRIBUTE_SOURCE_WIDTH,
3083+
VX_REMAP_SOURCE_HEIGHT = VX_REMAP_ATTRIBUTE_SOURCE_HEIGHT,
3084+
VX_REMAP_DESTINATION_WIDTH = VX_REMAP_ATTRIBUTE_DESTINATION_WIDTH,
3085+
VX_REMAP_DESTINATION_HEIGHT = VX_REMAP_ATTRIBUTE_DESTINATION_HEIGHT;
3086+
#endif
3087+
3088+
template<typename T>
3089+
void query(vx_enum att, T& value) const
3090+
{ IVX_CHECK_STATUS(vxQueryRemap(ref, att, &value, sizeof(value))); }
3091+
3092+
vx_uint32 srcWidth() const
3093+
{
3094+
vx_uint32 v;
3095+
query(VX_REMAP_SOURCE_WIDTH, v);
3096+
return v;
3097+
}
3098+
3099+
vx_uint32 srcHeight() const
3100+
{
3101+
vx_uint32 v;
3102+
query(VX_REMAP_SOURCE_HEIGHT, v);
3103+
return v;
3104+
}
3105+
3106+
vx_uint32 dstWidth() const
3107+
{
3108+
vx_uint32 v;
3109+
query(VX_REMAP_DESTINATION_WIDTH, v);
3110+
return v;
3111+
}
3112+
3113+
vx_uint32 dstHeight() const
3114+
{
3115+
vx_uint32 v;
3116+
query(VX_REMAP_DESTINATION_HEIGHT, v);
3117+
return v;
3118+
}
3119+
3120+
vx_uint32 srcCoordType() const
3121+
{ return VX_TYPE_FLOAT32; }
3122+
3123+
vx_uint32 dstCoordType() const
3124+
{ return VX_TYPE_UINT32; }
3125+
3126+
void setMapping(vx_uint32 dst_x, vx_uint32 dst_y, vx_float32 src_x, vx_float32 src_y)
3127+
{ IVX_CHECK_STATUS(vxSetRemapPoint(ref, dst_x, dst_y, src_x, src_y)); }
3128+
3129+
void getMapping(vx_uint32 dst_x, vx_uint32 dst_y, vx_float32 &src_x, vx_float32 &src_y) const
3130+
{ IVX_CHECK_STATUS(vxGetRemapPoint(ref, dst_x, dst_y, &src_x, &src_y)); }
3131+
3132+
#ifdef IVX_USE_OPENCV
3133+
void setMappings(const cv::Mat& map_x, const cv::Mat& map_y)
3134+
{
3135+
if (map_x.type() != enumToCVType(srcCoordType()) || map_y.type() != enumToCVType(srcCoordType()))
3136+
throw WrapperError(std::string(__func__) + "(): mapping type is wrong");
3137+
if ((vx_uint32)(map_x.rows) != dstHeight() || (vx_uint32)(map_x.cols) != dstWidth())
3138+
throw WrapperError(std::string(__func__) + "(): x mapping size is wrong");
3139+
if ((vx_uint32)(map_y.rows) != dstHeight() || (vx_uint32)(map_y.cols) != dstWidth())
3140+
throw WrapperError(std::string(__func__) + "(): y mapping size is wrong");
3141+
3142+
for (vx_uint32 y = 0; y < dstHeight(); y++)
3143+
{
3144+
const vx_float32* map_x_line = map_x.ptr<vx_float32>(y);
3145+
const vx_float32* map_y_line = map_y.ptr<vx_float32>(y);
3146+
for (vx_uint32 x = 0; x < dstWidth(); x++)
3147+
setMapping(x, y, map_x_line[x], map_y_line[x]);
3148+
}
3149+
}
3150+
3151+
void setMappings(const cv::Mat& map)
3152+
{
3153+
if (map.depth() != CV_MAT_DEPTH(enumToCVType(srcCoordType())) || map.channels() != 2)
3154+
throw WrapperError(std::string(__func__) + "(): mapping type is wrong");
3155+
if ((vx_uint32)(map.rows) != dstHeight() || (vx_uint32)(map.cols) != dstWidth())
3156+
throw WrapperError(std::string(__func__) + "(): x mapping size is wrong");
3157+
3158+
for (vx_uint32 y = 0; y < dstHeight(); y++)
3159+
{
3160+
const vx_float32* map_line = map.ptr<vx_float32>(y);
3161+
for (vx_uint32 x = 0; x < 2*dstWidth(); x+=2)
3162+
setMapping(x, y, map_line[x], map_line[x+1]);
3163+
}
3164+
}
3165+
3166+
void getMappings(cv::Mat& map_x, cv::Mat& map_y) const
3167+
{
3168+
if (map_x.type() != enumToCVType(srcCoordType()) || map_y.type() != enumToCVType(srcCoordType()))
3169+
throw WrapperError(std::string(__func__) + "(): mapping type is wrong");
3170+
if (((vx_uint32)(map_x.rows) != dstHeight() || (vx_uint32)(map_x.cols) != dstWidth()) && !map_x.empty())
3171+
throw WrapperError(std::string(__func__) + "(): x mapping size is wrong");
3172+
if (((vx_uint32)(map_y.rows) != dstHeight() || (vx_uint32)(map_y.cols) != dstWidth()) && !map_y.empty())
3173+
throw WrapperError(std::string(__func__) + "(): y mapping size is wrong");
3174+
3175+
if (map_x.empty())
3176+
map_x = cv::Mat((int)dstHeight(), (int)dstWidth(), enumToCVType(srcCoordType()));
3177+
if (map_y.empty())
3178+
map_y = cv::Mat((int)dstHeight(), (int)dstWidth(), enumToCVType(srcCoordType()));
3179+
3180+
for (vx_uint32 y = 0; y < dstHeight(); y++)
3181+
{
3182+
vx_float32* map_x_line = map_x.ptr<vx_float32>(y);
3183+
vx_float32* map_y_line = map_y.ptr<vx_float32>(y);
3184+
for (vx_uint32 x = 0; x < dstWidth(); x++)
3185+
getMapping(x, y, map_x_line[x], map_y_line[x]);
3186+
}
3187+
}
3188+
3189+
void getMappings(cv::Mat& map) const
3190+
{
3191+
if (map.depth() != CV_MAT_DEPTH(enumToCVType(srcCoordType())) || map.channels() != 2)
3192+
throw WrapperError(std::string(__func__) + "(): mapping type is wrong");
3193+
if (((vx_uint32)(map.rows) != dstHeight() || (vx_uint32)(map.cols) != dstWidth()) && !map.empty())
3194+
throw WrapperError(std::string(__func__) + "(): x mapping size is wrong");
3195+
3196+
if (map.empty())
3197+
map = cv::Mat((int)dstHeight(), (int)dstWidth(), CV_MAKETYPE(CV_MAT_DEPTH(enumToCVType(srcCoordType())),2));
3198+
3199+
for (vx_uint32 y = 0; y < dstHeight(); y++)
3200+
{
3201+
vx_float32* map_line = map.ptr<vx_float32>(y);
3202+
for (vx_uint32 x = 0; x < 2*dstWidth(); x+=2)
3203+
getMapping(x, y, map_line[x], map_line[x+1]);
3204+
}
3205+
}
3206+
#endif //IVX_USE_OPENCV
3207+
};
3208+
30023209
/// Standard nodes
30033210
namespace nodes {
30043211

modules/imgproc/src/imgwarp.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
#include "opencl_kernels_imgproc.hpp"
5252
#include "hal_replacement.hpp"
5353

54+
#include "opencv2/core/openvx/ovx_defs.hpp"
55+
5456
using namespace cv;
5557

5658
namespace cv
@@ -4750,6 +4752,94 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst,
47504752
}
47514753
#endif
47524754

4755+
#ifdef HAVE_OPENVX
4756+
static bool openvx_remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation, const Scalar& borderValue)
4757+
{
4758+
vx_interpolation_type_e inter_type;
4759+
switch (interpolation)
4760+
{
4761+
case INTER_LINEAR:
4762+
#if VX_VERSION > VX_VERSION_1_0
4763+
inter_type = VX_INTERPOLATION_BILINEAR;
4764+
#else
4765+
inter_type = VX_INTERPOLATION_TYPE_BILINEAR;
4766+
#endif
4767+
break;
4768+
case INTER_NEAREST:
4769+
/* NEAREST_NEIGHBOR mode disabled since OpenCV round half to even while OpenVX sample implementation round half up
4770+
#if VX_VERSION > VX_VERSION_1_0
4771+
inter_type = VX_INTERPOLATION_NEAREST_NEIGHBOR;
4772+
#else
4773+
inter_type = VX_INTERPOLATION_TYPE_NEAREST_NEIGHBOR;
4774+
#endif
4775+
if (!map1.empty())
4776+
for (int y = 0; y < map1.rows; ++y)
4777+
{
4778+
float* line = map1.ptr<float>(y);
4779+
for (int x = 0; x < map1.cols; ++x)
4780+
line[x] = cvRound(line[x]);
4781+
}
4782+
if (!map2.empty())
4783+
for (int y = 0; y < map2.rows; ++y)
4784+
{
4785+
float* line = map2.ptr<float>(y);
4786+
for (int x = 0; x < map2.cols; ++x)
4787+
line[x] = cvRound(line[x]);
4788+
}
4789+
break;
4790+
*/
4791+
case INTER_AREA://AREA interpolation mode is unsupported
4792+
default:
4793+
return false;
4794+
}
4795+
4796+
try
4797+
{
4798+
ivx::Context ctx = ivx::Context::create();
4799+
4800+
Mat a;
4801+
if (dst.data != src.data)
4802+
a = src;
4803+
else
4804+
src.copyTo(a);
4805+
4806+
ivx::Image
4807+
ia = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
4808+
ivx::Image::createAddressing(a.cols, a.rows, 1, (vx_int32)(a.step)), a.data),
4809+
ib = ivx::Image::createFromHandle(ctx, VX_DF_IMAGE_U8,
4810+
ivx::Image::createAddressing(dst.cols, dst.rows, 1, (vx_int32)(dst.step)), dst.data);
4811+
4812+
//ATTENTION: VX_CONTEXT_IMMEDIATE_BORDER attribute change could lead to strange issues in multi-threaded environments
4813+
//since OpenVX standart says nothing about thread-safety for now
4814+
ivx::border_t prevBorder = ctx.immediateBorder();
4815+
ctx.setImmediateBorder(VX_BORDER_CONSTANT, (vx_uint8)(borderValue[0]));
4816+
4817+
ivx::Remap map = ivx::Remap::create(ctx, src.cols, src.rows, dst.cols, dst.rows);
4818+
if (map1.empty()) map.setMappings(map2);
4819+
else if (map2.empty()) map.setMappings(map1);
4820+
else map.setMappings(map1, map2);
4821+
ivx::IVX_CHECK_STATUS(vxuRemap(ctx, ia, map, inter_type, ib));
4822+
#ifdef VX_VERSION_1_1
4823+
ib.swapHandle();
4824+
ia.swapHandle();
4825+
#endif
4826+
4827+
ctx.setImmediateBorder(prevBorder);
4828+
}
4829+
catch (ivx::RuntimeError & e)
4830+
{
4831+
CV_Error(CV_StsInternal, e.what());
4832+
return false;
4833+
}
4834+
catch (ivx::WrapperError & e)
4835+
{
4836+
CV_Error(CV_StsInternal, e.what());
4837+
return false;
4838+
}
4839+
return true;
4840+
}
4841+
#endif
4842+
47534843
#if defined HAVE_IPP && IPP_DISABLE_BLOCK
47544844

47554845
typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi,
@@ -4852,6 +4942,17 @@ void cv::remap( InputArray _src, OutputArray _dst,
48524942
Mat src = _src.getMat(), map1 = _map1.getMat(), map2 = _map2.getMat();
48534943
_dst.create( map1.size(), src.type() );
48544944
Mat dst = _dst.getMat();
4945+
4946+
4947+
CV_OVX_RUN(
4948+
src.type() == CV_8UC1 && dst.type() == CV_8UC1 &&
4949+
(borderType& ~BORDER_ISOLATED) == BORDER_CONSTANT &&
4950+
((map1.type() == CV_32FC2 && map2.empty() && map1.size == dst.size) ||
4951+
(map1.type() == CV_32FC1 && map2.type() == CV_32FC1 && map1.size == dst.size && map2.size == dst.size) ||
4952+
(map1.empty() && map2.type() == CV_32FC2 && map2.size == dst.size)) &&
4953+
((borderType & BORDER_ISOLATED) != 0 || !src.isSubmatrix()),
4954+
openvx_remap(src, dst, map1, map2, interpolation, borderValue));
4955+
48554956
CV_Assert( dst.cols < SHRT_MAX && dst.rows < SHRT_MAX && src.cols < SHRT_MAX && src.rows < SHRT_MAX );
48564957

48574958
if( dst.data == src.data )

0 commit comments

Comments
 (0)