2016-10-05 2 views
1

Leihen dieses Beispiel aus astropy liegt:Maskenabschnitt ein Bild (np.ndarray), die zwischen zwei Kurven

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() 

Ich möchte den Medianpixelwert (in Y-Richtung beispielsweise), die zwischen der liegt berechnen zwei Kurven:

enter image description here

ich glaube, die clevere Sache, eine Maske für die Region von Interesse zu schaffen wäre.

Gibt es eine Möglichkeit, diese Maske zu generieren, ohne die Bildpixel zu durchlaufen?

Edit 1: Verbesserung der Modified Frage Verständnis

Edit 2: Ich änderte das Beispiel, um besser die Frage Titel (Kurven statt Geraden)

+0

Sie möchten den Medianwert, was zu berechnen, genau? Wenn Sie versuchen, das Zentrum des Gebiets zu finden, das von diesen beiden Linien begrenzt wird, finden Sie dann nicht einfach den Mittelpunkt eines Trapezes? – blacksite

+0

Entschuldigung, ich wollte den mittleren Pixelwert zwischen diesen Zeilen in y-Richtung sagen. – Delosari

+0

So können Sie die Mittelpunktkoordinaten des Trapezes finden und dann das Bild indexieren, um den RGB-Wert zu finden. Ich arbeite jetzt an einer Lösung .... – blacksite

Antwort

3

Ein recht geradlinig Art und Weise der Erzeugung einer solchen Maske darstellen würde sei, das numpy.mgrid Ding zu verwenden, das im Wesentlichen Ihnen x- und y-Koordinatenfelder (in diesem Fall 2D) gibt, die dann verwendet werden können, um die Maske mit der Gleichung der Linien zu berechnen.

Edit: Sofern Sie Ihre Maske mit einer Gleichung ausdrücken kann (wie f(x,y)<0 wobei f jede gewünschte Funktion) oder eine Kombination dieser Gleichungen, können Sie alles, was Sie tun wollen. Hier ist ein Beispiel mit der neuen Maske zusammen mit einigen zusätzlichen Kunststücke:

import numpy as np 
import matplotlib.pyplot as plt 

y,x=np.mgrid[0:1000,0:1000] 

#a wiggly ramp 
plt.subplot(221) 
mask0=(y < x + 20 * np.sin(0.05*x)) & (y > x - 100 + 20 * np.sin(0.05*x)) 
plt.imshow(mask0,origin='lower',cmap='gray') 

#a ramp 
plt.subplot(222) 
mask1=(y < x) & (x < y+100) 
plt.imshow(mask1,origin='lower',cmap='gray') 

#a disk 
plt.subplot(223) 
mask2=(200**2>(x-500)**2+(y-500)**2) 
plt.imshow(mask2,origin='lower',cmap='gray') 

#a ying-yang attempt 
plt.subplot(224) 
mask3= (mask2 & (0 < np.sin(3.14*x/250)*100 + 500 - y) & (30**2 < (x-620)**2+(y-500)**2))| (30**2 > (x-380)**2+(y-500)**2) 
plt.imshow(mask3,origin='lower',cmap='gray') 

plt.show() 

Ausgang:

Output

+0

Vielen Dank @jadsq für Ihr Beispiel. Ich war mir dieser mgrid-Methode nicht bewusst ... Allerdings habe ich kein gutes Beispiel für meine Frage angegeben: Diese Lösung funktioniert für gerade Linien, aber nicht für Kurven ... Ich habe meinen ursprünglichen Code geändert, um das Problem besser darzustellen ...denkst du, dass es irgendwie angepasst werden kann? – Delosari

+0

Wow das ist sehr ordentlich vielen Dank !! – Delosari

5

Der Codeausschnitt unten eine Maske erstellt, setzt alle Werte außerhalb der Maske zu nan, und verwendet dann NumPy nanmedian, um die gewünschte Menge in der angegebenen Richtung zu berechnen.

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() 

Median along rows inside region of interest

+1

Vielen Dank für die Antwort Stefan! Es ist sehr sauber, aber ich denke, ich habe mich nicht richtig erklärt: Ich glaube, dass diese Polygon-Methode nur funktioniert, wenn die Schnittkanten völlig gerade sind ... Es wird nicht die richtige Lösung für gekrümmte Kanten geben ... Denkst du Kann es irgendwie angepasst werden? (Ich habe das Beispiel mit einem bisschen von Ihnen aktualisiert) – Delosari

+0

In diesem Fall gibt Ihnen die beiden oben genannten Lösungen in Kombination, was Sie brauchen. Nicht, dass Sie mit dieser Operation viel Speicher verbrauchen; Eine Schleife in Cython, Numba, Pypi usw. wäre viel schneller. –

Verwandte Themen