lunes, 2 de octubre de 2017

Cómo acceder a los subarrays de píxeles vecinos, en bloques 3x3, mediante ndimage del módulo scipy

En un artículo anterior se hizo mención a una manera expedita para determinar la estadística de píxeles vecinos, en bloques 3x3, mediante ndimage del módulo scipy. En este post se va a considerar dos maneras de acceder a los subarrays que permitieron determinar tales estadísticas.

Como puede observarse en la documentación de ndimage.generic_filter, el segundo parámetro es una función que puede ser invocada externamente. Desde allí se se puede acceder a los valores individuales de cada subarray e imprimirlos a un archivo de texto en disco para ser usados más adelante en el código principal. Sería la primera manera.

Sin embargo, usando el octavo argumento de ndimage.generic_filter, 'extra_arguments', es posible pasar los subarrays a una variable para ser usados dentro del código principal directamente.

Por otra parte, a diferencia del código original se usa una máscara para excluir el elemento central de cada subarray lo cual se habilita mediante el parámetro 'footprint'. El código completo es el siguiente:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import numpy as np
from scipy import ndimage
from os import path, remove

if path.exists("subarrays_file.txt"):
    remove("subarrays_file.txt")

def func(x, subarrays):
    file = open("subarrays_file.txt","a")
    file.write(str(x) + "\n")
    subarrays.append(x)
    return np.nanmean(x)

a = np.reshape(np.arange(25),(5,5))
print a

matrix = np.array(a).astype(np.float)

mask = np.ones((3, 3))
mask[1, 1] = 0

subarrays = []

result = ndimage.generic_filter(matrix, func, footprint = mask, mode='constant', cval=np.NaN, extra_arguments = (subarrays,))

print result

for subarray in subarrays:
    print subarray

file = open("subarrays_file.txt","r") 

lines = file.readlines()

values = [ [] for i in range(len(lines))]

for i, line in enumerate(lines):
    tmp = line.split(' ')
    for item in tmp:
        try:
            item = item.replace("]", " ")
            s = float(item)
            values[i].append(s)
        except ValueError:
            pass

print "Printing from text file"

for value in values:
    print value

Después de ejecutado en la Python Console de QGIS se obtiene el resultado a continuación; tal como se esperaba:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]
[[  4.           4.           5.           6.           6.66666667]
 [  5.6          6.           7.           8.           8.4       ]
 [ 10.6         11.          12.          13.          13.4       ]
 [ 15.6         16.          17.          18.          18.4       ]
 [ 17.33333333  18.          19.          20.          20.        ]]
[ nan  nan  nan  nan   1.  nan   5.   6.]
[ nan  nan  nan   0.   2.   5.   6.   7.]
[ nan  nan  nan   1.   3.   6.   7.   8.]
[ nan  nan  nan   2.   4.   7.   8.   9.]
[ nan  nan  nan   3.  nan   8.   9.  nan]
[ nan   0.   1.  nan   6.  nan  10.  11.]
[  0.   1.   2.   5.   7.  10.  11.  12.]
[  1.   2.   3.   6.   8.  11.  12.  13.]
[  2.   3.   4.   7.   9.  12.  13.  14.]
[  3.   4.  nan   8.  nan  13.  14.  nan]
[ nan   5.   6.  nan  11.  nan  15.  16.]
[  5.   6.   7.  10.  12.  15.  16.  17.]
[  6.   7.   8.  11.  13.  16.  17.  18.]
[  7.   8.   9.  12.  14.  17.  18.  19.]
[  8.   9.  nan  13.  nan  18.  19.  nan]
[ nan  10.  11.  nan  16.  nan  20.  21.]
[ 10.  11.  12.  15.  17.  20.  21.  22.]
[ 11.  12.  13.  16.  18.  21.  22.  23.]
[ 12.  13.  14.  17.  19.  22.  23.  24.]
[ 13.  14.  nan  18.  nan  23.  24.  nan]
[ nan  15.  16.  nan  21.  nan  nan  nan]
[ 15.  16.  17.  20.  22.  nan  nan  nan]
[ 16.  17.  18.  21.  23.  nan  nan  nan]
[ 17.  18.  19.  22.  24.  nan  nan  nan]
[ 18.  19.  nan  23.  nan  nan  nan  nan]
Printing from text file
[nan, nan, nan, nan, 1.0, nan, 5.0, 6.0]
[nan, nan, nan, 0.0, 2.0, 5.0, 6.0, 7.0]
[nan, nan, nan, 1.0, 3.0, 6.0, 7.0, 8.0]
[nan, nan, nan, 2.0, 4.0, 7.0, 8.0, 9.0]
[nan, nan, nan, 3.0, nan, 8.0, 9.0, nan]
[nan, 0.0, 1.0, nan, 6.0, nan, 10.0, 11.0]
[0.0, 1.0, 2.0, 5.0, 7.0, 10.0, 11.0, 12.0]
[1.0, 2.0, 3.0, 6.0, 8.0, 11.0, 12.0, 13.0]
[2.0, 3.0, 4.0, 7.0, 9.0, 12.0, 13.0, 14.0]
[3.0, 4.0, nan, 8.0, nan, 13.0, 14.0, nan]
[nan, 5.0, 6.0, nan, 11.0, nan, 15.0, 16.0]
[5.0, 6.0, 7.0, 10.0, 12.0, 15.0, 16.0, 17.0]
[6.0, 7.0, 8.0, 11.0, 13.0, 16.0, 17.0, 18.0]
[7.0, 8.0, 9.0, 12.0, 14.0, 17.0, 18.0, 19.0]
[8.0, 9.0, nan, 13.0, nan, 18.0, 19.0, nan]
[nan, 10.0, 11.0, nan, 16.0, nan, 20.0, 21.0]
[10.0, 11.0, 12.0, 15.0, 17.0, 20.0, 21.0, 22.0]
[11.0, 12.0, 13.0, 16.0, 18.0, 21.0, 22.0, 23.0]
[12.0, 13.0, 14.0, 17.0, 19.0, 22.0, 23.0, 24.0]
[13.0, 14.0, nan, 18.0, nan, 23.0, 24.0, nan]
[nan, 15.0, 16.0, nan, 21.0, nan, nan, nan]
[15.0, 16.0, 17.0, 20.0, 22.0, nan, nan, nan]
[16.0, 17.0, 18.0, 21.0, 23.0, nan, nan, nan]
[17.0, 18.0, 19.0, 22.0, 24.0, nan, nan, nan]
[18.0, 19.0, nan, 23.0, nan, nan, nan, nan]



No hay comentarios: