# Isolate stems and petioles

**URL:** <https://forum.opencv.org/t/isolate-stems-and-petioles/12596>\
**Category:** Uncategorized\
**Created:** [March 29, 2023, 8:53pm UTC](https://forum.opencv.org/t/isolate-stems-and-petioles/12596 "2023-03-29T20:53:44Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sylvain\_Ard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/sylvain_ard/32/114_2.png) [@Sylvain\_Ard](https://forum.opencv.org/u/Sylvain_Ard)\
**Post date:** [March 29, 2023, 8:53pm UTC](https://forum.opencv.org/t/isolate-stems-and-petioles/12596/1 "2023-03-29T20:53:44Z")

</div>

Hi,  
I have isolated the stems and petioles of a plant by semantic segmentation like you can see in red overlap in the following image :

 ![IMAGE_overlapped_tige](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/e/e3758b793b87d3c49944c477a95900cd926ddd77.jpeg)

now I want to isolate each branch and their intersection, furthermore I want to obtain the 1-pixel wide skeleton of each branch.  
I know it’s difficult.  
Any idea ?  
Thank you !  
Best regards

---

<div class="post-metadata">

**Author:** ![Sylvain\_Ard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/sylvain_ard/32/114_2.png) [@Sylvain\_Ard](https://forum.opencv.org/u/Sylvain_Ard)\
**Post date:** [March 31, 2023, 8:00pm UTC](https://forum.opencv.org/t/isolate-stems-and-petioles/12596/2 "2023-03-31T20:00:58Z")

</div>

chatGPT answered me this, it will replace humans ! :

```auto
#include <opencv2/opencv.hpp>

int main()
{
    // Charger l'image des branches segmentées
    cv::Mat branches = cv::imread("branches.jpg", cv::IMREAD_GRAYSCALE);

    // Calculer la carte de distance
    cv::Mat dist;
    cv::distanceTransform(branches, dist, cv::DIST_L2, 3);

    // Seuiller la carte de distance pour obtenir les points d'intersection
    cv::Mat intersections;
    cv::threshold(dist, intersections, 0.1 * cv::norm(dist), 255, cv::THRESH_BINARY);

    // Appliquer un flou gaussien pour éliminer les points de bruit
    cv::GaussianBlur(intersections, intersections, cv::Size(5, 5), 0);

    // Trouver les contours des points d'intersection
    std::vector<std::vector<cv::Point>> intersectionContours;
    cv::findContours(intersections, intersectionContours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);

    // Dessiner les contours des points d'intersection sur une image noire
    cv::Mat intersectionImage = cv::Mat::zeros(intersections.size(), CV_8UC1);
    cv::drawContours(intersectionImage, intersectionContours, -1, cv::Scalar(255), 2);

    // Trouver les lignes des branches en utilisant la transformée de Hough
    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(branches, lines, 1, CV_PI / 180, 50, 30, 10);

    // Dessiner les lignes sur une image noire
    cv::Mat linesImage = cv::Mat::zeros(branches.size(), CV_8UC1);
    for (const auto& line : lines)
    {
        cv::line(linesImage, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]), cv::Scalar(255), 2);
    }

    // Dessiner les branches séparées sur une image noire
    cv::Mat separatedImage = cv::Mat::zeros(branches.size(), CV_8UC1);
    for (const auto& line : lines)
    {
        cv::LineIterator it(branches, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]), 8);
        for (int i = 0; i < it.count; ++i, ++it)
        {
            if (intersectionImage.at<uchar>(it.pos()) > 0)
            {
                cv::line(separatedImage, cv::Point(line[0], line[1]), it.pos(), cv::Scalar(255), 1);
                cv::line(separatedImage, cv::Point(line[2], line[3]), it.pos(), cv::Scalar(255), 1);
                break;
            }
            else
            {
                separatedImage.at<uchar>(it.pos()) = 255;
            }
        }
    }

    // Afficher les résultats
    cv::imshow("Branches", branches);
    cv::imshow("Points d'intersection", intersectionImage);
    cv::imshow("Lignes des branches", linesImage);
    cv::imshow("Branches séparées", separatedImage);
    cv::waitKey();

    return 0;
}

```
