Commit f54778ba authored by Jennifer Lorena Ortega Aguilar's avatar Jennifer Lorena Ortega Aguilar
Browse files

BPF

parent d132a31b
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
"#imagename = \"Data/crateres.jpg\"\n", "#imagename = \"Data/crateres.jpg\"\n",
"#imagename = \"Data/Perseverance_ZR0_0074.png\" -codigo adicional para recorte de bordes negros.\n", "#imagename = \"Data/Perseverance_ZR0_0074.png\" -codigo adicional para recorte de bordes negros.\n",
"#imagename = \"Data/mastcamz_2_prints.jpg\"\n", "#imagename = \"Data/mastcamz_2_prints.jpg\"\n",
"imagename = \"Data/Data_Mars_Mars8.png\"\n", "imagename = \"Data_Mars/Mars8.png\"\n",
" \n", " \n",
"# read the image data using PIL\n", "# read the image data using PIL\n",
"image = Image.open(imagename)" "image = Image.open(imagename)"
......
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import cv2 import cv2
import numpy as np import numpy as np
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
from PIL import Image from PIL import Image
from PIL.ExifTags import TAGS from PIL.ExifTags import TAGS
from numpy import asarray from numpy import asarray
from numpy.fft import fft2, fftshift, fftfreq, ifft2 #Python DFT from numpy.fft import fft2, fftshift, fftfreq, ifft2 #Python DFT
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#imagename = "Data/crateres.jpg" #imagename = "Data/crateres.jpg"
#imagename = "Data/Perseverance_ZR0_0074.png" -codigo adicional para recorte de bordes negros. #imagename = "Data/Perseverance_ZR0_0074.png" -codigo adicional para recorte de bordes negros.
#imagename = "Data/mastcamz_2_prints.jpg" #imagename = "Data/mastcamz_2_prints.jpg"
imagename = "Data/Data_Mars_Mars8.png" imagename = "Data_Mars/Mars8.png"
# read the image data using PIL # read the image data using PIL
image = Image.open(imagename) image = Image.open(imagename)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
display (image) display (image)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
crateres.jpg : Image downloaded from : https://mars.nasa.gov/mars2020-raw-images/pub/ods/surface/sol/00000/ids/edr/browse/edl/ELM_0000_0666952859_600ECM_N0000030LVS_04000_0000LUJ00_800.jpg crateres.jpg : Image downloaded from : https://mars.nasa.gov/mars2020-raw-images/pub/ods/surface/sol/00000/ids/edr/browse/edl/ELM_0000_0666952859_600ECM_N0000030LVS_04000_0000LUJ00_800.jpg
Perseverance_ZR=_0074.png : Image downloaded from : Perseverance_ZR=_0074.png : Image downloaded from :
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
img = cv2.imread(imagename, 0) # load an image img = cv2.imread(imagename, 0) # load an image
#3 = np.asarray(imagename, dtype = np.float32) # Image class instance, I1, to float32 Numpy array, a #3 = np.asarray(imagename, dtype = np.float32) # Image class instance, I1, to float32 Numpy array, a
img_float32 = np.float32(img) img_float32 = np.float32(img)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Para procesar la imagen se lee como cv2.imread y luego se le aplica la DFT Para procesar la imagen se lee como cv2.imread y luego se le aplica la DFT
DFT: Discrete Fourier Transform. DFT: Discrete Fourier Transform.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
hist =cv2.calcHist([img],[0],None,[256],[0,256]) hist =cv2.calcHist([img],[0],None,[256],[0,256])
plt.plot(hist,color='blue') plt.plot(hist,color='blue')
plt.xlabel('Intensidad de Iluminacion') plt.xlabel('Intensidad de Iluminacion')
plt.ylabel('Pixels Bins') plt.ylabel('Pixels Bins')
plt.show() plt.show()
plt.hist(np.concatenate((img),axis=0),bins=250) plt.hist(np.concatenate((img),axis=0),bins=250)
plt.xlabel('Intensidad de Iluminacion') plt.xlabel('Intensidad de Iluminacion')
plt.ylabel('Pixels Bins') plt.ylabel('Pixels Bins')
plt.show() plt.show()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#transform,ar el array de la imagen en punto flotante para ser procesado. #transform,ar el array de la imagen en punto flotante para ser procesado.
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT) dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift =np.fft.fftshift(dft) dft_shift =np.fft.fftshift(dft)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# convert image to numpy array # convert image to numpy array
data = asarray(image) data = asarray(image)
print(type(data)) print(type(data))
# caracteristicas de la imagen # caracteristicas de la imagen
print(data.shape) print(data.shape)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Muestra cada valor de cada pixel de la imagen como array en Numpy #Muestra cada valor de cada pixel de la imagen como array en Numpy
#print(data) #print(data)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#imagen en el espacio de las frecuencias : #imagen en el espacio de las frecuencias :
f = np.fft.fft2(img) #fft2 para 2 dimensiones f = np.fft.fft2(img) #fft2 para 2 dimensiones
fshift = np.fft.fftshift(f) # para centrar las frecuencias bajas. fshift = np.fft.fftshift(f) # para centrar las frecuencias bajas.
# fft2 tiene valors imaginarios por ello se saca el espectro real o de magnitud. # fft2 tiene valors imaginarios por ello se saca el espectro real o de magnitud.
magnitude_sprectrum = 20*np.log(np.abs(fshift)) magnitude_sprectrum = 20*np.log(np.abs(fshift))
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
f.shape f.shape
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fft2(f) fft2(f)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Matplotlib para crear 2 subplots en la misma linea para comparar la imagen original y #Matplotlib para crear 2 subplots en la misma linea para comparar la imagen original y
#la imagen transformada en el espectro de frecuencias. #la imagen transformada en el espectro de frecuencias.
plt.subplot(121),plt.imshow(img , cmap = 'gray') plt.subplot(121),plt.imshow(img , cmap = 'gray')
plt.title('Original Image'), plt.xticks([]),plt.yticks([]) plt.title('Original Image'), plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_sprectrum , cmap = 'gray') plt.subplot(122),plt.imshow(magnitude_sprectrum , cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]),plt.yticks([]) plt.title('Magnitude Spectrum'), plt.xticks([]),plt.yticks([])
plt.show plt.show
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Filtro pasa alto HPF en el dominio de las frencuencias para demarcar contornos: #Filtro pasa alto HPF en el dominio de las frencuencias para demarcar contornos:
rows, cols = img.shape rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) crow, ccol = int(rows/2), int(cols/2)
#remover las frecuencias bajas usando una plantilla circular #remover las frecuencias bajas usando una plantilla circular
mask=np.ones((rows,cols,2),np.uint8) mask=np.ones((rows,cols,2),np.uint8)
r = 40 r = 40
center = [crow, ccol] center = [crow, ccol]
x, y = np.ogrid[:rows, :cols] x, y = np.ogrid[:rows, :cols]
mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r*r mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r*r
mask[mask_area] = 1 mask[mask_area] = 1
fshift=dft_shift*mask fshift=dft_shift*mask
fshift_mask_mag=2000*np.log(cv2.magnitude(fshift[:,:,0],fshift[:,:,1])) fshift_mask_mag=2000*np.log(cv2.magnitude(fshift[:,:,0],fshift[:,:,1]))
f_ishift =np.fft.ifftshift(fshift) f_ishift =np.fft.ifftshift(fshift)
img_back =cv2.idft(f_ishift) img_back =cv2.idft(f_ishift)
img_back =cv2.magnitude(img_back[:,:,0],img_back[:,:,1]) img_back =cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
#fshift[crow-30:crow+30,ccol-30:ccol+30]=0 #fshift[crow-30:crow+30,ccol-30:ccol+30]=0
f_ishift = np.fft.ifftshift(fshift) f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift) img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back) img_back = np.abs(img_back)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Filtro pasa Banda BPF aplicando dos circulos concentricos #Filtro pasa Banda BPF aplicando dos circulos concentricos
rows, cols = img.shape rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) # circulo centro crow, ccol = int(rows/2), int(cols/2) # circulo centro
#remover las frecuencias bajas usando una plantilla circular #remover las frecuencias bajas usando una plantilla circular
rows, cols = img.shape rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) crow, ccol = int(rows/2), int(cols/2)
mask=np.zeros((rows,cols,2),np.uint8) mask=np.zeros((rows,cols,2),np.uint8)
r_out = 40 r_out = 40
r_in = 4 r_in = 4
center = [crow, ccol] center = [crow, ccol]
x, y = np.ogrid[:rows, :cols] x, y = np.ogrid[:rows, :cols]
mask_area = np.logical_and(((x-center[0])**2 +(y-center[1])**2>= r_in**2), mask_area = np.logical_and(((x-center[0])**2 +(y-center[1])**2>= r_in**2),
((x-center[0])**2 +(y-center[1])**2<= r_out**2)) ((x-center[0])**2 +(y-center[1])**2<= r_out**2))
mask[mask_area] = 1 mask[mask_area] = 1
fshift=dft_shift*mask fshift=dft_shift*mask
fshift_mask_mag= 2000 * np.log(cv2.magnitude(fshift[:, :, 0], fshift[:, :, 1])) fshift_mask_mag= 2000 * np.log(cv2.magnitude(fshift[:, :, 0], fshift[:, :, 1]))
f_ishift =np.fft.ifftshift(fshift) f_ishift =np.fft.ifftshift(fshift)
img_back =cv2.idft(f_ishift) img_back =cv2.idft(f_ishift)
img_back =cv2.magnitude(img_back[:,:,0],img_back[:,:,1]) img_back =cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
#fshift[crow-30:crow+30,ccol-30:ccol+30]=0 #fshift[crow-30:crow+30,ccol-30:ccol+30]=0
fig = plt.figure(figsize=(20,20)) fig = plt.figure(figsize=(20,20))
fig.add_subplot(2, 2, 1), plt.imshow(img, cmap='gray') fig.add_subplot(2, 2, 1), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([]) plt.title('Input Image'), plt.xticks([]), plt.yticks([])
fig.add_subplot(2, 2, 2), plt.imshow(magnitude_sprectrum,cmap='gray') fig.add_subplot(2, 2, 2), plt.imshow(magnitude_sprectrum,cmap='gray')
plt.title('After FFT'), plt.xticks([]), plt.yticks([]) plt.title('After FFT'), plt.xticks([]), plt.yticks([])
fig.add_subplot(2, 2, 3), plt.imshow(fshift_mask_mag, cmap='gray') fig.add_subplot(2, 2, 3), plt.imshow(fshift_mask_mag, cmap='gray')
plt.title('FFT + Mask'), plt.xticks([]), plt.yticks([]) plt.title('FFT + Mask'), plt.xticks([]), plt.yticks([])
fig.add_subplot(2, 2, 4), plt.imshow(img_back, cmap='gray') fig.add_subplot(2, 2, 4), plt.imshow(img_back, cmap='gray')
plt.title('After FFT Inverse'), plt.xticks([]), plt.yticks([]) plt.title('After FFT Inverse'), plt.xticks([]), plt.yticks([])
plt.show() plt.show()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Filtro pasa Banda BPF aplicando dos circulos concentricos #Filtro pasa Banda BPF aplicando dos circulos concentricos
rows, cols = img.shape rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) # circulo centro crow, ccol = int(rows/2), int(cols/2) # circulo centro
#remover las frecuencias bajas usando una plantilla circular #remover las frecuencias bajas usando una plantilla circular
rows, cols = img.shape rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) crow, ccol = int(rows/2), int(cols/2)
mask=np.zeros((rows,cols,2),np.uint8) mask=np.zeros((rows,cols,2),np.uint8)
#con diferentes radios tal que sean mayor que la zona central, tapando la mayor cantidad de bajas frencuencias. #con diferentes radios tal que sean mayor que la zona central, tapando la mayor cantidad de bajas frencuencias.
r_out = 80 r_out = 80
r_in = 4 r_in = 4
center = [crow, ccol] center = [crow, ccol]
x, y = np.ogrid[:rows, :cols] x, y = np.ogrid[:rows, :cols]
mask_area = np.logical_and(((x-center[0])**2 +(y-center[1])**2>= r_in**2), mask_area = np.logical_and(((x-center[0])**2 +(y-center[1])**2>= r_in**2),
((x-center[0])**2 +(y-center[1])**2<= r_out**2)) ((x-center[0])**2 +(y-center[1])**2<= r_out**2))
mask[mask_area] = 1 mask[mask_area] = 1
fshift=dft_shift*mask fshift=dft_shift*mask
fshift_mask_mag= 2000 * np.log(cv2.magnitude(fshift[:, :, 0], fshift[:, :, 1])) fshift_mask_mag= 2000 * np.log(cv2.magnitude(fshift[:, :, 0], fshift[:, :, 1]))
f_ishift =np.fft.ifftshift(fshift) f_ishift =np.fft.ifftshift(fshift)
img_back =cv2.idft(f_ishift) img_back =cv2.idft(f_ishift)
img_back =cv2.magnitude(img_back[:,:,0],img_back[:,:,1]) img_back =cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
fig = plt.figure(figsize=(20,20)) fig = plt.figure(figsize=(20,20))
fig.add_subplot(121),plt.imshow(img , cmap = 'gray') fig.add_subplot(121),plt.imshow(img , cmap = 'gray')
plt.title('Original Image'), plt.xticks([]),plt.yticks([]) plt.title('Original Image'), plt.xticks([]),plt.yticks([])
fig.add_subplot(122),plt.imshow(img_back , cmap = 'gray') fig.add_subplot(122),plt.imshow(img_back , cmap = 'gray')
plt.title('AFTER FFT Inverse image'), plt.xticks([]),plt.yticks([]) plt.title('AFTER FFT Inverse image'), plt.xticks([]),plt.yticks([])
plt.show() plt.show()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
plt.subplot(131),plt.imshow(img, cmap='gray') plt.subplot(131),plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([]) plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(img_back , cmap = 'gray') plt.subplot(132),plt.imshow(img_back , cmap = 'gray')
plt.title('Imagen con HPF'), plt.xticks([]),plt.yticks([]) plt.title('Imagen con HPF'), plt.xticks([]),plt.yticks([])
plt.subplot(133),plt.imshow(img_back) plt.subplot(133),plt.imshow(img_back)
plt.title('Imagen Final'), plt.xticks([]),plt.yticks([]) plt.title('Imagen Final'), plt.xticks([]),plt.yticks([])
plt.show plt.show
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fig = plt.figure(figsize=(20,20)) fig = plt.figure(figsize=(20,20))
fig.add_subplot(121),plt.imshow(img , cmap = 'gray') fig.add_subplot(121),plt.imshow(img , cmap = 'gray')
plt.title('Original Image'), plt.xticks([]),plt.yticks([]) plt.title('Original Image'), plt.xticks([]),plt.yticks([])
fig.add_subplot(122),plt.imshow(img_back , cmap = 'gray') fig.add_subplot(122),plt.imshow(img_back , cmap = 'gray')
plt.title('HPF image'), plt.xticks([]),plt.yticks([]) plt.title('HPF image'), plt.xticks([]),plt.yticks([])
plt.show plt.show
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#Comparativa para la foto de las rocas #Comparativa para la foto de las rocas
#recortado de foto #recortado de foto
#Recortar una imagen #Recortar una imagen
crop= img[200:400,200:500] crop= img[200:400,200:500]
cv2.imshow('Seccion Imagen',crop) cv2.imshow('Seccion Imagen',crop)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#filtro Pasa bajos: LPF #filtro Pasa bajos: LPF
dft_shift= np.fft.fftshift(dft) dft_shift= np.fft.fftshift(dft)
rows, cols = img.shape rows, cols = img.shape
crow , ccol = int(rows/2), int(cols/2) crow , ccol = int(rows/2), int(cols/2)
mask= np.zeros((rows,cols,2),np.uint8) mask= np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30,ccol-30:ccol+30]=1 mask[crow-30:crow+30,ccol-30:ccol+30]=1
fshift = dft_shift*mask fshift = dft_shift*mask
f_ishift=np.fft.ifftshift(fshift) f_ishift=np.fft.ifftshift(fshift)
img_back=cv2.idft(f_ishift) img_back=cv2.idft(f_ishift)
img_back=cv2.magnitude(img_back[:,:,0],img_back[:,:,1]) img_back=cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fig = plt.figure(figsize=(20,20)) fig = plt.figure(figsize=(20,20))
fig.add_subplot(121),plt.imshow(img , cmap = 'gray') fig.add_subplot(121),plt.imshow(img , cmap = 'gray')
plt.title('Original Image'), plt.xticks([]),plt.yticks([]) plt.title('Original Image'), plt.xticks([]),plt.yticks([])
fig.add_subplot(122),plt.imshow(img_back , cmap = 'gray') fig.add_subplot(122),plt.imshow(img_back , cmap = 'gray')
plt.title('LPF image'), plt.xticks([]),plt.yticks([]) plt.title('LPF image'), plt.xticks([]),plt.yticks([])
plt.show plt.show
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
...@@ -561,6 +561,21 @@ ...@@ -561,6 +561,21 @@
"plt.show()\n" "plt.show()\n"
] ]
}, },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Cráteres\n",
"path = 'Data_Mars/crateres.jpg'\n",
"seg.gra_umbral(path)\n",
"umbral = 70\n",
"img10 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.10)\n",
"plt.imshow(img10[200:300, 100:200])\n",
"plt.show()"
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
...@@ -676,7 +691,7 @@ ...@@ -676,7 +691,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.7.6" "version": "3.7.3"
} }
}, },
"nbformat": 4, "nbformat": 4,
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Data Analysis with images from Mars # Data Analysis with images from Mars
## Nombres: Jennifer Ortega (EPN), Gerardo Semprum (UCV), Carla Gomez (USB) ## Nombres: Jennifer Ortega (EPN), Gerardo Semprum (UCV), Carla Gomez (USB)
## Segmentación de Imágenes de Marte ## Segmentación de Imágenes de Marte
El presente proyecto realiza una segmentación de imágenes de Marte, adquiridadas por el rover Mars Perseverance de la NASA, mediante el algoritmo de watershed. El presente proyecto realiza una segmentación de imágenes de Marte, adquiridadas por el rover Mars Perseverance de la NASA, mediante el algoritmo de watershed.
### Estructura del notebook ### Estructura del notebook
- Carga y visualización de la imagen - Carga y visualización de la imagen
- Tranformación de la imagen de RGB a Escala de Grises - Tranformación de la imagen de RGB a Escala de Grises
- Establecer umbral para la segmentación - Establecer umbral para la segmentación
- Cálculo de marcadores - Cálculo de marcadores
- Aplicación del algoritmo Watershed - Aplicación del algoritmo Watershed
- Análisis - Análisis
- Conclusiones - Conclusiones
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
--- ---
<font color='gray'> <font color='gray'>
### Imagen ### Imagen
Las imágenes digitales en color están hechas de píxeles. Un pixel es la menor unidad homogénea con color de la imagen, el pixel esta formado por combinaciones de colores primarios como son el **rojo**, **verde** y **azul** conocidos como canales **RGB**. Las imágenes digitales en color están hechas de píxeles. Un pixel es la menor unidad homogénea con color de la imagen, el pixel esta formado por combinaciones de colores primarios como son el **rojo**, **verde** y **azul** conocidos como canales **RGB**.
La imagen puede ser representada por una matriz de dimensiones NxM, donde cada elemento de la matriz es una matriz de 3 componentes, cada componente del elemento contiene los valores para los canales R, G y B de la imagen ([R G B]). La imagen puede ser representada por una matriz de dimensiones NxM, donde cada elemento de la matriz es una matriz de 3 componentes, cada componente del elemento contiene los valores para los canales R, G y B de la imagen ([R G B]).
--- ---
</font> </font>
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Carga y visualización de la imagen ### Carga y visualización de la imagen
- Para cargar la imagen utilizamos la biblioteca **PIL** de Python diseñada para el manejo y procesamiento de imágenes. - Para cargar la imagen utilizamos la biblioteca **PIL** de Python diseñada para el manejo y procesamiento de imágenes.
- La imagen es guardada en formato **numpy.ndarray**, que representa una matriz multidimensional. La matriz es de dimensión 1200 x 1648, donde cada elemento de la matriz es un array de 3 componentes. Cada componente del elemento contiene los valores para los canales R, G y B de la imagen. - La imagen es guardada en formato **numpy.ndarray**, que representa una matriz multidimensional. La matriz es de dimensión 1200 x 1648, donde cada elemento de la matriz es un array de 3 componentes. Cada componente del elemento contiene los valores para los canales R, G y B de la imagen.
- La imagen se puede encontrar <a href="https://mars.nasa.gov/mars2020/multimedia/raw-images/ZL0_0072_0673337731_644EBY_N0032208ZCAM08032_1100LUJ">aquí.</a> El rover Mars Perseverance de la NASA adquirió esta imagen usando su cámara Left Mastcam-Z., Mastcam-Z que son un par de cámaras ubicadas en lo alto del mástil del rover. Esta imagen fue adquirida en mayo. 04, 2021 (Sol 72) a la hora solar media local de 14:00:34. - La imagen se puede encontrar <a href="https://mars.nasa.gov/mars2020/multimedia/raw-images/ZL0_0072_0673337731_644EBY_N0032208ZCAM08032_1100LUJ">aquí.</a> El rover Mars Perseverance de la NASA adquirió esta imagen usando su cámara Left Mastcam-Z., Mastcam-Z que son un par de cámaras ubicadas en lo alto del mástil del rover. Esta imagen fue adquirida en mayo. 04, 2021 (Sol 72) a la hora solar media local de 14:00:34.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Bibliotecas # Bibliotecas
import numpy as np import numpy as np
from PIL import Image from PIL import Image
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import matplotlib.cm as cm import matplotlib.cm as cm
import cv2 import cv2
from numpy import asarray from numpy import asarray
from matplotlib.pyplot import figure from matplotlib.pyplot import figure
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%matplotlib inline %matplotlib inline
%config InlineBackend.figure_format = 'retina' %config InlineBackend.figure_format = 'retina'
#------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------
image = Image.open('Data_Mars/Mars8.png') # cargamos la imagen image = Image.open('Data_Mars/Mars8.png') # cargamos la imagen
matriz = asarray(image) # abrimos la imagen en formato numpy.ndarray matriz = asarray(image) # abrimos la imagen en formato numpy.ndarray
img = cv2.imread('Data_Mars/Mars8.png') img = cv2.imread('Data_Mars/Mars8.png')
img = img[:,50:-50] # recortamos la imagen ya que existen bordes negros en la imagen img = img[:,50:-50] # recortamos la imagen ya que existen bordes negros en la imagen
#------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------------
print('La matriz es de la clase: ', type(matriz)) print('La matriz es de la clase: ', type(matriz))
print('El número de elementos de la matriz es: ', matriz.size) print('El número de elementos de la matriz es: ', matriz.size)
print('La dimensión de la matriz es de: ',matriz.shape) print('La dimensión de la matriz es de: ',matriz.shape)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- Visualización de la imagen original descargada de la página web de la NASA, y una representación de cada uno de los canales R,G,B de la imagen. - Visualización de la imagen original descargada de la página web de la NASA, y una representación de cada uno de los canales R,G,B de la imagen.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
R, G, B = matriz[:, :, 0], matriz[:, :, 1], matriz[:, :, 2] # Separamos las matrices según R,G,B R, G, B = matriz[:, :, 0], matriz[:, :, 1], matriz[:, :, 2] # Separamos las matrices según R,G,B
zeros = np.zeros((B.shape), dtype=int) zeros = np.zeros((B.shape), dtype=int)
# Procedemos a separar la imagen según los canales # Procedemos a separar la imagen según los canales
# Canal Rojo -------------------------------------------------------------------------- # Canal Rojo --------------------------------------------------------------------------
matriz_canal_r = np.zeros((matriz.shape), dtype=int) matriz_canal_r = np.zeros((matriz.shape), dtype=int)
matriz_canal_r[:, :, 0], matriz_canal_r[:, :, 1], matriz_canal_r[:, :, 2] = R , zeros, zeros matriz_canal_r[:, :, 0], matriz_canal_r[:, :, 1], matriz_canal_r[:, :, 2] = R , zeros, zeros
# Canal Verde-------------------------------------------------------------------------- # Canal Verde--------------------------------------------------------------------------
matriz_canal_g = np.zeros((matriz.shape), dtype=int) matriz_canal_g = np.zeros((matriz.shape), dtype=int)
matriz_canal_g[:, :, 0], matriz_canal_g[:, :, 1], matriz_canal_g[:, :, 2] = zeros, G, zeros matriz_canal_g[:, :, 0], matriz_canal_g[:, :, 1], matriz_canal_g[:, :, 2] = zeros, G, zeros
# Canal Azul--------------------------------------------------------------------------- # Canal Azul---------------------------------------------------------------------------
matriz_canal_b = np.zeros((matriz.shape), dtype=int) matriz_canal_b = np.zeros((matriz.shape), dtype=int)
matriz_canal_b[:, :, 0], matriz_canal_b[:, :, 1], matriz_canal_b[:, :, 2] = zeros, zeros, B matriz_canal_b[:, :, 0], matriz_canal_b[:, :, 1], matriz_canal_b[:, :, 2] = zeros, zeros, B
# Gráficas----------------------------------------------------------------------------- # Gráficas-----------------------------------------------------------------------------
fig, ([ax1, ax2],[ ax3,ax4]) = plt.subplots(2,2, figsize=(12,10)) fig, ([ax1, ax2],[ ax3,ax4]) = plt.subplots(2,2, figsize=(12,10))
ax1.imshow(matriz) ax1.imshow(matriz)
ax1.set_title('Imagen Original') ax1.set_title('Imagen Original')
ax2.imshow(matriz_canal_r) ax2.imshow(matriz_canal_r)
ax2.set_title('Canal Rojo') ax2.set_title('Canal Rojo')
ax3.imshow(matriz_canal_g) ax3.imshow(matriz_canal_g)
ax3.set_title('Canal Verde') ax3.set_title('Canal Verde')
ax4.imshow(matriz_canal_b) ax4.imshow(matriz_canal_b)
ax4.set_title('Canal Azul') ax4.set_title('Canal Azul')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Tranformación de la imagen de RGB a Escala de Grises ### Tranformación de la imagen de RGB a Escala de Grises
- Procedemos ha realizar la transformación de GRB a escala de Grises mediante la siguiente ecuación: - Procedemos ha realizar la transformación de GRB a escala de Grises mediante la siguiente ecuación:
$$ Grayscale= (0.299\times R+0.587\times G+0.114\times B)$$ $$ Grayscale= (0.299\times R+0.587\times G+0.114\times B)$$
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
Grayscale =0.299*R+0.587*G+0.114*B Grayscale =0.299*R+0.587*G+0.114*B
Grayscale = Grayscale[:,50:-50] Grayscale = Grayscale[:,50:-50]
plt.imshow(Grayscale, 'gray') # imprimimos la imagen en escala de Grises. plt.imshow(Grayscale, 'gray') # imprimimos la imagen en escala de Grises.
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
--- ---
<font color='gray'> <font color='gray'>
### Segmentación ### Segmentación
La segmentación de imágenes divide la imagen en sus partes o regiones, esta técnica permite extraer información de los objetos. La división en partes se basa a menudo en las características de los píxeles de la imagen. La segmentación de imágenes divide la imagen en sus partes o regiones, esta técnica permite extraer información de los objetos. La división en partes se basa a menudo en las características de los píxeles de la imagen.
### Algoritmo Watershed ### Algoritmo Watershed
Es una técnica de segmentación de imágenes basada en marcadores, el algoritmo de **Watershed** se fundamenta en el concepto de visualizar una imagen como una superficie topográfica donde los valores de alta intensidad denotan picos y colinas mientras que los de baja intensidad denotan valles (mínimos locales). Esto se puede obtener trazando las coordenadas de la imagen (x, y) en función de sus valores de intensidad. Es una técnica de segmentación de imágenes basada en marcadores, el algoritmo de **Watershed** se fundamenta en el concepto de visualizar una imagen como una superficie topográfica donde los valores de alta intensidad denotan picos y colinas mientras que los de baja intensidad denotan valles (mínimos locales). Esto se puede obtener trazando las coordenadas de la imagen (x, y) en función de sus valores de intensidad.
El algoritmo comienza "inundando de agua" alrededor de la superficie topográfica de la imagen. Cuando el agua fusiona los picos, se construyen barreras para evitar esta fusión, hasta que todos los picos estén bajo el agua. Las barreras resultantes dan la segmentación de picos y valles en la imagen. Este enfoque produce una sobresegmentación debido al ruido o cualquier otra irregularidad en la imagen, por lo que algunos algoritmos han implementado marcadores que especifican cuáles son todos los puntos de valle que se fusionarán y cuáles no. El algoritmo comienza "inundando de agua" alrededor de la superficie topográfica de la imagen. Cuando el agua fusiona los picos, se construyen barreras para evitar esta fusión, hasta que todos los picos estén bajo el agua. Las barreras resultantes dan la segmentación de picos y valles en la imagen. Este enfoque produce una sobresegmentación debido al ruido o cualquier otra irregularidad en la imagen, por lo que algunos algoritmos han implementado marcadores que especifican cuáles son todos los puntos de valle que se fusionarán y cuáles no.
<img src="imagenes/watershed.png"> <img src="imagenes/watershed.png">
</font> </font>
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<font color='gray'> <font color='gray'>
### Función Watershed de Open CV ### Función Watershed de Open CV
Para realizar la segmentación se utilizará la función **cv2.watershed** de la biblioteca libre de visión artificial OpenCV (**cv2**), esta función implementa marcadores para evitar una segmentación excesiva. Para realizar la segmentación se utilizará la función **cv2.watershed** de la biblioteca libre de visión artificial OpenCV (**cv2**), esta función implementa marcadores para evitar una segmentación excesiva.
Para establecer los marcadores tenemos que etiquetar la imagen en 3 regiones, la primera es la región que estamos seguros de ser fondo, la región que estamos seguros que es un objeto y finalmente la región que desconocemos que tipo de superficie sea, esta última región se la etiqueta con 0. El algoritmo retornará una matriz cuya región que sea etiquetada con -1 es la que corresponde a los límites del objeto. Para establecer los marcadores tenemos que etiquetar la imagen en 3 regiones, la primera es la región que estamos seguros de ser fondo, la región que estamos seguros que es un objeto y finalmente la región que desconocemos que tipo de superficie sea, esta última región se la etiqueta con 0. El algoritmo retornará una matriz cuya región que sea etiquetada con -1 es la que corresponde a los límites del objeto.
--- ---
</font> </font>
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Establecer el umbral para la segmentación ### Establecer el umbral para la segmentación
Se establece un umbral en la imagen, esto se realiza para posteriormente determinar los marcadores, el umbral es el valor de píxel con el cual se realizará una división de la imagen en dos zonas, la primera corresponde a los píxeles menores a este umbral y la segunda los píxeles con valores superiores al umbral. Para determinar el umbral es necesario: Se establece un umbral en la imagen, esto se realiza para posteriormente determinar los marcadores, el umbral es el valor de píxel con el cual se realizará una división de la imagen en dos zonas, la primera corresponde a los píxeles menores a este umbral y la segunda los píxeles con valores superiores al umbral. Para determinar el umbral es necesario:
- Recortar una sección de la imagen donde se encuentre el objeto que quiere que el algoritmo segmente (divida). - Recortar una sección de la imagen donde se encuentre el objeto que quiere que el algoritmo segmente (divida).
- Realizar una cuantificación de los píxeles presentes en la imagen recortada, para poder elegir un buen umbral, esto se lo puede hacer mediante un histograma. - Realizar una cuantificación de los píxeles presentes en la imagen recortada, para poder elegir un buen umbral, esto se lo puede hacer mediante un histograma.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fig, (ax2, ax1) = plt.subplots(1,2, figsize=(12,4)) fig, (ax2, ax1) = plt.subplots(1,2, figsize=(12,4))
ax1.set_title('Histograma de la intensidad de los píxeles') ax1.set_title('Histograma de la intensidad de los píxeles')
ax1.set_ylabel('Número de Píxeles') ax1.set_ylabel('Número de Píxeles')
ax1.set_xlabel('Intesidad del píxel') ax1.set_xlabel('Intesidad del píxel')
ax1.hist(np.concatenate((Grayscale), axis=0), bins=250) ax1.hist(np.concatenate((Grayscale), axis=0), bins=250)
ax2.set_title('Imagen en escala de grises') ax2.set_title('Imagen en escala de grises')
#ax2.xlabel('Intesidad del píxel') #ax2.xlabel('Intesidad del píxel')
ax2.imshow(Grayscale, 'gray') ax2.imshow(Grayscale, 'gray')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- El histograma de las intensidades de luminosidad de los píxeles de la imagen nos da una idea de cual es la cantidad de objetos presentes en la imagen y su distribución en la misma. - El histograma de las intensidades de luminosidad de los píxeles de la imagen nos da una idea de cual es la cantidad de objetos presentes en la imagen y su distribución en la misma.
- Los valores que se encuentran entre los valores [100,250] podrían ser considerados como fondo ya que aquí se encuentra concentrada la mayor cantidad de valores de luminosidad, mientras que los valores que son menores o mayores a este valor podrían ser los objetos. - Los valores que se encuentran entre los valores [100,250] podrían ser considerados como fondo ya que aquí se encuentra concentrada la mayor cantidad de valores de luminosidad, mientras que los valores que son menores o mayores a este valor podrían ser los objetos.
Ahora concentrémonos en un objeto en específico que sería una roca, para eso recortamos la imagen y la analizamos, para determinar cuál es el umbral. Ahora concentrémonos en un objeto en específico que sería una roca, para eso recortamos la imagen y la analizamos, para determinar cuál es el umbral.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
plt.imshow(Grayscale[200:400,200:600], 'gray') plt.imshow(Grayscale[200:400,200:600], 'gray')
plt.show() plt.show()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
gray_total = np.concatenate((Grayscale[200:400,200:600]), axis=0) gray_total = np.concatenate((Grayscale[200:400,200:600]), axis=0)
plt.title('Histograma de la intensidad de los píxeles en imagen recortada') plt.title('Histograma de la intensidad de los píxeles en imagen recortada')
plt.ylabel('Número de Píxeles') plt.ylabel('Número de Píxeles')
plt.xlabel('Intesidad del píxel') plt.xlabel('Intesidad del píxel')
plt.hist(gray_total, bins=250) plt.hist(gray_total, bins=250)
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- El histograma nos muestra para la imagen recortada que los píxeles se dividen en 2 zonas, los píxeles con valores mayores a 125 y menores a este mismo número, por lo que tomar este valor como umbral, sería un buen comienzo para esta imagen, entonces el **umbral = 100**, este umbral nos da una perspectiva de como se encuentran distribuidas las luminosidades en la imagen y cuales píxeles se podrían considerar como fondo, y cuales no, además de lo que ya consideramos anteriormente en qué valores se encontraba el fondo, lo ideal sería elegir a los píxeles correspondientes a rocas como objeto y la arena como fondo, pero en este caso no se puede tomar de esta forma ya que las rocas tienen casi el mismo valor de píxel y algunas zonas corespondientes a fondo podría el algoritmo considerar como objeto. - El histograma nos muestra para la imagen recortada que los píxeles se dividen en 2 zonas, los píxeles con valores mayores a 125 y menores a este mismo número, por lo que tomar este valor como umbral, sería un buen comienzo para esta imagen, entonces el **umbral = 100**, este umbral nos da una perspectiva de como se encuentran distribuidas las luminosidades en la imagen y cuales píxeles se podrían considerar como fondo, y cuales no, además de lo que ya consideramos anteriormente en qué valores se encontraba el fondo, lo ideal sería elegir a los píxeles correspondientes a rocas como objeto y la arena como fondo, pero en este caso no se puede tomar de esta forma ya que las rocas tienen casi el mismo valor de píxel y algunas zonas corespondientes a fondo podría el algoritmo considerar como objeto.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Cálculo de Marcadores ### Cálculo de Marcadores
- Utilizaremos la función **cv2.threshold**, dependiendo del umbral ingresado la función genera una imagen de ceros y unos. Si el píxel de la imagen supera el umbral lo reescribe como 1 si el píxel no supera el umbral lo transforma en 0. - Utilizaremos la función **cv2.threshold**, dependiendo del umbral ingresado la función genera una imagen de ceros y unos. Si el píxel de la imagen supera el umbral lo reescribe como 1 si el píxel no supera el umbral lo transforma en 0.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
umbral = 110 umbral = 110
_, thresh = cv2.threshold(Grayscale, umbral, 255,cv2.THRESH_BINARY_INV ) _, thresh = cv2.threshold(Grayscale, umbral, 255,cv2.THRESH_BINARY_INV )
plt.imshow(thresh, 'gray') plt.imshow(thresh, 'gray')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- Ahora utilizaremos la función **Morphological Transformations**, ya que en la imagen anterior existen algunos agujeros o ruidos. Esta función es útil para cerrar pequeños agujeros dentro de los objetos en primer plano o pequeños puntos negros en el objeto. - Ahora utilizaremos la función **Morphological Transformations**, ya que en la imagen anterior existen algunos agujeros o ruidos. Esta función es útil para cerrar pequeños agujeros dentro de los objetos en primer plano o pequeños puntos negros en el objeto.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
kernel = np.ones((4,4)) kernel = np.ones((4,4))
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN, kernel, iterations = 1) opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN, kernel, iterations = 1)
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE , kernel, iterations = 1) closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE , kernel, iterations = 1)
plt.imshow(closing, 'gray') plt.imshow(closing, 'gray')
plt.show plt.show
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- Aquí utilizamos la función **cv2.dilate**, aumenta el límite del objeto al fondo, el objeto se hace más grande, de esta manera, podemos asegurarnos de que cualquier región de fondo en el resultado sea realmente un fondo, ya que se elimina la región de límite, que se encontro manualmente solamente determinando los valores de los píxeles. Este sera el primer marcador. - Aquí utilizamos la función **cv2.dilate**, aumenta el límite del objeto al fondo, el objeto se hace más grande, de esta manera, podemos asegurarnos de que cualquier región de fondo en el resultado sea realmente un fondo, ya que se elimina la región de límite, que se encontro manualmente solamente determinando los valores de los píxeles. Este sera el primer marcador.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
kernel = np.ones((1,1),np.uint8) kernel = np.ones((1,1),np.uint8)
Mark_int = cv2.dilate(closing, kernel,iterations=1) Mark_int = cv2.dilate(closing, kernel,iterations=1)
Mark_int = Mark_int.astype(np.uint8) Mark_int = Mark_int.astype(np.uint8)
plt.imshow(Mark_int, 'gray') plt.imshow(Mark_int, 'gray')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- Ahora encontraremos el segundo marcador, para eso utilizaremos la función **distanceTransform**, en esta operación, las intensidades de nivel de gris de los puntos dentro de las regiones del objeto se cambian por las distancias entre estos y del valor 0 más cercano (límite), a continuación se muestra de una manera gráfica como opera esta función, por lo que la imagen se ve de una forma muy clara en el centro y va degradándose el color a medida que se acerca al límite. - Ahora encontraremos el segundo marcador, para eso utilizaremos la función **distanceTransform**, en esta operación, las intensidades de nivel de gris de los puntos dentro de las regiones del objeto se cambian por las distancias entre estos y del valor 0 más cercano (límite), a continuación se muestra de una manera gráfica como opera esta función, por lo que la imagen se ve de una forma muy clara en el centro y va degradándose el color a medida que se acerca al límite.
<img src="imagenes/distance.png"> <img src="imagenes/distance.png">
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
dist_transform = cv2.distanceTransform(Mark_int,cv2.DIST_L2, 3) dist_transform = cv2.distanceTransform(Mark_int,cv2.DIST_L2, 3)
plt.imshow(dist_transform, 'gray') plt.imshow(dist_transform, 'gray')
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- Para encontrar el segundo marcador, utilizamos la función threshold, por lo que todos los valores de píxeles que sobrepasen el umbral se identifican como objeto y todos los que no lo sobrepasen se consideran como zonas desconocidas (no se sabe si es objeto o fondo). - Para encontrar el segundo marcador, utilizamos la función threshold, por lo que todos los valores de píxeles que sobrepasen el umbral se identifican como objeto y todos los que no lo sobrepasen se consideran como zonas desconocidas (no se sabe si es objeto o fondo).
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
dist_transform = cv2.distanceTransform(Mark_int,cv2.DIST_L2, 3) dist_transform = cv2.distanceTransform(Mark_int,cv2.DIST_L2, 3)
ret, Mark_fondo = cv2.threshold(dist_transform,0.1*dist_transform.max(),255,0) ret, Mark_fondo = cv2.threshold(dist_transform,0.1*dist_transform.max(),255,0)
plt.imshow(Mark_fondo, 'gray') plt.imshow(Mark_fondo, 'gray')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
- Calculamos la diferencia entre los dos marcadores, lo que nos dará como resultado una matriz que es cero en toda la imagen salvo la region donde el algoritmo de watershed va a definir que parte de la imagen representa fodo y que parte representa objeto (franja de algunos píxeles alrededor de los límites ). - Calculamos la diferencia entre los dos marcadores, lo que nos dará como resultado una matriz que es cero en toda la imagen salvo la region donde el algoritmo de watershed va a definir que parte de la imagen representa fodo y que parte representa objeto (franja de algunos píxeles alrededor de los límites ).
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
Mark_fondo = np.uint8(Mark_fondo) Mark_fondo = np.uint8(Mark_fondo)
desconocido = cv2.subtract(Mark_int,Mark_fondo) desconocido = cv2.subtract(Mark_int,Mark_fondo)
plt.imshow(desconocido,'gray') plt.imshow(desconocido,'gray')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Aplicación del algoritmo Watershed ### Aplicación del algoritmo Watershed
- Finalmente aplicamos la función de **watershed** que encontrará los bordes dentro de la franja en donde no estamos seguros qué parte representa fondo y cual parte representa el objeto. - Finalmente aplicamos la función de **watershed** que encontrará los bordes dentro de la franja en donde no estamos seguros qué parte representa fondo y cual parte representa el objeto.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
closing = closing.astype(np.uint8) #cambiamos el tipo de elemento, para que cooncuerde con lo que las funciones esperan closing = closing.astype(np.uint8) #cambiamos el tipo de elemento, para que cooncuerde con lo que las funciones esperan
ret, markers = cv2.connectedComponents(closing) ret, markers = cv2.connectedComponents(closing)
markers = markers+1 markers = markers+1
# Now, mark the region of unknown with zero # Now, mark the region of unknown with zero
markers[desconocido == 255] = 0 markers[desconocido == 255] = 0
markers = cv2.watershed(img, markers) markers = cv2.watershed(img, markers)
img[markers == -1] = [255,0,0] img[markers == -1] = [255,0,0]
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
plt.imshow(img) plt.imshow(img)
plt.show() plt.show()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(12,4)) fig, (ax1, ax2) = plt.subplots(1,2, figsize=(12,4))
ax1.imshow(img[200:400,200:500]) ax1.imshow(img[200:400,200:500])
ax2.imshow(img[700:900,400:650]) ax2.imshow(img[700:900,400:650])
plt.show() plt.show()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fig, ([ax1, ax2],[ax3,ax4]) = plt.subplots(2,2, figsize=(12,10)) fig, ([ax1, ax2],[ax3,ax4]) = plt.subplots(2,2, figsize=(12,10))
ax1.imshow(img[200:400,200:500]) ax1.imshow(img[200:400,200:500])
ax2.imshow(Grayscale[200:400,200:500], 'gray') ax2.imshow(Grayscale[200:400,200:500], 'gray')
ax3.imshow(img[700:900,400:650]) ax3.imshow(img[700:900,400:650])
ax4.imshow(Grayscale[700:900,400:650], 'gray') ax4.imshow(Grayscale[700:900,400:650], 'gray')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
> **Comentario:** > **Comentario:**
El algoritmo logra segmentar la imagen, de acuerdo a los píxeles con menor luminosidad, que en este caso serían los que corresponden a sombras, todos los píxeles con una luminosidad mayor los considera fondo. El algoritmo depende del umbral y del tipo de threshold que se le asigne, además del parámetro que determina la anchura de la banda donde se aplicará el algortimo Watershed (**0.1 x dist_transform.max()**), estos parámetros pueden se modificados y asi se podrán segmentar otros objetos, como rocas, auque esto puede ser una tarea muy dificil ya que las rocas tienen casi el mismo todo de gris en las imágenes que el fondo (suelo), en la siguiente sección se discutirá más a pronfundidad este hecho. El algoritmo logra segmentar la imagen, de acuerdo a los píxeles con menor luminosidad, que en este caso serían los que corresponden a sombras, todos los píxeles con una luminosidad mayor los considera fondo. El algoritmo depende del umbral y del tipo de threshold que se le asigne, además del parámetro que determina la anchura de la banda donde se aplicará el algortimo Watershed (**0.1 x dist_transform.max()**), estos parámetros pueden se modificados y asi se podrán segmentar otros objetos, como rocas, auque esto puede ser una tarea muy dificil ya que las rocas tienen casi el mismo todo de gris en las imágenes que el fondo (suelo), en la siguiente sección se discutirá más a pronfundidad este hecho.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Análisis ### Análisis
Esta sección consiste en aplicar el algoritmo diseñado para diferentes imágenes descargadas del siguiente link Esta sección consiste en aplicar el algoritmo diseñado para diferentes imágenes descargadas del siguiente link
<a href="https://mars.nasa.gov/mars2020/multimedia/raw-images/">(imágenes)</a> y con diferentes parámetros para estudiar el funcionamiento y la validez del algoritmo para segmentar diferentes objetos en la imagen, el objetivo principal es intentar segmentar e identificar rocas u otros objetos como partes del rover en las imágenes. <a href="https://mars.nasa.gov/mars2020/multimedia/raw-images/">(imágenes)</a> y con diferentes parámetros para estudiar el funcionamiento y la validez del algoritmo para segmentar diferentes objetos en la imagen, el objetivo principal es intentar segmentar e identificar rocas u otros objetos como partes del rover en las imágenes.
- Primero diseñaremos un código que permita redefinir algunos parámetros en el código para el análisis, que son los principales valores que determinan la región que se segmentará, tales como: - Primero diseñaremos un código que permita redefinir algunos parámetros en el código para el análisis, que son los principales valores que determinan la región que se segmentará, tales como:
- El umbral - El umbral
- El tipo de **threshold** que se utilizará. - El tipo de **threshold** que se utilizará.
- La distancia que es la amplitud de la banda donde se aplicará el algoritmo watershed. - La distancia que es la amplitud de la banda donde se aplicará el algoritmo watershed.
- El código anterior fue escrito en un archivo segmentacion_fun.py en forma de funciones y parámetros ajustables (umbral, tipo de threshold, y distancia de amplitud). El código es importado al notebook a continuación. - El código anterior fue escrito en un archivo segmentacion_fun.py en forma de funciones y parámetros ajustables (umbral, tipo de threshold, y distancia de amplitud). El código es importado al notebook a continuación.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import segmentacion_fun as seg import segmentacion_fun as seg
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
path = 'Data_Mars/Mars13.png' path = 'Data_Mars/Mars13.png'
seg.gra_umbral(path) seg.gra_umbral(path)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
umbral = 100 umbral = 100
seg.thresh_norm(path, umbral) seg.thresh_norm(path, umbral)
img1 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.2) img1 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.2)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
umbral = 120 umbral = 120
path = 'Data_Mars/Mars10.png' path = 'Data_Mars/Mars10.png'
seg.gra_umbral(path) seg.gra_umbral(path)
seg.thresh_norm(path, umbral) seg.thresh_norm(path, umbral)
img2 = seg.segmentar(path, seg.thresh_norm(path, umbral), 0.09) img2 = seg.segmentar(path, seg.thresh_norm(path, umbral), 0.09)
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
> **Comentario:** > **Comentario:**
Cambiando los parámetros podemos invertir la forma de segmentación, en este caso se logra identificar las zonas con mayor luminosidad, que para este caso coinciden con las rocas o zonas rocosas dentro de la imagen (zonas iluminadas). Cambiando los parámetros podemos invertir la forma de segmentación, en este caso se logra identificar las zonas con mayor luminosidad, que para este caso coinciden con las rocas o zonas rocosas dentro de la imagen (zonas iluminadas).
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
path = 'Data_Mars/Mars5.png' path = 'Data_Mars/Mars5.png'
seg.gra_umbral(path) seg.gra_umbral(path)
umbral = 100 umbral = 100
seg.thresh_norm(path, umbral) seg.thresh_norm(path, umbral)
img3 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.3) img3 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.3)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fig, ([[ax1, ax2], [ax3, ax4]]) = plt.subplots(2,2, figsize=(12,10)) fig, ([[ax1, ax2], [ax3, ax4]]) = plt.subplots(2,2, figsize=(12,10))
ax1.imshow(img1[600:,0:500], 'gray') ax1.imshow(img1[600:,0:500], 'gray')
ax1.set_title('Partes del Rover') ax1.set_title('Partes del Rover')
ax2.imshow(img3[700:1000,100:500], 'gray') ax2.imshow(img3[700:1000,100:500], 'gray')
ax2.set_title('Roca') ax2.set_title('Roca')
ax3.imshow(img[700:900,400:650], 'gray') ax3.imshow(img[700:900,400:650], 'gray')
ax3.set_title('Sombras') ax3.set_title('Sombras')
ax4.imshow(img2[350:650,140:550], 'gray') ax4.imshow(img2[350:650,140:550], 'gray')
ax4.set_title('Zona rocosa') ax4.set_title('Zona rocosa')
plt.show() plt.show()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Cráteres
path = 'Data_Mars/crateres.jpg'
seg.gra_umbral(path)
umbral = 70
img10 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.10)
plt.imshow(img10[200:300, 100:200])
plt.show()
```
%% Cell type:code id: tags:
``` python
path = 'Data_Mars/Mars1.jpeg' path = 'Data_Mars/Mars1.jpeg'
seg.gra_umbral(path) seg.gra_umbral(path)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
seg.thresh_norm(path, umbral) seg.thresh_norm(path, umbral)
umbral = 100 umbral = 100
img4 = seg.segmentar1(path, seg.thresh_norm(path, umbral), 0.4) img4 = seg.segmentar1(path, seg.thresh_norm(path, umbral), 0.4)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
seg.thresh_norm(path, umbral) seg.thresh_norm(path, umbral)
umbral = 160 umbral = 160
img5 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.40) img5 = seg.segmentar(path, seg.thresh_inv(path, umbral), 0.40)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
path = 'Data_Mars/Mars3.png' path = 'Data_Mars/Mars3.png'
seg.gra_umbral(path) seg.gra_umbral(path)
umbral = 70 umbral = 70
img6 = seg.segmentar(path, seg.thresh_norm(path, umbral), 0.10) img6 = seg.segmentar(path, seg.thresh_norm(path, umbral), 0.10)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
path = 'Data_Mars/Mars2.png' path = 'Data_Mars/Mars2.png'
seg.gra_umbral(path) seg.gra_umbral(path)
umbral = 150 umbral = 150
img7 = seg.segmentar(path, seg.thresh_norm(path, umbral), 0.30) img7 = seg.segmentar(path, seg.thresh_norm(path, umbral), 0.30)
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
fig, ([[ax1, ax2], [ax3, ax4]]) = plt.subplots(2,2, figsize=(12,10)) fig, ([[ax1, ax2], [ax3, ax4]]) = plt.subplots(2,2, figsize=(12,10))
ax1.imshow(img4[100:400,0:300], 'gray') ax1.imshow(img4[100:400,0:300], 'gray')
ax1.set_title('Rocas') ax1.set_title('Rocas')
ax2.imshow(img5[200:,300:], 'gray') ax2.imshow(img5[200:,300:], 'gray')
ax2.set_title('Huellas Rover') ax2.set_title('Huellas Rover')
ax4.imshow(img7[10:400,800:1400], 'gray') ax4.imshow(img7[10:400,800:1400], 'gray')
ax4.set_title('Horizonte') ax4.set_title('Horizonte')
ax3.imshow(img6[200:400,600:800], 'gray') ax3.imshow(img6[200:400,600:800], 'gray')
ax3.set_title('Zona rocosa') ax3.set_title('Zona rocosa')
plt.show() plt.show()
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Conclusiones ### Conclusiones
Se utilizó el algoritmo de Watershed con marcadores de la biblioteca OpenCV, para segmentar imágenes del rover Mars Perseverance de la NASA, este algoritmo se basa en la luminosidad de los píxeles para realizar la segmentación, por lo que puede identificar sombras que usualmente se producen por pequeñas elevaciones (rocas) o partes del rover, esto se realizó cambiando los diferentes parámetros dentro de los marcadores utilizados posteriormente en el algortimo de watershed de segmentación, además si se cambiaban los parámetros se podían identificar partes rocosas en el suelo de Marte, este algoritmo funciona si se escogen bien los valores modificables. Se utilizó el algoritmo de Watershed con marcadores de la biblioteca OpenCV, para segmentar imágenes del rover Mars Perseverance de la NASA, este algoritmo se basa en la luminosidad de los píxeles para realizar la segmentación, por lo que puede identificar sombras que usualmente se producen por pequeñas elevaciones (rocas) o partes del rover, esto se realizó cambiando los diferentes parámetros dentro de los marcadores utilizados posteriormente en el algortimo de watershed de segmentación, además si se cambiaban los parámetros se podían identificar partes rocosas en el suelo de Marte, este algoritmo funciona si se escogen bien los valores modificables.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment