Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I load a horizontally-flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);

                circle(frame, location, 3, Scalar(127, 127, 127), 3);
            }
        }

        //cout << endl;



    }


    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray circles detect branching:

image description

Please mark this answer as correct if it satisfies your question. :)

I load a horizontally-flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);

                circle(frame, location, 3, Scalar(127, 127, 127), 3);
            }
        }

        //cout << endl;



    }


    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray circles detect branching:

image description

Please mark this answer as correct if it satisfies your question. :)

I load a horizontally-flipped flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);

                circle(frame, location, 3, Scalar(127, 127, 127), 3);
            }
        }

        //cout << endl;



    }


    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray circles detect branching:

image description

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);

                circle(frame, location, 3, Scalar(127, 127, 127), 3);
            }
        }

        //cout << endl;



    }

    }

    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray circles detect branching:

image description

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    imshow("thresh", frame);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                 branch_locations.push_back(location);
            }
        }
    }

    cvtColor(frame, frame, CV_GRAY2BGR);

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(frame, location, 3, Scalar(127, branch_locations[i], 2, Scalar(0, 127, 127), 3);
            }
        }
    }
255), 2);


    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray circles detect branching:

image description

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    imshow("thresh", frame);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    cvtColor(frame, frame, CV_GRAY2BGR);

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(frame, branch_locations[i], 2, Scalar(0, 127, 255), 2);


    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray circles detect branching:

image descriptionimage description

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    imshow("thresh", frame);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    cvtColor(frame, frame, CV_GRAY2BGR);

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(frame, branch_locations[i], 2, Scalar(0, 127, 255), 2);


    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray circles detect branching:

image description

As you can see, it works quite well now.

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    imshow("thresh", frame);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    cvtColor(frame, frame, CV_GRAY2BGR);

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(frame, branch_locations[i], 2, Scalar(0, 127, 255), 2);


    imshow("frame", frame);

    waitKey();

    return 0;
}

My output looks like this, where the gray orange circles detect show branching:

image description

As you can see, it works quite well now.

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png", CV_LOAD_IMAGE_GRAYSCALE);
imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    imshow("thresh", frame);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if(255 if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    cvtColor(frame, frame, CV_GRAY2BGR);

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(frame, circle(colour_frame, branch_locations[i], 2, Scalar(0, Scalar(255, 127, 255), 0), 2);

     imshow("frame", frame);
colour_frame);

    waitKey();

    return 0;
}

My output looks like this, where the orange circles show branching:

image description

As you can see, it works quite well now.

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

My output looks like this, where the orange blue circles show branching:

image descriptionimage description

As you can see, it works quite well now.

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        // for each black region begin/end pair
        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows - 2);
        }

        // for each black region begin/end pair
        for (int k = 0; k < begin_end_black_regions.size(); k += 2)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; l <= begin_end_black_regions[k + 1]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        size_t spark_count = 0;
        size_t bg_count = 0;
        bool lit = false;
        vector<int> begin_end_black_regions;
