From 9c7b767aa1ea6edf739fc46521bd25905f0ffac9 Mon Sep 17 00:00:00 2001 From: Jeerhz Date: Thu, 15 Jan 2026 16:22:25 +0100 Subject: [PATCH 1/7] stack node version of the other chains extraction --- ED-perso.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ED-perso.h | 1 + 2 files changed, 61 insertions(+) diff --git a/ED-perso.cpp b/ED-perso.cpp index b64dcbf..d00fdf9 100644 --- a/ED-perso.cpp +++ b/ED-perso.cpp @@ -545,6 +545,66 @@ void ED::extractOtherChains(Chain *anchor_chain_root, std::vector> &anchorSegments) +{ + // We assume that main children chains have already been extracted + // Store the pointer to the main children in order to skip them + Chain *main_first_child = anchor_chain_root->first_childChain; + Chain *main_second_child = anchor_chain_root->second_childChain; + + // Explore the whole chain depth first + std::stack chain_stack; + chain_stack.push(anchor_chain_root); + + while (!chain_stack.empty()) + { + Chain *current_chain = chain_stack.top(); + chain_stack.pop(); + + if (current_chain == nullptr) + continue; + + // Compute the longest path from the current chain + int nb_pixels_longest_path = current_chain->pruneToLongestChain(); + + // add the child that is not part of the longest path in the stack + if (current_chain->is_first_childChain_longest_path) + chain_stack.push(current_chain->second_childChain); + else + chain_stack.push(current_chain->first_childChain); + + // Skip the extraction of the main children chains (already extracted) or if the longest path is too short + if (current_chain == main_first_child || current_chain == main_second_child || nb_pixels_longest_path < minPathLen) + continue; + + // Extraction of the longest path of the current chain into a new segment + std::pair> all_chains_resp = current_chain->getAllChains(true); + std::vector chainChilds_in_longest_path = all_chains_resp.second; + + // Initialize a segment that will hold the points of the current chain longest path + std::vector currentSegment; + // Extract the pixels and add them to the current segment + for (size_t chain_index = 0; chain_index < chainChilds_in_longest_path.size(); ++chain_index) + { + Chain *child_chain = chainChilds_in_longest_path[chain_index]; + if (!child_chain) + break; + + cleanUpPenultimateSegmentPixel(child_chain, currentSegment, true); + + for (size_t pixel_index = 0; pixel_index < child_chain->pixels.size(); ++pixel_index) + currentSegment.push_back(Point(child_chain->pixels[pixel_index] % image_width, child_chain->pixels[pixel_index] / image_width)); + } + + // If the current segment is not empty, add it to the anchor segments + if (!currentSegment.empty()) + anchorSegments.push_back(currentSegment); + } +} + void ED::extractSegmentsFromChain(Chain *anchor_chain_root, std::vector> &anchorSegments) { if (!anchor_chain_root) diff --git a/ED-perso.h b/ED-perso.h index fe2a158..6db33b5 100644 --- a/ED-perso.h +++ b/ED-perso.h @@ -63,6 +63,7 @@ class ED void extractSecondChildChains(Chain *anchor_chain_root, std::vector &anchorSegment); void extractFirstChildChains(Chain *anchor_chain_root, std::vector &anchorSegment); void extractOtherChains(Chain *anchor_chain_root, std::vector> &anchorSegments); + void extractOtherChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments); int *sortAnchorsByGradValue(); void cleanUpSurroundingAnchorPixels(StackNode ¤t_node); From 2dbc91c2a9b3d674af75fc908acd04af7d26ee10 Mon Sep 17 00:00:00 2001 From: Jeerhz Date: Thu, 15 Jan 2026 18:28:51 +0100 Subject: [PATCH 2/7] unique reccursion segment extraction for chains --- Chain.cpp | 3 - Chain.h | 1 - ED-perso.cpp | 161 +++++++++------------------------------------------ ED-perso.h | 6 +- 4 files changed, 28 insertions(+), 143 deletions(-) diff --git a/Chain.cpp b/Chain.cpp index 2410f0a..55c1164 100644 --- a/Chain.cpp +++ b/Chain.cpp @@ -48,9 +48,6 @@ std::pair> Chain::getAllChains(bool only_longest_path) void Chain::appendAllChains(std::vector &allChains, int &total_length, bool only_longest_path) { - if (only_longest_path && this->is_extracted) - return; - allChains.push_back(this); total_length += pixels.size(); if (first_childChain && (!only_longest_path || is_first_childChain_longest_path)) diff --git a/Chain.h b/Chain.h index c751eef..8e393a9 100644 --- a/Chain.h +++ b/Chain.h @@ -26,7 +26,6 @@ struct Chain Chain *const parent_chain; // Pointer to parent chain (never changes after init) Chain *first_childChain; // Pointer to left/up child chain bool is_first_childChain_longest_path; // Flag to indicate if this is the longest path use first child - bool is_extracted = false; // Flag to indicate if this chain has been extracted into a segment Chain *second_childChain; // Pointer to right/down child chain const Direction direction; // Direction of this chain (never changes after init) diff --git a/ED-perso.cpp b/ED-perso.cpp index d00fdf9..0323565 100644 --- a/ED-perso.cpp +++ b/ED-perso.cpp @@ -423,7 +423,7 @@ bool ED::areNeighbors(int offset1, int offset2) return (row_distance <= 1 && col_distance <= 1); } -// We take the last or first pixel of the current processed chain and clean its neighbors in the segment +// We take the last (or first for the first child chain) pixel of the current processed chain and clean its neighbors in the segment void ED::cleanUpPenultimateSegmentPixel(Chain *chain, std::vector &anchorSegment, bool is_first_child) { if (!chain || chain->pixels.empty()) @@ -443,117 +443,17 @@ void ED::cleanUpPenultimateSegmentPixel(Chain *chain, std::vector &an } } -// Backward extraction, we start from the end of the latest sub chain and move towards the anchor root -void ED::extractSecondChildChains(Chain *anchor_chain_root, std::vector &anchorSegment) -{ - if (!anchor_chain_root || !anchor_chain_root->second_childChain) - return; - - std::pair> resp = anchor_chain_root->second_childChain->getAllChains(true); - std::vector all_second_child_chains_in_longest_path = resp.second; - - // iterate through all sub chains in the longest path, clean and add pixels to the anchor segment - for (size_t chain_index = all_second_child_chains_in_longest_path.size() - 1; chain_index > 0; --chain_index) - { - Chain *chain = all_second_child_chains_in_longest_path[chain_index]; - if (!chain || chain->is_extracted) - break; - - cleanUpPenultimateSegmentPixel(chain, anchorSegment, false); - - // add the chain pixels to the anchor segment - for (int pixel_index = (int)chain->pixels.size() - 1; pixel_index >= 0; --pixel_index) - { - int pixel_offset = chain->pixels[pixel_index]; - anchorSegment.push_back(Point(pixel_offset % image_width, pixel_offset / image_width)); - } - chain->is_extracted = true; - } -} - -// Forward extraction, we start from the anchor root, and go deeper -void ED::extractFirstChildChains(Chain *anchor_chain_root, std::vector &anchorSegment) -{ - if (!anchor_chain_root || !anchor_chain_root->first_childChain) - return; - - std::pair> resp = anchor_chain_root->first_childChain->getAllChains(true); - std::vector all_first_child_chains_in_longest_path = resp.second; - - for (size_t chain_index = 0; chain_index < all_first_child_chains_in_longest_path.size(); ++chain_index) - { - Chain *chain = all_first_child_chains_in_longest_path[chain_index]; - if (!chain || chain->is_extracted) - break; - - cleanUpPenultimateSegmentPixel(chain, anchorSegment, true); - - for (size_t pixel_index = 0; pixel_index < chain->pixels.size(); ++pixel_index) - { - int pixel_offset = chain->pixels[pixel_index]; - anchorSegment.push_back(Point(pixel_offset % image_width, pixel_offset / image_width)); - } - chain->is_extracted = true; - } -} - -// Extract the remaining significant chains that are not part of the main anchor segment -void ED::extractOtherChains(Chain *anchor_chain_root, std::vector> &anchorSegments) -{ - if (!anchor_chain_root) - return; - - std::pair> resp_all = anchor_chain_root->getAllChains(false); - // This is all chains in the anchor root, traversed depth-first adding the first child first. - std::vector all_anchor_root_chains = resp_all.second; - - // Start the iteration from the anchor root and go deeper - for (size_t k = 0; k < all_anchor_root_chains.size(); ++k) - { - Chain *other_chain = all_anchor_root_chains[k]; - if (!other_chain) - continue; - - std::vector otherAnchorSegment; - other_chain->pruneToLongestChain(); - - std::pair> other_resp = other_chain->getAllChains(true); - int other_chain_total_length = other_resp.first; - std::vector other_chain_chainChilds_in_longest_path = other_resp.second; - - if (other_chain_total_length < minPathLen) - continue; - - for (size_t chain_index = 0; chain_index < other_chain_chainChilds_in_longest_path.size(); ++chain_index) - { - Chain *other_chain_childChain = other_chain_chainChilds_in_longest_path[chain_index]; - if (!other_chain_childChain || other_chain_childChain->is_extracted) - break; - - cleanUpPenultimateSegmentPixel(other_chain_childChain, otherAnchorSegment, true); - - for (size_t pixel_index = 0; pixel_index < other_chain_childChain->pixels.size(); ++pixel_index) - { - int pixel_offset = other_chain_childChain->pixels[pixel_index]; - otherAnchorSegment.push_back(Point(pixel_offset % image_width, pixel_offset / image_width)); - } - other_chain_childChain->is_extracted = true; - } - - if (!otherAnchorSegment.empty()) - anchorSegments.push_back(otherAnchorSegment); - } -} - // Explore the binary graph by depth first from the children of the anchor root. // Prune the considered node to its longest path. Add the childnode that is not from longest path to the processed stack // Call cleanUpPenultimateSegmentPixel with a forward pass, add the chains pixels to the segment before processing to the next stack node -void ED::extractOtherChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments) +// To reconstruct the main segment, when we arrive to the segment from the second main child, we revert the segment and add it to the first segment. +void ED::extractChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments) { // We assume that main children chains have already been extracted - // Store the pointer to the main children in order to skip them + // Store the pointer to the main children in order to reconstruct the 'main segment' Chain *main_first_child = anchor_chain_root->first_childChain; Chain *main_second_child = anchor_chain_root->second_childChain; + bool is_first_pass = true; // Explore the whole chain depth first std::stack chain_stack; @@ -577,7 +477,7 @@ void ED::extractOtherChainsRecur(Chain *anchor_chain_root, std::vectorfirst_childChain); // Skip the extraction of the main children chains (already extracted) or if the longest path is too short - if (current_chain == main_first_child || current_chain == main_second_child || nb_pixels_longest_path < minPathLen) + if (nb_pixels_longest_path < minPathLen) continue; // Extraction of the longest path of the current chain into a new segment @@ -599,36 +499,29 @@ void ED::extractOtherChainsRecur(Chain *anchor_chain_root, std::vectorpixels[pixel_index] % image_width, child_chain->pixels[pixel_index] / image_width)); } - // If the current segment is not empty, add it to the anchor segments - if (!currentSegment.empty()) - anchorSegments.push_back(currentSegment); - } -} - -void ED::extractSegmentsFromChain(Chain *anchor_chain_root, std::vector> &anchorSegments) -{ - if (!anchor_chain_root) - return; - - std::vector anchorSegment; - - // second child (backward) - extractSecondChildChains(anchor_chain_root, anchorSegment); - - // first child (forward) - extractFirstChildChains(anchor_chain_root, anchorSegment); + if (currentSegment.empty()) + { + is_first_pass = false; + continue; + } - // Clean possible boucle at the beginning of the segment - if (anchorSegment.size() > 1 && areNeighbors(anchorSegment[1].y * image_width + anchorSegment[1].x, - anchorSegment.back().y * image_width + anchorSegment.back().x)) - anchorSegment.erase(anchorSegment.begin()); + // If the current segment is not empty, add it to the anchor segments or to the main segment for the main childs + // Clean possible boucle at the beginning of the segment + if (currentSegment.size() > 1 && areNeighbors(currentSegment[1].y * image_width + currentSegment[1].x, + currentSegment.back().y * image_width + currentSegment.back().x)) + currentSegment.erase(currentSegment.begin()); - // Add the main anchor segment to the anchor segments (only if non-empty) - if (!anchorSegment.empty()) - anchorSegments.push_back(anchorSegment); + if ((current_chain == main_first_child || current_chain == main_second_child) && !is_first_pass) + { + // Revert the order of the main child segment and add it to the first segment + std::reverse(currentSegment.begin(), currentSegment.end()); + anchorSegments[0].insert(anchorSegments[0].end(), currentSegment.begin(), currentSegment.end()); + } + else + anchorSegments.push_back(currentSegment); - // other long segments attached to anchor root - extractOtherChains(anchor_chain_root, anchorSegments); + is_first_pass = false; + } } void ED::JoinAnchorPointsUsingSortedAnchors() @@ -682,7 +575,7 @@ void ED::JoinAnchorPointsUsingSortedAnchors() anchor_chain_root->second_childChain->pruneToLongestChain(); // Create a segment corresponding to this anchor chain std::vector> anchorSegments; - extractSegmentsFromChain(anchor_chain_root, anchorSegments); + extractChainsRecur(anchor_chain_root, anchorSegments); segmentPoints.insert(segmentPoints.end(), anchorSegments.begin(), anchorSegments.end()); } diff --git a/ED-perso.h b/ED-perso.h index 6db33b5..be3b216 100644 --- a/ED-perso.h +++ b/ED-perso.h @@ -59,11 +59,7 @@ class ED void ComputeAnchorPoints(); void JoinAnchorPointsUsingSortedAnchors(); void exploreChain(StackNode ¤t_node, Chain *current_chain, int &total_pixels_in_anchor_chain); - void extractSegmentsFromChain(Chain *chain, std::vector> &anchorSegments); - void extractSecondChildChains(Chain *anchor_chain_root, std::vector &anchorSegment); - void extractFirstChildChains(Chain *anchor_chain_root, std::vector &anchorSegment); - void extractOtherChains(Chain *anchor_chain_root, std::vector> &anchorSegments); - void extractOtherChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments); + void extractChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments); int *sortAnchorsByGradValue(); void cleanUpSurroundingAnchorPixels(StackNode ¤t_node); From b255ed8b5459258f1800898bc47099703f9daf00 Mon Sep 17 00:00:00 2001 From: Jeerhz Date: Thu, 15 Jan 2026 18:50:58 +0100 Subject: [PATCH 3/7] fix: correct validation in exploreChain perpendicular --- ED-perso.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/ED-perso.cpp b/ED-perso.cpp index 0323565..5f0a420 100644 --- a/ED-perso.cpp +++ b/ED-perso.cpp @@ -553,13 +553,11 @@ void ED::JoinAnchorPointsUsingSortedAnchors() while (!process_stack.empty()) { + std::cout << "Processing stack node at offset: " << process_stack.top().offset << std::endl; + std::cout << "Stack Size: " << process_stack.size() << std::endl; StackNode currentNode = process_stack.top(); process_stack.pop(); - // processed stack pixel are in two chains in opposite directions, we track duplicates - if (edgeImgPointer[currentNode.offset] != EDGE_PIXEL) - total_pixels_in_anchor_chain--; - Chain *new_process_stack_chain = new Chain(currentNode.node_direction, currentNode.parent_chain); setChildToChain(new_process_stack_chain->parent_chain, new_process_stack_chain); // Explore from the stack node to add more pixels to the new created chain @@ -638,7 +636,6 @@ StackNode ED::getNextChainPixel(StackNode ¤t_node) void ED::exploreChain(StackNode ¤t_node, Chain *current_chain, int &total_pixels_in_anchor_chain) { - GradOrientation chain_orientation = current_chain->direction == LEFT || current_chain->direction == RIGHT ? EDGE_HORIZONTAL : EDGE_VERTICAL; // Explore until we find change direction or we hit an edge pixel or the gradient is below threshold while (gradOrientationImgPointer[current_node.offset] == chain_orientation) @@ -668,18 +665,18 @@ void ED::exploreChain(StackNode ¤t_node, Chain *current_chain, int &total_ { // Add UP and DOWN for horizontal chains if the pixels are valid // The border pixels were set to a low gradient threshold, so we do not need to check for out of bounds access - if (edgeImgPointer[current_node.offset + image_width] == EDGE_PIXEL || gradImgPointer[current_node.offset + image_width] < gradThresh) - process_stack.push(StackNode(current_node.offset, DOWN, current_chain)); - if (edgeImgPointer[current_node.offset - image_width] == EDGE_PIXEL || gradImgPointer[current_node.offset - image_width] < gradThresh) - process_stack.push(StackNode(current_node.offset, UP, current_chain)); + if (edgeImgPointer[current_node.offset + image_width] != EDGE_PIXEL && gradImgPointer[current_node.offset + image_width] >= gradThresh) + process_stack.push(StackNode(current_node.offset + image_width, DOWN, current_chain)); + if (edgeImgPointer[current_node.offset - image_width] != EDGE_PIXEL && gradImgPointer[current_node.offset - image_width] >= gradThresh) + process_stack.push(StackNode(current_node.offset - image_width, UP, current_chain)); } else { // Add LEFT and RIGHT for vertical chains - if (edgeImgPointer[current_node.offset + 1] == EDGE_PIXEL || gradImgPointer[current_node.offset + 1] < gradThresh) - process_stack.push(StackNode(current_node.offset, RIGHT, current_chain)); - if (edgeImgPointer[current_node.offset - 1] == EDGE_PIXEL || gradImgPointer[current_node.offset - 1] < gradThresh) - process_stack.push(StackNode(current_node.offset, LEFT, current_chain)); + if (edgeImgPointer[current_node.offset + 1] != EDGE_PIXEL && gradImgPointer[current_node.offset + 1] >= gradThresh) + process_stack.push(StackNode(current_node.offset + 1, RIGHT, current_chain)); + if (edgeImgPointer[current_node.offset - 1] != EDGE_PIXEL && gradImgPointer[current_node.offset - 1] >= gradThresh) + process_stack.push(StackNode(current_node.offset - 1, LEFT, current_chain)); } } From 2766d93ee024d0cb977aea4b4105fd7f55c6f1dd Mon Sep 17 00:00:00 2001 From: Jeerhz Date: Thu, 15 Jan 2026 19:28:45 +0100 Subject: [PATCH 4/7] refactor: update parameter passing for cleanUpSurroundingAnchorPixels and getNextChainPixel functions --- ED-perso.cpp | 32 ++++++++++++++++++-------------- ED-perso.h | 4 ++-- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ED-perso.cpp b/ED-perso.cpp index 5f0a420..1c536d3 100644 --- a/ED-perso.cpp +++ b/ED-perso.cpp @@ -535,22 +535,22 @@ void ED::JoinAnchorPointsUsingSortedAnchors() if (edgeImgPointer[anchorPixelOffset] != ANCHOR_PIXEL) continue; - int total_pixels_in_anchor_chain = 0; // Count total pixels in the anchor chain and its children - Chain *anchor_chain_root = new Chain(); // We initialize two distinct nodes to start anchor chain exploration in order to avoid duplicate pixels from the start. // This is not done in the original implementation where we set the anchor point two times if (gradOrientationImgPointer[anchorPixelOffset] == EDGE_VERTICAL) { process_stack.push(StackNode(anchorPixelOffset, DOWN, anchor_chain_root)); - process_stack.push(StackNode(anchorPixelOffset - image_width, UP, anchor_chain_root)); + process_stack.push(StackNode(anchorPixelOffset, UP, anchor_chain_root)); } else { process_stack.push(StackNode(anchorPixelOffset, RIGHT, anchor_chain_root)); - process_stack.push(StackNode(anchorPixelOffset - 1, LEFT, anchor_chain_root)); + process_stack.push(StackNode(anchorPixelOffset, LEFT, anchor_chain_root)); } + int total_pixels_in_anchor_chain = -1; // Count total pixels in the anchor chain and its children. Start at one for the duplicate anchor. + while (!process_stack.empty()) { std::cout << "Processing stack node at offset: " << process_stack.top().offset << std::endl; @@ -583,7 +583,7 @@ void ED::JoinAnchorPointsUsingSortedAnchors() } // Clean pixel perpendicular to edge direction -void ED::cleanUpSurroundingAnchorPixels(StackNode ¤t_node) +void ED::cleanUpSurroundingAnchorPixels(const StackNode ¤t_node) { int offset = current_node.offset; int offset_diff = (current_node.node_direction == LEFT || current_node.node_direction == RIGHT) ? image_width : 1; @@ -597,7 +597,7 @@ void ED::cleanUpSurroundingAnchorPixels(StackNode ¤t_node) } // Get next pixel in the chain based on current node direction and gradient values -StackNode ED::getNextChainPixel(StackNode ¤t_node) +StackNode ED::getNextChainPixel(const StackNode ¤t_node) { const int offset = current_node.offset; const Direction dir = current_node.node_direction; @@ -665,18 +665,22 @@ void ED::exploreChain(StackNode ¤t_node, Chain *current_chain, int &total_ { // Add UP and DOWN for horizontal chains if the pixels are valid // The border pixels were set to a low gradient threshold, so we do not need to check for out of bounds access - if (edgeImgPointer[current_node.offset + image_width] != EDGE_PIXEL && gradImgPointer[current_node.offset + image_width] >= gradThresh) - process_stack.push(StackNode(current_node.offset + image_width, DOWN, current_chain)); - if (edgeImgPointer[current_node.offset - image_width] != EDGE_PIXEL && gradImgPointer[current_node.offset - image_width] >= gradThresh) - process_stack.push(StackNode(current_node.offset - image_width, UP, current_chain)); + StackNode up_next_node = getNextChainPixel(StackNode(current_node.offset, UP, current_chain)); + StackNode down_next_node = getNextChainPixel(StackNode(current_node.offset, DOWN, current_chain)); + if (edgeImgPointer[down_next_node.offset] != EDGE_PIXEL && gradImgPointer[down_next_node.offset] >= gradThresh) + process_stack.push(down_next_node); + if (edgeImgPointer[up_next_node.offset] != EDGE_PIXEL && gradImgPointer[up_next_node.offset] >= gradThresh) + process_stack.push(up_next_node); } else { + StackNode left_next_node = getNextChainPixel(StackNode(current_node.offset, LEFT, current_chain)); + StackNode right_next_node = getNextChainPixel(StackNode(current_node.offset, RIGHT, current_chain)); // Add LEFT and RIGHT for vertical chains - if (edgeImgPointer[current_node.offset + 1] != EDGE_PIXEL && gradImgPointer[current_node.offset + 1] >= gradThresh) - process_stack.push(StackNode(current_node.offset + 1, RIGHT, current_chain)); - if (edgeImgPointer[current_node.offset - 1] != EDGE_PIXEL && gradImgPointer[current_node.offset - 1] >= gradThresh) - process_stack.push(StackNode(current_node.offset - 1, LEFT, current_chain)); + if (edgeImgPointer[left_next_node.offset] != EDGE_PIXEL && gradImgPointer[left_next_node.offset] >= gradThresh) + process_stack.push(left_next_node); + if (edgeImgPointer[right_next_node.offset] != EDGE_PIXEL && gradImgPointer[right_next_node.offset] >= gradThresh) + process_stack.push(right_next_node); } } diff --git a/ED-perso.h b/ED-perso.h index be3b216..39e0242 100644 --- a/ED-perso.h +++ b/ED-perso.h @@ -62,8 +62,8 @@ class ED void extractChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments); int *sortAnchorsByGradValue(); - void cleanUpSurroundingAnchorPixels(StackNode ¤t_node); - StackNode getNextChainPixel(StackNode ¤t_node); + void cleanUpSurroundingAnchorPixels(const StackNode ¤t_node); + StackNode getNextChainPixel(const StackNode ¤t_node); bool areNeighbors(int offset1, int offset2); void cleanUpPenultimateSegmentPixel(Chain *chain, std::vector &anchorSegment, bool is_first_child); void revertChainEdgePixel(Chain *&chain); From 24ed19bab6b2215dd718b976444207bbeff62223 Mon Sep 17 00:00:00 2001 From: Jeerhz Date: Thu, 15 Jan 2026 19:37:25 +0100 Subject: [PATCH 5/7] refactor: enhance cleanUpSurroundingAnchorPixels to optionally clear perpendicular pixels --- ED-perso.cpp | 15 +++++++++++++-- ED-perso.h | 2 +- test_ED.cpp | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ED-perso.cpp b/ED-perso.cpp index 1c536d3..d5218db 100644 --- a/ED-perso.cpp +++ b/ED-perso.cpp @@ -583,10 +583,11 @@ void ED::JoinAnchorPointsUsingSortedAnchors() } // Clean pixel perpendicular to edge direction -void ED::cleanUpSurroundingAnchorPixels(const StackNode ¤t_node) +void ED::cleanUpSurroundingAnchorPixels(const StackNode ¤t_node, bool clear_perpendicular) { int offset = current_node.offset; int offset_diff = (current_node.node_direction == LEFT || current_node.node_direction == RIGHT) ? image_width : 1; + int perpendicular_offset_diff = (current_node.node_direction == LEFT || current_node.node_direction == RIGHT) ? 1 : image_width; // Left/up neighbor if (edgeImgPointer[offset - offset_diff] == ANCHOR_PIXEL) @@ -594,6 +595,16 @@ void ED::cleanUpSurroundingAnchorPixels(const StackNode ¤t_node) // Right/down neighbor if (edgeImgPointer[offset + offset_diff] == ANCHOR_PIXEL) edgeImgPointer[offset + offset_diff] = 0; + + if (clear_perpendicular) + { + // Left/up neighbor + if (edgeImgPointer[offset - perpendicular_offset_diff] == ANCHOR_PIXEL) + edgeImgPointer[offset - perpendicular_offset_diff] = 0; + // Right/down neighbor + if (edgeImgPointer[offset + perpendicular_offset_diff] == ANCHOR_PIXEL) + edgeImgPointer[offset + perpendicular_offset_diff] = 0; + } } // Get next pixel in the chain based on current node direction and gradient values @@ -657,7 +668,7 @@ void ED::exploreChain(StackNode ¤t_node, Chain *current_chain, int &total_ current_chain->pixels.push_back(current_node.offset); total_pixels_in_anchor_chain++; edgeImgPointer[current_node.offset] = EDGE_PIXEL; - cleanUpSurroundingAnchorPixels(current_node); + cleanUpSurroundingAnchorPixels(current_node, true); // We add new nodes to the process stack in perpendicular directions to the edge with reference to this chain as a parent // This is different from the original implementation where the above node is the starting of the perpendicular sub-chains diff --git a/ED-perso.h b/ED-perso.h index 39e0242..8c35aa7 100644 --- a/ED-perso.h +++ b/ED-perso.h @@ -62,7 +62,7 @@ class ED void extractChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments); int *sortAnchorsByGradValue(); - void cleanUpSurroundingAnchorPixels(const StackNode ¤t_node); + void cleanUpSurroundingAnchorPixels(const StackNode ¤t_node, bool clear_perpendicular = false); StackNode getNextChainPixel(const StackNode ¤t_node); bool areNeighbors(int offset1, int offset2); void cleanUpPenultimateSegmentPixel(Chain *chain, std::vector &anchorSegment, bool is_first_child); diff --git a/test_ED.cpp b/test_ED.cpp index cbb9270..8cd9e82 100644 --- a/test_ED.cpp +++ b/test_ED.cpp @@ -47,7 +47,7 @@ int main(int argc, char **argv) // ------------------------------- tm.reset(); tm.start(); - ED testED = ED(testImg, LSD_OPERATOR, 6, 2, 10, 1.0, true); + ED testED = ED(testImg, LSD_OPERATOR, 6, 0, 10, 1.0, true); tm.stop(); double newEdTime = tm.getTimeMilli(); cout << "New ED Implementation : " << newEdTime << " ms" << endl; From 5e36644f943f03b1126fac60ac62f0ad94e3f04a Mon Sep 17 00:00:00 2001 From: Jeerhz Date: Thu, 15 Jan 2026 19:40:43 +0100 Subject: [PATCH 6/7] minor remove debug cout --- ED-perso.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/ED-perso.cpp b/ED-perso.cpp index d5218db..58e7cbd 100644 --- a/ED-perso.cpp +++ b/ED-perso.cpp @@ -553,8 +553,6 @@ void ED::JoinAnchorPointsUsingSortedAnchors() while (!process_stack.empty()) { - std::cout << "Processing stack node at offset: " << process_stack.top().offset << std::endl; - std::cout << "Stack Size: " << process_stack.size() << std::endl; StackNode currentNode = process_stack.top(); process_stack.pop(); From fec1e36729894b5793755138ce1ce7bfb70ea20a Mon Sep 17 00:00:00 2001 From: Jeerhz Date: Fri, 16 Jan 2026 15:36:47 +0100 Subject: [PATCH 7/7] fix: compare with gradien torientation and not direction --- ED-perso.cpp | 17 +++-------------- ED-perso.h | 2 +- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/ED-perso.cpp b/ED-perso.cpp index 58e7cbd..f6f81d6 100644 --- a/ED-perso.cpp +++ b/ED-perso.cpp @@ -581,11 +581,10 @@ void ED::JoinAnchorPointsUsingSortedAnchors() } // Clean pixel perpendicular to edge direction -void ED::cleanUpSurroundingAnchorPixels(const StackNode ¤t_node, bool clear_perpendicular) +void ED::cleanUpSurroundingAnchorPixels(const StackNode ¤t_node) { int offset = current_node.offset; - int offset_diff = (current_node.node_direction == LEFT || current_node.node_direction == RIGHT) ? image_width : 1; - int perpendicular_offset_diff = (current_node.node_direction == LEFT || current_node.node_direction == RIGHT) ? 1 : image_width; + int offset_diff = gradOrientationImgPointer[offset] == EDGE_HORIZONTAL ? image_width : 1; // Left/up neighbor if (edgeImgPointer[offset - offset_diff] == ANCHOR_PIXEL) @@ -593,16 +592,6 @@ void ED::cleanUpSurroundingAnchorPixels(const StackNode ¤t_node, bool clea // Right/down neighbor if (edgeImgPointer[offset + offset_diff] == ANCHOR_PIXEL) edgeImgPointer[offset + offset_diff] = 0; - - if (clear_perpendicular) - { - // Left/up neighbor - if (edgeImgPointer[offset - perpendicular_offset_diff] == ANCHOR_PIXEL) - edgeImgPointer[offset - perpendicular_offset_diff] = 0; - // Right/down neighbor - if (edgeImgPointer[offset + perpendicular_offset_diff] == ANCHOR_PIXEL) - edgeImgPointer[offset + perpendicular_offset_diff] = 0; - } } // Get next pixel in the chain based on current node direction and gradient values @@ -666,7 +655,7 @@ void ED::exploreChain(StackNode ¤t_node, Chain *current_chain, int &total_ current_chain->pixels.push_back(current_node.offset); total_pixels_in_anchor_chain++; edgeImgPointer[current_node.offset] = EDGE_PIXEL; - cleanUpSurroundingAnchorPixels(current_node, true); + cleanUpSurroundingAnchorPixels(current_node); // We add new nodes to the process stack in perpendicular directions to the edge with reference to this chain as a parent // This is different from the original implementation where the above node is the starting of the perpendicular sub-chains diff --git a/ED-perso.h b/ED-perso.h index 8c35aa7..39e0242 100644 --- a/ED-perso.h +++ b/ED-perso.h @@ -62,7 +62,7 @@ class ED void extractChainsRecur(Chain *anchor_chain_root, std::vector> &anchorSegments); int *sortAnchorsByGradValue(); - void cleanUpSurroundingAnchorPixels(const StackNode ¤t_node, bool clear_perpendicular = false); + void cleanUpSurroundingAnchorPixels(const StackNode ¤t_node); StackNode getNextChainPixel(const StackNode ¤t_node); bool areNeighbors(int offset1, int offset2); void cleanUpPenultimateSegmentPixel(Chain *chain, std::vector &anchorSegment, bool is_first_child);