Ask Your Question
0

Find a small square patch inside an "approxPolyDP" polygon

asked 2013-12-22 03:21:37 -0600

mtourne gravatar image

updated 2013-12-22 03:23:18 -0600

Hi,

I'm processing a still image in order to find where the water is. (see my other question here)

Now, I can find all the rather large polygons in the image, using approxPolyDP. But there is no guarantee that the water is the dominant part of the image.

In case I have a few large-ish polygons (> 5%) of the image), I'd like to find a small patch that fits in my polygon and test its texture using one of the classic statistical texture methods (local binary pattern, laws, gabor filters).

But I'm not sure how to find a small square that fits inside the polygon. The only thing I can think of is to use the center of gravity, and create a small box around it. But in the case of a complicated shape, the center of gravity might not be in the shape itself.

Here is an example where finding a small square patch in the polygon that I have outlined seems potentially tricky:

Original image:

Original image

Outline of the water (one of the large polygons), where I'd like to define a square patch :

Water mask

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
1

answered 2013-12-22 06:01:58 -0600

Guanta gravatar image

Filter your mask with a kernel having the size you want to find and then take the maximum response, if this response is not the size of the kernel, there doesn't exist a large enough patch, otherwise you can use its location for a suitable patch.

Code:

import cv2
import numpy as np

# read in your image
mask = cv2.imread('zEBLK2z.jpg', cv2.CV_LOAD_IMAGE_GRAYSCALE)
# make sure the masked part is 1 (not 255)
mask[mask>0] = 1

# make a window with the minimum window size to find
min_s = 16
kernel = np.ones((min_s, min_s),dtype=np.uint8)
# filter the image with this kernel
res = cv2.filter2D(mask, cv2.CV_16S, kernel)

# find the maximum 
m = np.amax(res)
# if the maximum is the area of your window at least
# one location has been found
if m == min_s*min_s:
    mask_color = cv2.cvtColor(mask*255, cv2.cv.CV_GRAY2BGR)
    # show each location where we found the maximum
    # i.e. a possible location for a patch
    mask_color[res == m] = (0,255,0)                       

    # if you are only interested in the first hit use this:
    # find firs index and convert it to coordinates of the mask
    y,x = np.unravel_index(np.argmax(res), mask.shape)
    # could do now other things with this location, 
    # but for now just show it in another color
    mask_color[y:y+min_s,x:x+min_s] = (255,0,0)

    cv2.imwrite('result.png', mask_color)

Result (green: all possible locations, blue the first one):

Result

edit flag offensive delete link more

Comments

My next idea was to apply a distance transform on the masked version, then threshold to get a local max. This should get me a patch towards the center of the texture. I imagine the distance transform is more expensive ?

mtourne gravatar imagemtourne ( 2013-12-23 03:06:32 -0600 )edit

Good idea. Speed-wise it is hard to say what is faster, convolution depends on the kernel size you chose, e.g. if it is a larger one, FFT is used for speed up. On the other hand, the speed of the distance transform depends the most on the chosen distance metric. I guess, if you chose l1, then this will be faster.

Guanta gravatar imageGuanta ( 2013-12-23 03:52:42 -0600 )edit

Question Tools

Stats

Asked: 2013-12-22 03:21:37 -0600

Seen: 907 times

Last updated: Dec 22 '13