-
-
Notifications
You must be signed in to change notification settings - Fork 56.2k
LineVirtualIterator #13869
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
LineVirtualIterator #13869
Conversation
Proposal of LineVirtualIterator, an alternative to "LineIterator not attached to any mat". This is basically the same implementation, replacing the address difference by a single "offset" variable. elemsize becomes irrelevant and considered to be 1. "step" is thus equal to size.width since no stride is expected.
fixed warning
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 add some accuracy tests.
modules/imgproc/src/drawing.cpp
Outdated
|
||
s = dy < 0 ? -1 : 0; | ||
dy = (dy ^ s) - s; | ||
istep = (istep ^ s) - s; |
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.
"undefined behavior"
Lets try to avoid that.
Compilers are smart enough (or at least this is not required in non "heavy" constructor calls).
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.
Not sure to understand this one. This is the LineIterator implementation; is there a problem here ?
instead of being too conservative, the new implementation gets rid of "offset/step" and only keeps a "Point currentPos" up to date. left_to_right is renamed to forceLeftToRight as suggested (even for the old LineIterator) assert() replaced by CV_Assert() (even for the old LineIterator)
some suggested improvements have been made in the new commit. [edit] [edit2] |
+fixed last commit so that LineVirtualIterator gives at least the same results as LineIterator +added a new constructor that does not require any Size, so that no clipping is done and iteration occurs from pt1 to pt2. This is done by adding a spatial offset to pt1 and pt2 so that the same implementation is used, the size being in that case the spatial size between pt1 and pt2
fixed warnings
fixed whitespace
trailing whitespace
+added a new constructor that takes a Rect rather than a Size. It computes the line pt1->pt2 that clips that rect. Yet again, this is still based on the same implementation, thanks to the Size and the currentPosOffset that can artifically consider the origin of the rect at (0,0)
I still did not update the doc in the source code, I am first waiting to know whether the pull request is accepted or not |
revert changes on original LineIterator implementation, that will be superseded by the new LineVirtualIterator anyway
@chacha21 Do you have a chance to work on some tests for the new feature? |
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 for your work!
There is a couple of improvements those can be done.
Also consider to use const
where it is possible and add spaces between math operators e.g. pos.x+offset.x%2
is quite unreadable.
@@ -4717,7 +4717,7 @@ class CV_EXPORTS LineIterator | |||
not to depend on the ordering of pt1 and pt2 parameters | |||
*/ | |||
LineIterator( const Mat& img, Point pt1, Point pt2, | |||
int connectivity = 8, bool leftToRight = false ); | |||
int connectivity = 8, bool forceLeftToRight = false ); |
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.
Documentary string should be updated too (forceLeftToRight
).
Use C++11 chained constructors Improved code style
Added offset as random test data.
Thank you for your work! |
@chacha21, thank you for the contribution! I think, in this class it makes sense to modify implementation of Bresenham algorithm to operate directly on the pixel coordinates. With current implementation it's so slow that we can basically use the original class, just add an extra constructor to it. |
const int offset = minusStep + (plusStep & mask); | ||
const size_t flattenedCoord = (currentPos.y - currentPosOffset.y) * size.width + (currentPos.x - currentPosOffset.x) + offset; | ||
currentPos.y = static_cast<int>((flattenedCoord / size.width) + currentPosOffset.y); | ||
currentPos.x = static_cast<int>((flattenedCoord % size.width) + currentPosOffset.x); |
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.
basically, I mean that these 2 lines (currentPos.y=...; currentPos.x=...;
) should be removed; instead, you should update currentPos directly using the Bresenham algorithm
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 current implementation is rather far from standard Bresenham's algorithm descriptions, so it is not that straightfoward to rewrite differently all the cases in both 4 and 8 connectivity.
@chacha21, @asmorkalov, I've updated the implementation, made it one class, not two. Hopefully, it's good enough to be merged |
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.
See comments in previous patch about that: #13843 (mentioned in PR description)
added one perfectly predictable check; in theory, since ptmode is set in the end of the constructor in the header file, the compiler can figure out that it's always true/false and eliminate the check from the inline `LineIterator::operator++()` completely
in the most common case (CV_8UC3) eliminated the check from the loop
@alalek, can we merge it? |
* LineVirtualIterator Proposal of LineVirtualIterator, an alternative to "LineIterator not attached to any mat". This is basically the same implementation, replacing the address difference by a single "offset" variable. elemsize becomes irrelevant and considered to be 1. "step" is thus equal to size.width since no stride is expected. * Update drawing.cpp fixed warning * improvement of LineVirtualIterator instead of being too conservative, the new implementation gets rid of "offset/step" and only keeps a "Point currentPos" up to date. left_to_right is renamed to forceLeftToRight as suggested (even for the old LineIterator) assert() replaced by CV_Assert() (even for the old LineIterator) * fixed implementation +fixed last commit so that LineVirtualIterator gives at least the same results as LineIterator +added a new constructor that does not require any Size, so that no clipping is done and iteration occurs from pt1 to pt2. This is done by adding a spatial offset to pt1 and pt2 so that the same implementation is used, the size being in that case the spatial size between pt1 and pt2 * Update imgproc.hpp fixed warnings * Update drawing.cpp fixed whitespace * Update drawing.cpp trailing whitespace * Update imgproc.hpp +added a new constructor that takes a Rect rather than a Size. It computes the line pt1->pt2 that clips that rect. Yet again, this is still based on the same implementation, thanks to the Size and the currentPosOffset that can artifically consider the origin of the rect at (0,0) * revert changes revert changes on original LineIterator implementation, that will be superseded by the new LineVirtualIterator anyway * added test of LineVirtualIterator * More tests * refactoring Use C++11 chained constructors Improved code style * improve test Added offset as random test data. * fixed order of initialization * merged LineIterator and VirtualLineIterator * merged LineIterator & VirtualLineIterator * merged LineIterator & VirtualLineIterator * merged LineIterator & VirtualLineIterator * made LineIterator::operator ++() more efficient added one perfectly predictable check; in theory, since ptmode is set in the end of the constructor in the header file, the compiler can figure out that it's always true/false and eliminate the check from the inline `LineIterator::operator++()` completely * optimized Line() function in the most common case (CV_8UC3) eliminated the check from the loop Co-authored-by: Vadim Pisarevsky <vadim.pisarevsky@gmail.com>
Proposal of LineVirtualIterator, an alternative to "LineIterator not attached to any mat".
This is basically the same implementation, replacing the address difference by a single "offset" variable. elemsize becomes irrelevant and considered to be 1. "step" is thus equal to size.width since no stride is expected.
related to #13843