Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork56.4k
Find contours speedup#26834
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
+270 −50
Merged
Find contours speedup#26834
Changes from1 commit
Commits
Show all changes
19 commits Select commitHold shift + click to select a range
085e8e3 gather preliminary work into one commit
chacha219278de7 better C++ grammar for gcc/clang
chacha214dd8408 Do not use map for contour indexing
mshabunin4a341bc use vector instead of stack
chacha21c3347a4 changed an assert
chacha21a75ad49 try to minimize allocations
chacha21e8bcc40 fixed typo not detected by MSVC
chacha21b89bb69 new storage structure for the levels of TreeIterator
chacha2173bba4d fixed move
chacha211ca692a Merge branch '4.x' into findContours_speedup
chacha213dbd4ee cleanup and optimizations
chacha21c0b747a typo not detected at compile time
chacha21b9e2403 use abstraction for Contour::codes
chacha211875ef6 use BlockStorage for codes
chacha21ce01235 remove unused debugging code
chacha219938b26 Merge remote-tracking branch 'upstream/master' into findContours_speedup
chacha2145e2d17 changes as suggested by reviewer
chacha21e6f4e8a typo
chacha21fd90ee4 indentation
chacha21File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
changes as suggested by reviewer
-class BlockStorgae has its own file-TreeIterator::levels reverted to std::stack (get rid of vectorOfRanges)-ContourPointsStorage and ContourCodesStorage are template specialization of the same class ContourDataStorage-ContourPointsStorage and ContourCodesStorage us a static size of 0 for their inner BlockStorageI have run the tstandard findContours perf_tests to check that all those changes were not a slowdown for the average case (because the current use case of the PR must not take precedence). It's ok.
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
commit45e2d177be5bd5f9898ea106c9700fb878f44e39
There are no files selected for viewing
122 changes: 122 additions & 0 deletionsmodules/imgproc/src/contours_blockstorage.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| // 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_CONTOURS_BLOCKSTORAGE_HPP | ||
| #define OPENCV_CONTOURS_BLOCKSTORAGE_HPP | ||
| #include "precomp.hpp" | ||
| #include <array> | ||
| namespace cv { | ||
| // BLOCK_SIZE_ELEM - number of elements in a block | ||
| // STATIC_CAPACITY_BYTES - static memory in bytes for preallocated blocks | ||
| template <typename T, size_t BLOCK_SIZE_ELEM = 1024, size_t STATIC_CAPACITY_BYTES = 4096> | ||
| class BlockStorage { | ||
| public: | ||
| using value_type = T; | ||
| typedef struct {value_type data[BLOCK_SIZE_ELEM];} block_type; | ||
| BlockStorage() | ||
| { | ||
| const size_t minDynamicBlocks = !staticBlocksCount ? 1 : 0; | ||
| for(size_t i = 0 ; i<minDynamicBlocks ; ++i) | ||
| dynamicBlocks.push_back(new block_type); | ||
| } | ||
| BlockStorage(const BlockStorage&) = delete; | ||
| BlockStorage(BlockStorage&&) noexcept = default; | ||
| ~BlockStorage() { | ||
| for(const auto & block : dynamicBlocks) { | ||
| delete block; | ||
| } | ||
| } | ||
| BlockStorage& operator=(const BlockStorage&) = delete; | ||
| BlockStorage& operator=(BlockStorage&&) noexcept = default; | ||
| void clear(void) { | ||
| const size_t minDynamicBlocks = !staticBlocksCount ? 1 : 0; | ||
| for(size_t i = minDynamicBlocks, count = dynamicBlocks.size() ; i<count ; ++i ) { | ||
| delete dynamicBlocks[i]; | ||
| } | ||
| dynamicBlocks.resize(minDynamicBlocks); | ||
| sz = 0; | ||
| } | ||
| void push_back(const value_type& value) { | ||
| const size_t blockIndex = sz / BLOCK_SIZE_ELEM; | ||
| const size_t currentBlocksCount = staticBlocksCount+dynamicBlocks.size(); | ||
| if (blockIndex == currentBlocksCount) | ||
| dynamicBlocks.push_back(new block_type); | ||
| block_type& cur_block = | ||
| (blockIndex < staticBlocksCount) ? staticBlocks[blockIndex] : | ||
| *dynamicBlocks[blockIndex-staticBlocksCount]; | ||
| cur_block.data[sz % BLOCK_SIZE_ELEM] = value; | ||
| ++sz; | ||
| } | ||
| size_t size() const { return sz; } | ||
| const value_type& at(size_t index) const { | ||
| const size_t blockIndex = index / BLOCK_SIZE_ELEM; | ||
| const block_type& cur_block = | ||
| (blockIndex < staticBlocksCount) ? staticBlocks[blockIndex] : | ||
| *dynamicBlocks[blockIndex-staticBlocksCount]; | ||
| return cur_block.data[index % BLOCK_SIZE_ELEM]; | ||
| } | ||
| value_type& at(size_t index) { | ||
| const size_t blockIndex = index / BLOCK_SIZE_ELEM; | ||
| block_type& cur_block = | ||
| (blockIndex < staticBlocksCount) ? staticBlocks[blockIndex] : | ||
| *dynamicBlocks[blockIndex-staticBlocksCount]; | ||
| return cur_block.data[index % BLOCK_SIZE_ELEM]; | ||
| } | ||
| const value_type& operator[](size_t index) const {return at(index);} | ||
| value_type& operator[](size_t index) {return at(index);} | ||
| public: | ||
| friend class RangeIterator; | ||
| class RangeIterator | ||
| { | ||
| public: | ||
| RangeIterator(const BlockStorage* _owner, size_t _first, size_t _last) | ||
| :owner(_owner),remaining(_last-_first), | ||
| blockIndex(_first/BLOCK_SIZE_ELEM),offset(_first%BLOCK_SIZE_ELEM) { | ||
| } | ||
| private: | ||
| const BlockStorage* owner = nullptr; | ||
| size_t remaining = 0; | ||
| size_t blockIndex = 0; | ||
| size_t offset = 0; | ||
| public: | ||
| bool done(void) const {return !remaining;} | ||
| std::pair<const value_type*, size_t> operator*(void) const {return get();} | ||
| std::pair<const value_type*, size_t> get(void) const { | ||
| const block_type& cur_block = | ||
| (blockIndex < owner->staticBlocksCount) ? owner->staticBlocks[blockIndex] : | ||
| *owner->dynamicBlocks[blockIndex-owner->staticBlocksCount]; | ||
| const value_type* rangeStart = cur_block.data+offset; | ||
| const size_t rangeLength = std::min(remaining, BLOCK_SIZE_ELEM-offset); | ||
| return std::make_pair(rangeStart, rangeLength); | ||
| } | ||
| RangeIterator& operator++() { | ||
| std::pair<const value_type*, size_t> range = get(); | ||
| remaining -= range.second; | ||
| offset = 0; | ||
| ++blockIndex; | ||
| return *this; | ||
| } | ||
| }; | ||
| RangeIterator getRangeIterator(size_t first, size_t last) const { | ||
| return RangeIterator(this, first, last); | ||
| } | ||
| private: | ||
| std::array<block_type, STATIC_CAPACITY_BYTES/(BLOCK_SIZE_ELEM*sizeof(value_type))> staticBlocks; | ||
| const size_t staticBlocksCount = STATIC_CAPACITY_BYTES/(BLOCK_SIZE_ELEM*sizeof(value_type)); | ||
| std::vector<block_type*> dynamicBlocks; | ||
| size_t sz = 0; | ||
| }; | ||
| } // namespace cv | ||
| #endif // OPENCV_CONTOURS_COMMON_HPP |
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.