Ask Your Question

Filtering out coast line

asked 2013-12-09 01:00:42 -0600

mtourne gravatar image

updated 2013-12-09 13:32:00 -0600


In the context of flying over water, I'm trying to segment the coastline out of the water.

To do that I've been using a Canny edge detection, which I'm hoping to use to create several large polygons : Each polygon should be contain either: the coastline, the body of water, or some other occlusion

My problem is that I can't find a way to connect a line to the "borders of the image" and make a polygon that way.

What I currently have produces this image : On the top left, and the right is a coastline (flying over a bay), and the bottom part is the UAV itself with the antenna.

This is almost what I need, but I need to create a polygon that extends all the way to the borders. image description

This is the code :

def find_coastline(img_gray, img_rgb):
    CANNY_THRSH_LOW = 1000
    # add borders for polygons
    edge = cv2.Canny(img_gray, CANNY_THRSH_LOW, CANNY_THRSH_HIGH, apertureSize=5)
    kern = np.ones((5, 5))
    # dilatation connects most of the disparate edges
    edge = cv2.dilate(edge, kern)
    vis = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    vis[edge != 0] = (0, 255, 0)
    cv2.imwrite('boats_canny.jpg', vis)
    # only external contours
    contours, hierarchy = cv2.findContours(edge.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    vis = np.zeros((img_rgb.shape), np.uint8)
    i = 0
    for cnt in contours:
        color = np.random.random_integers(255, size=(3))
        cv2.drawContours( vis, contours0, i, color,
                          3, cv2.CV_AA, hierarchy, 0)
        i += 1
    cv2.imwrite('boats_contours.jpg', vis)

This is the original image : image description

edit retag flag offensive close merge delete


Posting your source image might be helpful for viewers.

Haris gravatar imageHaris ( 2013-12-09 06:16:00 -0600 )edit

2 answers

Sort by ยป oldest newest most voted

answered 2013-12-10 01:45:58 -0600

Haris gravatar image

updated 2013-12-10 01:54:35 -0600

Using your first image(processed image) I just proceed some more step like

made the result as shown below.

Code:- Here is the C++ code for the above steps,

Mat tmp,thr;
Mat src=imread("river.jpg",1); //Your processed  image


    //Find biggest contour to segment exact object
    vector< vector <Point> > contours; // Vector for storing contour
    vector< Vec4i > hierarchy;
    int largest_contour_index=0;
    int largest_area=0;
    Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0)); //create destination image

    findContours( thr, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
     for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
       double a=contourArea( contours[i],false);  //  Find the area of contour
       largest_contour_index=i;                //Store the index of largest contour

     drawContours( dst,contours, largest_contour_index, Scalar(255,255,255),CV_FILLED, 8, hierarchy ); // Draw the largest contour using previously stored index.

     ///Either directly draw the contour
     drawContours( src,contours, largest_contour_index, Scalar(0,255,0),3, 8, hierarchy ); 

     ///Or use convex hull to draw the contour
     vector<vector<Point> >hull(1);
     convexHull(contours[largest_contour_index],  hull[0],false,true );
     drawContours( src, hull, 0, Scalar(0,0,255), 2, 8, vector<Vec4i>(), 0, Point() );

Result:- Red boundary is result of convexhull and Green boundary is the result of drawcontour using largest contour. image description

edit flag offensive delete link more


Did you use a trackbar to change the value for the threshold in practice ? I can't seem to replicate your result using the value "10" for the threshold

mtourne gravatar imagemtourne ( 2013-12-10 02:23:59 -0600 )edit

No I just used fixed threshold value(10) and I got above image for the same code I posted above. But my source image is your first image(edge image) as I mentioned the answer.

Haris gravatar imageHaris ( 2013-12-10 03:26:09 -0600 )edit

That makes sense, thank you!

mtourne gravatar imagemtourne ( 2013-12-10 11:37:39 -0600 )edit

You are welcome.

Haris gravatar imageHaris ( 2013-12-10 12:39:15 -0600 )edit

answered 2013-12-22 02:53:48 -0600

mtourne gravatar image

updated 2013-12-22 02:54:36 -0600

I finally ended up inverting the edges found with the canny procedure and applying findContours on that, to cut on the number of steps. It roughly looks like that :

edge = cv2.Canny(img_gray, CANNY_THRSH_LOW, CANNY_THRSH_HIGH, apertureSize=5)
kern = np.ones((5, 5))
# dilatation connects most of the disparate edges
edge = cv2.dilate(edge, kern)
# invert edges to create one big water blob
edge_inv = np.zeros((img_gray.shape), np.uint8)
edge_inv = edge_inv - edge
contours0, hierarchy0 = cv2.findContours(edge_inv.copy(), cv2.RETR_EXTERNAL,
edit flag offensive delete link more

Question Tools

1 follower


Asked: 2013-12-09 01:00:42 -0600

Seen: 1,773 times

Last updated: Dec 22 '13