Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong result using function fillPoly in opencv for very large images

I have a hard time solving the issue with mask creation.My image is large, 40959px X 24575px and im trying to create a mask for it. I noticed that i dont have a problem for images up to certain size(I tested about 33000px X 22000px), but for dimensions larger than that i get an error inside my mask(Error is that it gets black in the middle of the polygon and white region extends itself to the left edge.Result should be without black area inside polygon and no white area extending to the left edge of image).

So my code looks like this:

    pixel_points_list = latLonToPixel(dataSet, lat_lon_pairs)
    print pixel_points_list
    # This is the list im getting
    #[[213, 6259], [22301, 23608], [25363, 22223], [27477, 23608], [35058, 18433], [12168, 282], [213, 6259]]
    image = cv2.imread(in_tmpImgFilePath,-1)
    print image.shape
    #Value of image.shape: (24575, 40959, 4)
    mask = np.zeros(image.shape, dtype=np.uint8)
    roi_corners = np.array([pixel_points_list], dtype=np.int32)
    print roi_corners
    #contents of roi_corners_array:
    """
    [[[  213  6259]
    [22301 23608]
    [25363 22223]
    [27477 23608]
    [35058 18433]
    [12168   282]
    [  213  6259]]]
    """
    channel_count = image.shape[2] 
    ignore_mask_color = (255,)*channel_count
    cv2.fillPoly(mask, roi_corners, ignore_mask_color)
    cv2.imwrite("mask.tif",mask)

And this is the mask im getting with those coordinates(minified mask): Part of mask is mirrored

You see that in the middle of the mask the mask is mirrored.I took those points from pixel_points_list and drawn them on coordinate system and im getting valid polygon, but when using fillPoly im getting wrong results.

Here is even simpler example where i have only 4(5) points:

 roi_corners = array([[  213  6259]
                      [22301 23608]
                      [35058 18433]
                      [12168   282]
                      [  213  6259]])

And i get enter image description here

Does anyone have a clue why does this happen? Thanks!

like image 604
Milos Miletic Avatar asked May 23 '16 13:05

Milos Miletic


1 Answers

The issue is in the function CollectPolyEdges, called by fillPoly (and drawContours, fillConvexPoly, etc...).

Internally, it's assumed that the point coordinates (of integer type int32) have meaningful values only in the 16 lowest bits. In practice, you can draw correctly only if your points have coordinates up to 32768 (which is exactly the maximum x coordinate you can draw in your image.)

This can't be considered as a bug, since your images are extremely large.


As a workaround, you can try to scale your mask and your points by a given factor, fill the poly on the smaller mask, and then re-scale the mask back to original size


As @DanMašek pointed out in the comments, this is in fact a bug, not fixed, yet.

In the bug discussion, there is another workaround mentioned. It consists on drawing using multiple ROIs with size less than 32768, correcting coordinates for each ROI using the offset parameter in fillPoly.

like image 120
Miki Avatar answered Sep 21 '22 14:09

Miki