CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 56.2k
first proposal of cv::remap with relative displacement field (#24603) #24621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…24603) Currently, `remap()` is applied as `dst(x, y) <- src(mapX(x, y), mapY(x, y))` It means that the maps must be filled with absolute coordinates. However, if one wants to remap something according to a displacement field ("warp"), the operation should be `dst(x, y) <- src(x+displacementX(x, y), y+displacementY(x, y))` It is trivial to build a mapping from a displacement field, but it is an undesirable overhead for CPU and memory. This PR implements the feature as an experimental option, through the optional flag WARP_RELATIVE_MAP than can be ORed to the interpolation mode. Since the xy maps might be const, there is no attempt to add the coordinate offset to those maps, and everything is postponed on-the-fly to the very last coordinate computation before fetching `src`. Interestingly, this let `cv::concertMaps()` unchanged since the fractional part of interpolation does not care of the integer coordinate offset.
locally on my machine, there is no more performance regression when cv::remap() without WARP_RELATIVE_MAP using WARP_RELATIVE_MAP always performs better than manually preprocessing the maps from displacement fields to absolute coordinates
added missing Neon in place bin_op implementation
…nto remap_relative
This reverts commit 32ebbf1.
operator += is not supported as wide as SSE
avoid operator += for wide intrinsics
use v_add instead of operator+
@vpisarev Friendly reminder. |
1 similar comment
@vpisarev Friendly reminder. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the great job! The proposed option is really very useful. I apologize for large delay caused by release and some 5.0 preparation activities. General proposals:
- Extend accuracy tests. The current test does not cover all touched cases. Also the test scenario looks very simple. As soon as absolute->relative displacement conversion is very simple the test expansion may be done easily.
- Need to add several corner cases, e.g. absolute coordinate is close to type range
- There are no performance tests. I propose to patch the existing one as in the first item.
modules/imgproc/src/imgwarp.cpp
Outdated
{ | ||
Size ssize = _src.size(), dsize = _dst.size(); | ||
const Point offset = _offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to create local variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about performance ? don't you think that keeping a reference will prevent the compiler from optimizing access to offset.x|y in the inner loops ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good question. we need performance test for it ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran performance test in the PR and do not see visible effect of additional constant inside implementation. I propose to remove it.
modules/imgproc/src/imgwarp.cpp
Outdated
const ushort* FXY, const void* _wtab, int width ) const | ||
const ushort* FXY, const void* _wtab, int width, const Point& _offset ) const | ||
{ | ||
int cn = _src.channels(), x = 0, sstep = (int)_src.step; | ||
Point rel_offset = _offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to create local variable.
modules/imgproc/src/imgwarp.cpp
Outdated
{ | ||
typedef typename CastOp::rtype T; | ||
typedef typename CastOp::type1 WT; | ||
Size ssize = _src.size(), dsize = _dst.size(); | ||
const Point offset = _offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need in local variable
modules/imgproc/src/imgwarp.cpp
Outdated
{ | ||
typedef typename CastOp::rtype T; | ||
typedef typename CastOp::type1 WT; | ||
Size ssize = _src.size(), dsize = _dst.size(); | ||
const Point offset = _offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need in local variable
cv::Mat mapRelativeX32F(size, CV_32FC1); | ||
mapRelativeX32F.setTo(cv::Scalar::all(-0.33)); | ||
|
||
cv::Mat mapRelativeY32F(size, CV_32FC1); | ||
mapRelativeY32F.setTo(cv::Scalar::all(-0.33)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to use different values for x and y to highlight x<->y swaps in code and other related offset issues.
- fixed doc to add INTER_NEAREST_EXACT as not supported - use a bu_ld constant instead of an argument for the OpenCL kernel - add comment to explain why some propably useless local variable are used - extend tests. (the covered test cases were previously just copied from original remap tests.)
A few comments after the last commit :
|
@chacha21 Thanks a lot! I added performance test for the new case. Also, please take a look on CI issues, e.g.
|
do we keep the "WARP_RELATIVE_MAP" flag ? Is there a better strategy to enable that code ? Is the name OK ? (I have not mentioned it in the doc yet) - Looks good to me. |
- fixed typo in comment - removed dead code - added WARP_RELATIVE_MAP to doc
…nto remap_relative
@chacha21, thank you for the contribution! I like how OpenCL part is implemented. It's conditionally compiled code, and so it does not affect performance of the standard case. But I don't like that in CPU version there are extra conditions inside the innermost loops. And the extra registers needed to hold the pixel grid coordinates. In subsequent versions of OpenCV we would like to optimize remap further, not to slow it down. We want to keep it clean, we want to avoid any unnecessary overhead. Here is the proposed solution. If "relative" flag is set, a tile of map(s) should be copied to a temporary buffer (probably stack-allocated buffer) and augmented there prior to calling the remap kernels instead of doing it in the remap kernels themselves. Since the offsets for x and y are integers, such method is compatible with both floating-point and the fixed-point representations of the maps. |
There is no such problem because there is
Just need to provide performance report for such modifications. |
Exactly, my first commit on this PR was a local
I will try to run the test and report ASAP (not familiar at all with the procedure) |
@chacha21, yes, I'm probably wrong about performance - I still see some unconditional things like vector registers holding the pixel coordinates. Maybe compiler will optimize it out, but maybe not. Besides, it basically duplicates all the remap kernels for such a very rarely used feature. I'd still suggest to do it externally by copying each tile of maps into a temporary buffer and augmenting it there. The kernels then will stay unchanged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please, do mapx & mapy augmentation as a separate preprocessing step (probably, tile-by-tile, to achieve cache and thread locality), not inside interpolation kernels
@vpisarev Actual :
modified :
As the first step, I just tried to observe the overhead of the allocation of m1AugmentedTile and m2AugmentedTile, with their content copied from m1 and m2 without modification. And the timing is not good. original implementation : When allocating m1AugmentedTile/m2AugmentedTile in The overhead of using m1AugmentedTile/m2AugmentedTile is from the beginning larger than the current proposal for WARP_RELATIVE_MAP. So I have to admit than WARP_RELATIVE_MAP is not free. But my idea was that the cost of using relative offsets on the fly was still cheaper than creating absolute maps from relative maps before calling What do you think ? Should I try with a stack allocation for m1AugmentedTile/m2AugmentedTile or is it a bad idea ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
the purpose of the variable was to bring locality but did not show measurable performance improvement
ok, since @asmorkalov could not reproduce any regressions on his machines, let's merge it in! |
First proposal of cv::remap with relative displacement field (opencv#24603) opencv#24621 Implements opencv#24603 Currently, `remap()` is applied as `dst(x, y) <- src(mapX(x, y), mapY(x, y))` It means that the maps must be filled with absolute coordinates. However, if one wants to remap something according to a displacement field ("warp"), the operation should be `dst(x, y) <- src(x+displacementX(x, y), y+displacementY(x, y))` It is trivial to build a mapping from a displacement field, but it is an undesirable overhead for CPU and memory. This PR implements the feature as an experimental option, through the optional flag WARP_RELATIVE_MAP than can be ORed to the interpolation mode. Since the xy maps might be const, there is no attempt to add the coordinate offset to those maps, and everything is postponed on-the-fly to the very last coordinate computation before fetching `src`. Interestingly, this let `cv::convertMaps()` unchanged since the fractional part of interpolation does not care of the integer coordinate offset. ### 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
first proposal of cv::remap with relative displacement field Relates to [#24621](opencv/opencv#24621), [#24603](opencv/opencv#24603) CUDA implementation of the feature ### 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
First proposal of cv::remap with relative displacement field (opencv#24603) opencv#24621 Implements opencv#24603 Currently, `remap()` is applied as `dst(x, y) <- src(mapX(x, y), mapY(x, y))` It means that the maps must be filled with absolute coordinates. However, if one wants to remap something according to a displacement field ("warp"), the operation should be `dst(x, y) <- src(x+displacementX(x, y), y+displacementY(x, y))` It is trivial to build a mapping from a displacement field, but it is an undesirable overhead for CPU and memory. This PR implements the feature as an experimental option, through the optional flag WARP_RELATIVE_MAP than can be ORed to the interpolation mode. Since the xy maps might be const, there is no attempt to add the coordinate offset to those maps, and everything is postponed on-the-fly to the very last coordinate computation before fetching `src`. Interestingly, this let `cv::convertMaps()` unchanged since the fractional part of interpolation does not care of the integer coordinate offset. ### 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
First proposal of cv::remap with relative displacement field (opencv#24603) opencv#24621 Implements opencv#24603 Currently, `remap()` is applied as `dst(x, y) <- src(mapX(x, y), mapY(x, y))` It means that the maps must be filled with absolute coordinates. However, if one wants to remap something according to a displacement field ("warp"), the operation should be `dst(x, y) <- src(x+displacementX(x, y), y+displacementY(x, y))` It is trivial to build a mapping from a displacement field, but it is an undesirable overhead for CPU and memory. This PR implements the feature as an experimental option, through the optional flag WARP_RELATIVE_MAP than can be ORed to the interpolation mode. Since the xy maps might be const, there is no attempt to add the coordinate offset to those maps, and everything is postponed on-the-fly to the very last coordinate computation before fetching `src`. Interestingly, this let `cv::convertMaps()` unchanged since the fractional part of interpolation does not care of the integer coordinate offset. ### 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
Implements #24603
Currently,
remap()
is applied asdst(x, y) <- src(mapX(x, y), mapY(x, y))
It means that the maps must be filled with absolute coordinates.However, if one wants to remap something according to a displacement field ("warp"), the operation should be
dst(x, y) <- src(x+displacementX(x, y), y+displacementY(x, y))
It is trivial to build a mapping from a displacement field, but it is an undesirable overhead for CPU and memory.
This PR implements the feature as an experimental option, through the optional flag WARP_RELATIVE_MAP than can be ORed to the interpolation mode.
Since the xy maps might be const, there is no attempt to add the coordinate offset to those maps, and everything is postponed on-the-fly to the very last coordinate computation before fetching
src
. Interestingly, this letcv::convertMaps()
unchanged since the fractional part of interpolation does not care of the integer coordinate offset.Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
Patch to opencv_extra has the same branch name.