Mask an image (np.ndarray) section which lies between two curves
<p>Borrowing this example from astropy:</p>

<pre><code>import numpy as np
from matplotlib import pyplot as plt
from astropy.io import fits
from astropy.wcs import WCS
from astropy.utils.data import download_file

fits_file = 'http://data.astropy.org/tutorials/FITS-images/HorseHead.fits'
image_file = download_file(fits_file, cache=True)
hdu = fits.open(image_file)[0]
wcs = WCS(hdu.header)

fig = plt.figure()
ax = fig.add_subplot(111)
plt.imshow(hdu.data, origin='lower', cmap='cubehelix')
plt.xlabel('X')
plt.ylabel('Y')

x_array = np.arange(0, 1000)
line_1 = 1 * x_array + 20 * np.sin(0.05*x_array)
line_2 = x_array - 100 + 20 * np.sin(0.05*x_array)

plt.plot(x_array, line_1, color='red')
plt.plot(x_array, line_2, color='red')

ax.set_xlim(0, hdu.shape[1])
ax.set_ylim(0, hdu.shape[0])

plt.show()
</code></pre>

<p>I would like to calculate the median pixel value (in y direction for example) which lies between the two curves:</p>

<p><a href="http://i.stack.imgur.com/5QvFz.png" rel="nofollow"><img src="http://i.stack.imgur.com/5QvFz.png" alt="enter image description here"></a></p>

<p>I believe the clever thing would be to create a mask for the region of interest.</p>

<p>Is there a way to generate this mask without looping across the image pixels?</p>

<p>Edit 1: Modified question improve understanding</p>

<p>Edit 2: I changed the example to better represent the question title (curves instead of straight lines)</p>

<p>The code snippet below creates a mask, sets all values outside the mask to nan, and then uses NumPy's <code>nanmedian</code> to calculate the desired quantity along the direction indicated.</p>

<pre><code>import numpy as np

import matplotlib.pyplot as plt
from matplotlib import gridspec

from skimage.measure import grid_points_in_poly


# Create test image
N = 900
image = np.sin(np.linspace(0, 2 * np.pi, N * N).reshape((N, N)) ** 2)

# Define the mask polygon
poly = [[N, 0],
        [0, N],
        [100, N],
        [N, 100]]

# Create the mask (True is inside the polygon)
mask = grid_points_in_poly(image.shape, poly)

# Set everything outside the mask to nan
masked_image = image.copy()
masked_image[~mask] = np.nan

# Perform the required operation
row_med = np.nanmedian(masked_image, axis=1)

# The rest of the code is to visualize the result
fig = plt.figure(figsize=(15, 10))
gs = gridspec.GridSpec(1, 3, width_ratios=(1, 1, 1/8))
ax0 = plt.subplot(gs[0])
ax1 = plt.subplot(gs[1])
ax2 = plt.subplot(gs[2])

ax0.imshow(image, cmap='gray')
ax0.set_title('Input image')
ax0.set_xlim(0, N)

ax1.imshow(masked_image, cmap='gray')
ax1.set_title('Masked image')
ax1.set_xlim(0, N)

ax2.plot(row_med, np.arange(N))
ax2.set_ylim([N, 0])
ax2.set_xlim([-1.5, 1.5])
ax2.set_title('Row median')

plt.tight_layout()
plt.show()
</code></pre>

<p><a href="http://i.stack.imgur.com/axaZq.png" rel="nofollow"><img src="http://i.stack.imgur.com/axaZq.png" alt="Median along rows inside region of interest"></a></p>

python numpy indexing mask scikit-image