Carpetfizz
Carpetfizz

Reputation: 9149

Select region of interest with border rules

I would like to extract a small window around every pixel in my image. Of course, I can use Python list slicing to achieve this. But, list slicing alone won't solve the "edge case" where a window of size W simply does not exist around a pixel because it's close to the edge. Consider the simple matrix M

1 1 1 1
1 1 1 1
1 1 1 1

If I want to select a window of size 3x3 around M(1,1) I would not be able to because there's nothing above it or to the left of it.

Is there a Numpy function or something in Skimage that would allow me to specify what happens when the list index goes out of bounds? For example, what if I just wanted to copy over the nearest neighbor?

I can certainly write this logic on my own as this is a trivial algorithm. I am just wondering if such an option already exists in Numpy, Skimage, OpenCV, etc.

Upvotes: 2

Views: 580

Answers (1)

alkasm
alkasm

Reputation: 23012

Typically you pad the image first, via np.pad() (docs) or cv2.copyMakeBorder() (docs) and shift the indices you want to select depending on the size of your padding. The nice thing about both of these functions is they give a lot of different options with what values the images get padded with. Numpy has a lot more options, but most of the standard ones you'd want to use (repeating the edge pixels, mirroring the edge pixels, wrapping the edge pixels, or constant padding) are available in both libraries.

The numpy border types are directly listed in the docs, but I'll copy them here:

mode : str or function
    One of the following string values or a user supplied function.

    ‘constant’
        Pads with a constant value.

    ‘edge’
        Pads with the edge values of array.

    ‘linear_ramp’
        Pads with the linear ramp between end_value and the array edge value.

    ‘maximum’
        Pads with the maximum value of all or part of the vector along each axis.

    ‘mean’
        Pads with the mean value of all or part of the vector along each axis.

    ‘median’
        Pads with the median value of all or part of the vector along each axis.

    ‘minimum’
        Pads with the minimum value of all or part of the vector along each axis.

    ‘reflect’
        Pads with the reflection of the vector mirrored on the first and last values of the vector along each axis.

    ‘symmetric’
        Pads with the reflection of the vector mirrored along the edge of the array.

    ‘wrap’
        Pads with the wrap of the vector along the axis. The first values are used to pad the end and the end values are used to pad the beginning.

    <function>
        Padding function, see Notes.

It has notes further down for arbitrary functions passed in, which is a cool feature.

The OpenCV border types are not specified directly in the copyMakeBorder() docs, but you can find them by searching border types on the docs. Again, just to have them on SO:

BORDER_CONSTANT 
Python: cv.BORDER_CONSTANT
iiiiii|abcdefgh|iiiiiii with some specified i

BORDER_REPLICATE 
Python: cv.BORDER_REPLICATE
aaaaaa|abcdefgh|hhhhhhh

BORDER_REFLECT 
Python: cv.BORDER_REFLECT
fedcba|abcdefgh|hgfedcb

BORDER_WRAP 
Python: cv.BORDER_WRAP
cdefgh|abcdefgh|abcdefg

BORDER_REFLECT_101 
Python: cv.BORDER_REFLECT_101
gfedcb|abcdefgh|gfedcba

BORDER_TRANSPARENT 
Python: cv.BORDER_TRANSPARENT
uvwxyz|abcdefgh|ijklmno

BORDER_REFLECT101 
Python: cv.BORDER_REFLECT101
same as BORDER_REFLECT_101

BORDER_DEFAULT 
Python: cv.BORDER_DEFAULT
same as BORDER_REFLECT_101

BORDER_ISOLATED 
Python: cv.BORDER_ISOLATED
do not look outside of ROI

Upvotes: 2

Related Questions