begin_black_regions;
        vector<int> end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
            spark_count++;
        }
        else
        {
            lit = false;
            bg_count++;
            begin_end_black_regions.push_back(0);
begin_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                spark_count++;
                begin_end_black_regions.push_back(j end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                bg_count++;
                begin_end_black_regions.push_back(j);
begin_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i))
        {
            begin_end_black_regions.push_back(frame.rows i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            begin_end_black_regions.push_back(frame.rows end_black_regions.push_back(frame.rows - 2);
        }

        //  Bug check...
        if(begin_black_regions.size() != end_black_regions.size())
        cout << begin_black_regions.size() << " " << end_black_regions.size() << endl;

        // for each black region begin/end pair
        for (int (size_t k = 0; k < begin_end_black_regions.size(); k += 2)
begin_black_regions.size(); k++)
        {
            bool found_branch = true;

            for (int l = begin_end_black_regions[k]; begin_black_regions[k]; l <= begin_end_black_regions[k + 1]; end_black_regions[k]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_end_black_regions[k]);
begin_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My code is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        bool lit = false;
        vector<int> begin_black_regions;
        vector<int> end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
        }
        else
        {
            lit = false;
            begin_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                begin_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == true)
        {
            begin_black_regions.push_back(frame.rows - 1);
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 2);
        }

        //  Bug check...
        if(begin_black_regions.size() != end_black_regions.size())
         cout << begin_black_regions.size() << " " << end_black_regions.size() << endl;

        // for each black region begin/end pair
        for (size_t k = 0; k < begin_black_regions.size(); k++)
        {
            bool found_branch = true;

            for (int l = begin_black_regions[k]; l <= end_black_regions[k]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My C++ code (now followed by a Python code) is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        bool lit = false;
        vector<int> begin_black_regions;
        vector<int> end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
        }
        else
        {
            lit = false;
            begin_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                begin_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == true)
        {
            begin_black_regions.push_back(frame.rows - 1);
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 2);
        }

        if(begin_black_regions.size() != end_black_regions.size())
            cout << begin_black_regions.size() << " " << end_black_regions.size() << endl;

        // for each black region begin/end pair
        for (size_t k = 0; k < begin_black_regions.size(); k++)
        {
            bool found_branch = true;

            for (int l = begin_black_regions[k]; l <= end_black_regions[k]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

The Python code is:

import cv2
import numpy

frame = cv2.imread('sparks.png')

if frame is None:
    print('Error loading image')
    exit()

colour_frame = frame

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

ret, frame = cv2.threshold(frame, 127, 255, cv2.THRESH_BINARY)

rows = frame.shape[0]
cols = frame.shape[1]

branch_locations_x = []
branch_locations_y = []


# start with second column
for i in range(1, cols):
    lit = False
    begin_black_regions = []
    end_black_regions = []

    # start with first row
    if 255 == frame[0, i]:
        lit = Frue
    else:
        lit = False
    begin_black_regions.append(0)

    # start with second row
    for j in range(1, rows - 1):
        if 255 == frame[j, i] and lit == False:
            lit = True
            end_black_regions.append(j - 1)
    elif 0 == frame[j, i] and lit == True:
            lit = False
            begin_black_regions.append(j)

    # end with last row
    if 0 == frame[rows - 1, i] and lit == False:
        end_black_regions.append(rows - 1)
    elif 0 == frame[rows - 1, i] and lit == True:
        begin_black_regions.append(rows - 1)
        end_black_regions.append(rows - 1)
    elif 255 == frame[rows - 1, i] and lit == False:
    end_black_regions.append(rows - 2)

    #print len(begin_black_regions)
    #print len(end_black_regions)

    for k in range(0, len(begin_black_regions)):
        found_branch = True

        for l in range(begin_black_regions[k], end_black_regions[k] + 1):
            if 0 == frame[l, i - 1]:
                found_branch = False
                break

        if found_branch == True:
            location_x = i - 1
            location_y = begin_black_regions[k]    
            branch_locations_x.append(location_x)
            branch_locations_y.append(location_y)

for i in range(0, len(branch_locations_x)):
    cv2.circle(colour_frame, (branch_locations_x[i], branch_locations_y[i]), 2, (255, 127, 0), 2)

cv2.imshow("Frame", colour_frame)

cv2.waitKey(0)

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My C++ code (now followed by a Python code) is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        bool lit = false;
        vector<int> begin_black_regions;
        vector<int> end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
        }
        else
        {
            lit = false;
            begin_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                begin_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == true)
        {
            begin_black_regions.push_back(frame.rows - 1);
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 2);
        }

        if(begin_black_regions.size() != end_black_regions.size())
            cout << begin_black_regions.size() << " " << end_black_regions.size() << endl;

        // for each black region begin/end pair
        for (size_t k = 0; k < begin_black_regions.size(); k++)
        {
            bool found_branch = true;

            for (int l = begin_black_regions[k]; l <= end_black_regions[k]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

The Python code is:

import cv2
import numpy

frame = cv2.imread('sparks.png')

if frame is None:
    print('Error loading image')
    exit()

colour_frame = frame

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

ret, frame = cv2.threshold(frame, 127, 255, cv2.THRESH_BINARY)

rows = frame.shape[0]
cols = frame.shape[1]

branch_locations_x = []
branch_locations_y = []


# start with second column
for i in range(1, cols):
    lit = False
    begin_black_regions = []
    end_black_regions = []

    # start with first row
    if 255 == frame[0, i]:
        lit = Frue
True
    else:
        lit = False
    begin_black_regions.append(0)

    # start with second row
    for j in range(1, rows - 1):
        if 255 == frame[j, i] and lit == False:
            lit = True
            end_black_regions.append(j - 1)
    elif 0 == frame[j, i] and lit == True:
            lit = False
            begin_black_regions.append(j)

    # end with last row
    if 0 == frame[rows - 1, i] and lit == False:
        end_black_regions.append(rows - 1)
    elif 0 == frame[rows - 1, i] and lit == True:
        begin_black_regions.append(rows - 1)
        end_black_regions.append(rows - 1)
    elif 255 == frame[rows - 1, i] and lit == False:
    end_black_regions.append(rows - 2)

    #print len(begin_black_regions)
    #print len(end_black_regions)

    for k in range(0, len(begin_black_regions)):
        found_branch = True

        for l in range(begin_black_regions[k], end_black_regions[k] + 1):
            if 0 == frame[l, i - 1]:
                found_branch = False
                break

        if found_branch == True:
            location_x = i - 1
            location_y = begin_black_regions[k]    
            branch_locations_x.append(location_x)
            branch_locations_y.append(location_y)

for i in range(0, len(branch_locations_x)):
    cv2.circle(colour_frame, (branch_locations_x[i], branch_locations_y[i]), 2, (255, 127, 0), 2)

cv2.imshow("Frame", colour_frame)

cv2.waitKey(0)

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My C++ code (now followed by a Python code) is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        bool lit = false;
        vector<int> begin_black_regions;
        vector<int> end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
        }
        else
        {
            lit = false;
            begin_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                begin_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == true)
        {
            begin_black_regions.push_back(frame.rows - 1);
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 2);
        }

        if(begin_black_regions.size() != end_black_regions.size())
            cout << begin_black_regions.size() << " " << end_black_regions.size() << endl;

        // for each black region begin/end pair
        for (size_t k = 0; k < begin_black_regions.size(); k++)
        {
            bool found_branch = true;

            for (int l = begin_black_regions[k]; l <= end_black_regions[k]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

The Python code is:

import cv2
import numpy

frame = cv2.imread('sparks.png')

if frame is None:
    print('Error loading image')
    exit()

colour_frame = frame

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

ret, frame = cv2.threshold(frame, 127, 255, cv2.THRESH_BINARY)

rows = frame.shape[0]
cols = frame.shape[1]

branch_locations_x = []
branch_locations_y = []


# start with second column
for i in range(1, cols):
    lit = False
    begin_black_regions = []
    end_black_regions = []

    # start with first row
    if 255 == frame[0, i]:
        lit = True
    else:
        lit = False
     begin_black_regions.append(0)

    # start with second row
    for j in range(1, rows - 1):
        if 255 == frame[j, i] and lit == False:
            lit = True
            end_black_regions.append(j - 1)
    elif 0 == frame[j, i] and lit == True:
            lit = False
            begin_black_regions.append(j)

    # end with last row
    if 0 == frame[rows - 1, i] and lit == False:
        end_black_regions.append(rows - 1)
    elif 0 == frame[rows - 1, i] and lit == True:
        begin_black_regions.append(rows - 1)
        end_black_regions.append(rows - 1)
    elif 255 == frame[rows - 1, i] and lit == False:
    end_black_regions.append(rows     end_black_regions.append    (rows - 2)

    #print len(begin_black_regions)
    #print len(end_black_regions)

    for k in range(0, len(begin_black_regions)):
        found_branch = True

        for l in range(begin_black_regions[k], end_black_regions[k] + 1):
            if 0 == frame[l, i - 1]:
                found_branch = False
                break

        if found_branch == True:
            location_x = i - 1
            location_y = begin_black_regions[k]    
            branch_locations_x.append(location_x)
            branch_locations_y.append(location_y)

for i in range(0, len(branch_locations_x)):
    cv2.circle(colour_frame, (branch_locations_x[i], branch_locations_y[i]), 2, (255, 127, 0), 2)

cv2.imshow("Frame", colour_frame)

cv2.waitKey(0)

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My C++ code (now followed by a Python code) is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        bool lit = false;
        vector<int> begin_black_regions;
        vector<int> end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
        }
        else
        {
            lit = false;
            begin_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                begin_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == true)
        {
            begin_black_regions.push_back(frame.rows - 1);
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 2);
        }

        if(begin_black_regions.size() != end_black_regions.size())
            cout << begin_black_regions.size() << " " << end_black_regions.size() << endl;

        // for each black region begin/end pair
        for (size_t k = 0; k < begin_black_regions.size(); k++)
        {
            bool found_branch = true;

            for (int l = begin_black_regions[k]; l <= end_black_regions[k]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

The Python code is:

import cv2
import numpy

frame = cv2.imread('sparks.png')

if frame is None:
    print('Error loading image')
    exit()

colour_frame = frame

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

ret, frame = cv2.threshold(frame, 127, 255, cv2.THRESH_BINARY)

rows = frame.shape[0]
cols = frame.shape[1]

branch_locations_x = []
branch_locations_y = []


# start with second column
for i in range(1, cols):
    lit = False
    begin_black_regions = []
    end_black_regions = []

    # start with first row
    if 255 == frame[0, i]:
        lit = True
    else:
        lit = False
        begin_black_regions.append(0)

    # start with second row
    for j in range(1, rows - 1):
        if 255 == frame[j, i] and lit == False:
            lit = True
            end_black_regions.append(j - 1)
    elif 0 == frame[j, i] and lit == True:
            lit = False
            begin_black_regions.append(j)

    # end with last row
    if 0 == frame[rows - 1, i] and lit == False:
        end_black_regions.append(rows - 1)
    elif 0 == frame[rows - 1, i] and lit == True:
        begin_black_regions.append(rows - 1)
        end_black_regions.append(rows - 1)
    elif 255 == frame[rows - 1, i] and lit == False:
        end_black_regions.append    (rows end_black_regions.append(rows - 2)

    #print len(begin_black_regions)
    #print len(end_black_regions)

    for k in range(0, len(begin_black_regions)):
        found_branch = True

        for l in range(begin_black_regions[k], end_black_regions[k] + 1):
            if 0 == frame[l, i - 1]:
                found_branch = False
                break

        if found_branch == True:
            location_x = i - 1
            location_y = begin_black_regions[k]    
            branch_locations_x.append(location_x)
            branch_locations_y.append(location_y)

for i in range(0, len(branch_locations_x)):
    cv2.circle(colour_frame, (branch_locations_x[i], branch_locations_y[i]), 2, (255, 127, 0), 2)

cv2.imshow("Frame", colour_frame)

cv2.waitKey(0)

Please mark this answer as correct if it satisfies your question. :)

I load a flipped version of your input image:

image description

My output looks like this, where the blue circles show branching:

image description

As you can see, it works quite well now.

My C++ code (now followed by a Python code) is:

#include <opencv2/opencv.hpp>
using namespace cv;
#pragma comment(lib, "opencv_world331.lib")

#include <iostream>
#include <vector>
using namespace std;


int main(void)
{
    Mat frame = imread("sparks.png");

    if (frame.empty())
    {
        cout << "Error loading image file" << endl;
        return -1;
    }

    Mat colour_frame = frame.clone();

    cvtColor(frame, frame, CV_BGR2GRAY);

    threshold(frame, frame, 127, 255, THRESH_BINARY);

    vector<Point2i> branch_locations;

    // Start with the second column
    for (int i = 1; i < frame.cols; i++)
    {
        bool lit = false;
        vector<int> begin_black_regions;
        vector<int> end_black_regions;

        // Start with the first row
        if (255 == frame.at<unsigned char>(0, i))
        {
            lit = true;
        }
        else
        {
            lit = false;
            begin_black_regions.push_back(0);
        }

        // Start with the second row
        for (int j = 1; j < frame.rows - 1; j++)
        {
            if (255 == frame.at<unsigned char>(j, i) && lit == false)
            {
                lit = true;
                end_black_regions.push_back(j - 1);
            }
            else if (0 == frame.at<unsigned char>(j, i) && lit == true)
            {
                lit = false;
                begin_black_regions.push_back(j);
            }
        }

        // End with the last row
        if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (0 == frame.at<unsigned char>(frame.rows - 1, i) && lit == true)
        {
            begin_black_regions.push_back(frame.rows - 1);
            end_black_regions.push_back(frame.rows - 1);
        }
        else if (255 == frame.at<unsigned char>(frame.rows - 1, i) && lit == false)
        {
            end_black_regions.push_back(frame.rows - 2);
        }

        if(begin_black_regions.size() != end_black_regions.size())
            cout << begin_black_regions.size() << " " << end_black_regions.size() << endl;

        // for each black region begin/end pair
        for (size_t k = 0; k < begin_black_regions.size(); k++)
        {
            bool found_branch = true;

            for (int l = begin_black_regions[k]; l <= end_black_regions[k]; l++)
            {
                if (0 == frame.at<unsigned char>(l, i - 1))
                {
                    found_branch = false;
                    break;
                }
            }

            if (found_branch == true)
            {
                Point2i location(i - 1, begin_black_regions[k]);
                branch_locations.push_back(location);
            }
        }
    }

    for (size_t i = 0; i < branch_locations.size(); i++)
        circle(colour_frame, branch_locations[i], 2, Scalar(255, 127, 0), 2);

    imshow("frame", colour_frame);

    waitKey();

    return 0;
}

The Python code is:

import cv2
import numpy

frame = cv2.imread('sparks.png')

if frame is None:
    print('Error loading image')
    exit()

colour_frame = frame

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

ret, frame = cv2.threshold(frame, 127, 255, cv2.THRESH_BINARY)

rows = frame.shape[0]
cols = frame.shape[1]

branch_locations_x branch_locations = []
branch_locations_y = []


# start with second column
for i in range(1, cols):
    lit = False
    begin_black_regions = []
    end_black_regions = []

    # start with first row
    if 255 == frame[0, i]:
        lit = True
    else:
        lit = False
        begin_black_regions.append(0)

    # start with second row
    for j in range(1, rows - 1):
        if 255 == frame[j, i] and lit == False:
            lit = True
            end_black_regions.append(j - 1)
     elif 0 == frame[j, i] and lit == True:
            lit = False
            begin_black_regions.append(j)

    # end with last row
    if 0 == frame[rows - 1, i] and lit == False:
        end_black_regions.append(rows - 1)
    elif 0 == frame[rows - 1, i] and lit == True:
        begin_black_regions.append(rows - 1)
        end_black_regions.append(rows - 1)
    elif 255 == frame[rows - 1, i] and lit == False:
        end_black_regions.append(rows - 2)

    #print len(begin_black_regions)
    #print len(end_black_regions)

    for k in range(0, len(begin_black_regions)):
        found_branch = True

        for l in range(begin_black_regions[k], end_black_regions[k] + 1):
            if 0 == frame[l, i - 1]:
                found_branch = False
                break

        if found_branch == True:
            location_x = i - 1
            location_y = begin_black_regions[k]    
            branch_locations_x.append(location_x)
            branch_locations_y.append(location_y)
branch_locations.append(complex(i - 1, begin_black_regions[k]))

for i in range(0, len(branch_locations_x)):
len(branch_locations)):
    cv2.circle(colour_frame, (branch_locations_x[i], branch_locations_y[i]), (int(branch_locations[i].real), int(branch_locations[i].imag)), 2, (255, 127, 0), 2)

cv2.imshow("Frame", colour_frame)

cv2.waitKey(0)