5

For my college project I need to identify a species of a plant from plant leaf shape by detecting edges of a leaf. (I use OpenCV 2.4.9 and C++), but the source image has taken in the real environment of the plant and has more than one leaf. See the below example image. So here I need to extract the edge pattern of just one leaf to process further.

enter image description here

Using Canny Edge Detector I can identify edges of the whole image.

enter image description here

But I don't know how to proceed from here to extract edge pattern of just one leaf, may be more clear and complete leaf. I don't know even if this is possible also. Can anyone please tell me if this is possible how to extract edges of one leaf I just want to know the image peocessing steps that I need to apply to the image. I don't want any code samples. I'm new to image processing and OpenCV and learning by doing experiments.

Thanks in advance.

Edit

As Luis said said I have done Morphological close to the image after doing edge detection using Canny edge detection, but it seems still it is difficult me to find the largest contour from the image. Here are the steps I have taken to process the image

  1. Apply Bilateral Filter to reduce noise

    bilateralFilter(img_src, img_blur, 31, 31 * 2, 31 / 2);
    
  2. Adjust contrast by histogram equaliztion

    cvtColor(img_blur,img_equalized,CV_BGR2GRAY);
    
  3. Apply Canny edge detector

    Canny(img_equalized, img_edge_detected, 20, 60, 3);
    
  4. Threshold binary image to remove some background data

    threshold(img_edge_detected, img_threshold, 1, 255,THRESH_BINARY_INV);
    
  5. Morphological close of the image

    morphologyEx(img_threshold, img_closed, MORPH_CLOSE, getStructuringElement(MORPH_ELLIPSE, Size(2, 2)));
    

Following are the resulting images I'm getting.

This result I'm getting for the above original image

enter image description here

Source image and result for second image

Source :

enter image description here

Result :

enter image description here

Is there any way to detect the largest contour and extract it from the image ?

Note that my final target is to create a plant identification system using real environmental image, but here I cannot use template matching or masking kind of things because the user has to take an image and upload it so the system doesn't have any prior idea about the leaf.

Here is the full code

#include <opencv\cv.h>
#include <opencv\highgui.h>
using namespace cv;

int main()
{
Mat img_src,     img_blur,img_gray,img_equalized,img_edge_detected,img_threshold,img_closed;
//Load original image
img_src = imread("E:\\IMAG0196.jpg");

//Apply Bilateral Filter to reduce noise
bilateralFilter(img_src, img_blur, 31, 31 * 2, 31 / 2);

//Adjust contrast by histogram equaliztion
cvtColor(img_blur,img_equalized,CV_BGR2GRAY);

//Apply Canny edge detector
Canny(img_equalized, img_edge_detected, 20, 60, 3);

//Threshold binary image to remove some background data
threshold(img_edge_detected, img_threshold, 15, 255,THRESH_BINARY_INV);

//Morphological close of the image
morphologyEx(img_threshold, img_closed, MORPH_CLOSE, getStructuringElement(MORPH_ELLIPSE, Size(2, 2)));

imshow("Result", img_closed);
waitKey(0);
return 0;
}

Thank you.

Grant
  • 4,413
  • 18
  • 56
  • 82
  • 1
    You will probably need to take a fuzzier approach. Think about what can be done with imperfect edge detections. (This also appears to be the bulk of the assignment) – Drew Dormann Jun 26 '14 at 16:08
  • you might increase your threshold to possibly exclude the objects in the background, and then look into segmentation on whatever's left – Ben Jun 26 '14 at 16:09
  • Yes I can change the threshold and get clear edges, but the problem is how to get the edge of one leaf ? – Grant Jun 26 '14 at 16:11
  • @Drew Dormann Can you please explain what is fuzzier approach ? Thank you for the comment – Grant Jun 27 '14 at 07:30
  • Hi, @Grant. I'm suggesting that you worry less about getting the perfect outline of one single leaf and see what analysis you can do with the image you've already produced. – Drew Dormann Jun 27 '14 at 14:45
  • @Grant I updated my answer, have a look :). – Luis Enrique Jul 06 '14 at 12:39

1 Answers1

6

Well there is a similar question that was asked here:

It seems that edge information is not a good descriptor for the image, still if you want to try it I'll do the following steps:

  1. Load image and convert it to grayscale
  2. Detect edges - Canny, Sobel try them and find what it suits you best
  3. Set threshold to a given value that eliminates most background - Binarize image
  4. Close the image - Morphological close dont close the window!
  5. Count and identify objects in the image (Blobs, Watershed)
  6. Check each object for a shape (assuming you have described shapes of the leaf you could find before or a standard shape like an ellipse) features like:
  7. If a given object has a given shape that you described as a leaf then you detected the leaf!.

I believe that given images are taken in the real world these algorithm will perform poorly but it's a start. Well hope it helps :).

-- POST EDIT 06/07

Well since you have no prior information about the leaf, I think the best we could do is the following:

  • Load image
  • Bilateral filter
  • Canny
  • Extract contours
  • Assume: that the contour with the largest perimeter is the leaf
  • Convex hull the 3 or 2 largest contours (the blue line is the convex hull done)
  • Use this convex hull to do a graph cut on the image and segmentate it

If you do those steps, you'll end up with images like these:

Leaf 1 segmentation

Leaf 2 segmentation

I won't post the code here, but you can check it out in my messy github. I hope you don't mind it was made in python.

Leaf - Github

Still, I have a couple of things to finish that could improve the result.. Roadmap would be:

  • Define the mask in the graphcut (like its described in the doc)
  • Apply region grow may give a better convex hull
  • Remove all edges that touch the border of the image can help to identify larger edges

Well, again, I hope it helps

Community
  • 1
  • 1
Luis Enrique
  • 440
  • 1
  • 4
  • 10
  • Thanks for your answer. Without using edges what are the other ways that I can use to extract single object ? – Grant Jun 27 '14 at 06:19
  • Well, if by extract you mean identify the leaf and segment it out of the image some of theses steps still apply, Instead of edges you could find the leaf with help of descriptors like SIFT or SURF. I believe current state of the art is convolutional neural netwoks (deep learning) but I haven't used them myself yet so I woudn't know for sure. – Luis Enrique Jun 27 '14 at 15:06
  • Can you please explain bit more about the morphological close I tried to do it but unfortunately using that I cannot complete the edge lines of the leaf. Thanks – Grant Jul 01 '14 at 19:00
  • 1
    Take a look at this http://stackoverflow.com/questions/18339988/implementing-imcloseim-se-in-opencv. It would help if you edit your first post and show us the new results, over the next week. I'll implement some code myself and give you an example. – Luis Enrique Jul 01 '14 at 19:55
  • Thank you very much for your kind support I have updated this question please look it. – Grant Jul 02 '14 at 13:34
  • As always your answer helps me a lot. Thank you for spending your time on this task. I have some confusions still. Can you briefly tell me how did you achieve Region grow and interactive images. – Grant Jul 07 '14 at 11:30
  • I didn't do region grow yet, I didn't find it in python API. And there is an source file in the github that does an interactive grabcut (source is from opencv docs actually) – Luis Enrique Jul 07 '14 at 21:40