Wednesday, 2 October 2013

Segmenting leaf by openCV2--02 : Segment leafs to single leaf part 1

  Last post I  use watershed to segment the leafs, this post I would like to segment those leafs into single leaf.Let us begin from simple case(graph_00).graph_00 is easier to segment than graph_01 and graph_02 because the leafs are not stick together as close as graph_01 and graph_02. If they stick(merge) together like graph_01 and graph_02 do, we will need to pay much more efforts to separate those leafs.

graph_00
graph_01
graph_02

  Separate the leafs of graph_00 could be done by simple algorithms as following.

 
/**
 * @brief cut the leafs to single leaf
 * @param input  input image
 * @param name   name of the image want to be saved
 */
void cut_to_single_leaf_simple(cv::Mat const &input, 
                               std::string const &name)
{
    cv::Mat mask;
    //step 1 : convert the input to gray image
    cv::cvtColor(input, mask, CV_BGR2GRAY);
    //step 2 : binarize it
    cv::threshold(mask, mask, 128, 255, CV_THRESH_BINARY);
    //step 3 : do serious erosion
    cv::erode(mask, mask, 
             cv::getStructuringElement(cv::MORPH_RECT, 
             cv::Size(5, 5)), 
             cv::Point(-1, -1), 5);
    //step 4 : find and remove the outliers contours
    ContoursType contours;
    cv::findContours(mask, contours, CV_RETR_EXTERNAL, 
                     CV_CHAIN_APPROX_NONE);
    OCV::remove_contours(contours, 500, 120000);
    cv::Mat result;
    //step 5 : draw the contours one by one
    for(size_t i = 0; i != contours.size(); ++i){
        mask.setTo(0);
        cv::drawContours(mask, contours, i, cv::Scalar(255), 
                         CV_FILLED);
        //step 6 : dilate and close the contours
        cv::dilate(mask, mask, 
                   cv::getStructuringElement(cv::MORPH_RECT, 
                   cv::Size(5, 5)), 
                   cv::Point(-1, -1), 6);
        cv::morphologyEx(mask, mask, CV_MOP_CLOSE, 
                         cv::getStructuringElement(cv::MORPH_RECT, 
                         cv::Size(15, 15)));
        //step 6 : save the results
        input.copyTo(result, mask);
        cv::imwrite(name + std::to_string(i) + ".png", result);
        result.setTo(0);
    }
}

I think the codes and the comment already show us the whole story.

As usual, the codes can download from github.

Next post of Recognize leaf by openCV2 

  Try my best to segment the graph_01 and graph_02, I think I would use machine learning to solve this problem.