mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
Merge pull request #24893 from chacha21:cart_polar_inplace
Added in-place support for cartToPolar and polarToCart #24893 - a fused hal::cartToPolar[32|64]f() is used instead of sequential hal::magnitude[32|64]f/hal::fastAtan[32|64]f - ipp_polarToCart is skipped for in-place processing (it seems not to support it correctly) relates to #24891 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [X] There is a reference to the original bug report and related work - [X] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -233,16 +233,26 @@ static bool ocl_cartToPolar( InputArray _src1, InputArray _src2,
|
||||
rowsPerWI = d.isIntel() ? 4 : 1;
|
||||
bool doubleSupport = d.doubleFPConfig() > 0;
|
||||
|
||||
const bool _src1IsDstMag = (_src1.getObj() == _dst1.getObj());
|
||||
const bool _src1IsDstAngle = (_src1.getObj() == _dst2.getObj());
|
||||
const bool _src2IsDstMag = (_src2.getObj() == _dst1.getObj());
|
||||
const bool _src2IsDstAngle = (_src2.getObj() == _dst2.getObj());
|
||||
|
||||
if ( !(_src1.dims() <= 2 && _src2.dims() <= 2 &&
|
||||
(depth == CV_32F || depth == CV_64F) && type == _src2.type()) ||
|
||||
(depth == CV_64F && !doubleSupport) )
|
||||
return false;
|
||||
|
||||
ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
|
||||
format("-D BINARY_OP -D dstT=%s -D DEPTH_dst=%d -D rowsPerWI=%d -D OP_CTP_%s%s",
|
||||
format("-D BINARY_OP -D dstT=%s -D DEPTH_dst=%d -D rowsPerWI=%d -D OP_CTP_%s%s%s%s%s%s",
|
||||
ocl::typeToStr(CV_MAKE_TYPE(depth, 1)), depth,
|
||||
rowsPerWI, angleInDegrees ? "AD" : "AR",
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
_src1IsDstMag ? " -D SRC1_IS_DST_MAG" : "",
|
||||
_src1IsDstAngle ? " -D SRC1_IS_DST_ANGLE" : "",
|
||||
_src2IsDstMag ? " -D SRC2_IS_DST_MAG" : "",
|
||||
_src2IsDstAngle ? " -D SRC2_IS_DST_ANGLE" : ""
|
||||
));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
@@ -254,8 +264,8 @@ static bool ocl_cartToPolar( InputArray _src1, InputArray _src2,
|
||||
_dst2.create(size, type);
|
||||
UMat dst1 = _dst1.getUMat(), dst2 = _dst2.getUMat();
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src1),
|
||||
ocl::KernelArg::ReadOnlyNoSize(src2),
|
||||
k.args(_src1IsDstMag || _src1IsDstAngle ? ocl::KernelArg::ReadWriteNoSize(src1) : ocl::KernelArg::ReadOnlyNoSize(src1),
|
||||
_src2IsDstMag || _src2IsDstAngle ? ocl::KernelArg::ReadWriteNoSize(src2) : ocl::KernelArg::ReadOnlyNoSize(src2),
|
||||
ocl::KernelArg::WriteOnly(dst1, cn),
|
||||
ocl::KernelArg::WriteOnlyNoSize(dst2));
|
||||
|
||||
@@ -270,8 +280,7 @@ void cartToPolar( InputArray src1, InputArray src2,
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(src1.getObj() != dst1.getObj() && src1.getObj() != dst2.getObj() &&
|
||||
src2.getObj() != dst1.getObj() && src2.getObj() != dst2.getObj());
|
||||
CV_Assert(dst1.getObj() != dst2.getObj());
|
||||
|
||||
CV_OCL_RUN(dst1.isUMat() && dst2.isUMat(),
|
||||
ocl_cartToPolar(src1, src2, dst1, dst2, angleInDegrees))
|
||||
@@ -298,15 +307,13 @@ void cartToPolar( InputArray src1, InputArray src2,
|
||||
{
|
||||
const float *x = (const float*)ptrs[0], *y = (const float*)ptrs[1];
|
||||
float *mag = (float*)ptrs[2], *angle = (float*)ptrs[3];
|
||||
hal::magnitude32f( x, y, mag, len );
|
||||
hal::fastAtan32f( y, x, angle, len, angleInDegrees );
|
||||
hal::cartToPolar32f( x, y, mag, angle, len, angleInDegrees );
|
||||
}
|
||||
else
|
||||
{
|
||||
const double *x = (const double*)ptrs[0], *y = (const double*)ptrs[1];
|
||||
double *angle = (double*)ptrs[3];
|
||||
hal::magnitude64f(x, y, (double*)ptrs[2], len);
|
||||
hal::fastAtan64f(y, x, angle, len, angleInDegrees);
|
||||
double *mag = (double*)ptrs[2], *angle = (double*)ptrs[3];
|
||||
hal::cartToPolar64f(x, y, mag, angle, len, angleInDegrees);
|
||||
}
|
||||
ptrs[0] += len*esz1;
|
||||
ptrs[1] += len*esz1;
|
||||
@@ -474,15 +481,24 @@ static bool ocl_polarToCart( InputArray _mag, InputArray _angle,
|
||||
rowsPerWI = d.isIntel() ? 4 : 1;
|
||||
bool doubleSupport = d.doubleFPConfig() > 0;
|
||||
|
||||
const bool _src1IsDstX = (_mag.getObj() == _dst1.getObj());
|
||||
const bool _src1IsDstY = (_mag.getObj() == _dst2.getObj());
|
||||
const bool _src2IsDstX = (_angle.getObj() == _dst1.getObj());
|
||||
const bool _src2IsDstY = (_angle.getObj() == _dst2.getObj());
|
||||
|
||||
if ( !doubleSupport && depth == CV_64F )
|
||||
return false;
|
||||
|
||||
ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
|
||||
format("-D dstT=%s -D DEPTH_dst=%d -D rowsPerWI=%d -D BINARY_OP -D OP_PTC_%s%s",
|
||||
format("-D dstT=%s -D DEPTH_dst=%d -D rowsPerWI=%d -D BINARY_OP -D OP_PTC_%s%s%s%s%s%s",
|
||||
ocl::typeToStr(CV_MAKE_TYPE(depth, 1)), depth,
|
||||
rowsPerWI,
|
||||
angleInDegrees ? "AD" : "AR",
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "",
|
||||
_src1IsDstX ? " -D SRC1_IS_DST_X" : "",
|
||||
_src1IsDstY ? " -D SRC1_IS_DST_Y" : "",
|
||||
_src2IsDstX ? " -D SRC2_IS_DST_X" : "",
|
||||
_src2IsDstY ? " -D SRC2_IS_DST_Y" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
@@ -494,8 +510,10 @@ static bool ocl_polarToCart( InputArray _mag, InputArray _angle,
|
||||
_dst2.create(size, type);
|
||||
UMat dst1 = _dst1.getUMat(), dst2 = _dst2.getUMat();
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(mag), ocl::KernelArg::ReadOnlyNoSize(angle),
|
||||
ocl::KernelArg::WriteOnly(dst1, cn), ocl::KernelArg::WriteOnlyNoSize(dst2));
|
||||
k.args(_src1IsDstX || _src1IsDstY ? ocl::KernelArg::ReadWriteNoSize(mag) : ocl::KernelArg::ReadOnlyNoSize(mag),
|
||||
_src2IsDstX || _src2IsDstY ? ocl::KernelArg::ReadWriteNoSize(angle) : ocl::KernelArg::ReadOnlyNoSize(angle),
|
||||
ocl::KernelArg::WriteOnly(dst1, cn),
|
||||
ocl::KernelArg::WriteOnlyNoSize(dst2));
|
||||
|
||||
size_t globalsize[2] = { (size_t)dst1.cols * cn, ((size_t)dst1.rows + rowsPerWI - 1) / rowsPerWI };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
@@ -567,8 +585,13 @@ void polarToCart( InputArray src1, InputArray src2,
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(src1.getObj() != dst1.getObj() && src1.getObj() != dst2.getObj() &&
|
||||
src2.getObj() != dst1.getObj() && src2.getObj() != dst2.getObj());
|
||||
CV_Assert(dst1.getObj() != dst2.getObj());
|
||||
|
||||
const bool isInPlace =
|
||||
(src1.getObj() == dst1.getObj()) ||
|
||||
(src1.getObj() == dst2.getObj()) ||
|
||||
(src2.getObj() == dst1.getObj()) ||
|
||||
(src2.getObj() == dst2.getObj());
|
||||
|
||||
int type = src2.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
CV_Assert((depth == CV_32F || depth == CV_64F) && (src1.empty() || src1.type() == type));
|
||||
@@ -582,7 +605,7 @@ void polarToCart( InputArray src1, InputArray src2,
|
||||
dst2.create( Angle.dims, Angle.size, type );
|
||||
Mat X = dst1.getMat(), Y = dst2.getMat();
|
||||
|
||||
CV_IPP_RUN(!angleInDegrees, ipp_polarToCart(Mag, Angle, X, Y));
|
||||
CV_IPP_RUN(!angleInDegrees && !isInPlace, ipp_polarToCart(Mag, Angle, X, Y));
|
||||
|
||||
const Mat* arrays[] = {&Mag, &Angle, &X, &Y, 0};
|
||||
uchar* ptrs[4] = {};
|
||||
@@ -592,7 +615,7 @@ void polarToCart( InputArray src1, InputArray src2,
|
||||
int j, k, total = (int)(it.size*cn), blockSize = std::min(total, ((BLOCK_SIZE+cn-1)/cn)*cn);
|
||||
size_t esz1 = Angle.elemSize1();
|
||||
|
||||
if( depth == CV_64F )
|
||||
if (( depth == CV_64F ) || isInPlace)
|
||||
{
|
||||
_buf.allocate(blockSize*2);
|
||||
buf[0] = _buf.data();
|
||||
@@ -604,7 +627,7 @@ void polarToCart( InputArray src1, InputArray src2,
|
||||
for( j = 0; j < total; j += blockSize )
|
||||
{
|
||||
int len = std::min(total - j, blockSize);
|
||||
if( depth == CV_32F )
|
||||
if (( depth == CV_32F ) && !isInPlace)
|
||||
{
|
||||
const float *mag = (const float*)ptrs[0], *angle = (const float*)ptrs[1];
|
||||
float *x = (float*)ptrs[2], *y = (float*)ptrs[3];
|
||||
@@ -632,6 +655,27 @@ void polarToCart( InputArray src1, InputArray src2,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (( depth == CV_32F ) && isInPlace)
|
||||
{
|
||||
const float *mag = (const float*)ptrs[0], *angle = (const float*)ptrs[1];
|
||||
float *x = (float*)ptrs[2], *y = (float*)ptrs[3];
|
||||
|
||||
for( k = 0; k < len; k++ )
|
||||
buf[0][k] = (float)angle[k];
|
||||
|
||||
SinCos_32f( buf[0], buf[1], buf[0], len, angleInDegrees );
|
||||
if( mag )
|
||||
for( k = 0; k < len; k++ )
|
||||
{
|
||||
float m = mag[k];
|
||||
x[k] = buf[0][k]*m; y[k] = buf[1][k]*m;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(x, buf[0], sizeof(float) * len);
|
||||
std::memcpy(y, buf[1], sizeof(float) * len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const double *mag = (const double*)ptrs[0], *angle = (const double*)ptrs[1];
|
||||
@@ -649,8 +693,11 @@ void polarToCart( InputArray src1, InputArray src2,
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(x, buf[0], sizeof(float) * len);
|
||||
std::memcpy(y, buf[1], sizeof(float) * len);
|
||||
for( k = 0; k < len; k++ )
|
||||
{
|
||||
x[k] = buf[0][k];
|
||||
y[k] = buf[1][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user