Topic: matrice tridimensionale da una serie di byte  (Letto 259 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline sirjo

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
matrice tridimensionale da una serie di byte
« il: Aprile 27, 2018, 12:34 »
Ciao a tutti,
sono un programmatore VB.NET e quindi di Python so veramente poco, ma mi trovo a dover modificare un programma scritto in Python e non vi dico le ore che sto perdendo per studiare ed imparare.
Sono però bloccato su una cosa per generare una matrice tridimensionale.

ho una serie di byte, diciamo ad esempio:
my_bytes = b'x00x14x28x3cx50x64x78x8cxa0xb4xc8xd2'
che corrisponde (in decimale) a: 0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 210
ho anche
x = 3 (numero di colonne che dovranno risultare)
y = 4 (numero di righe che dovranno risultare)
dovrei trasformare il tutto in:
[[[  0   0   0 255]
  [ 20  20  20 255]
  [ 40  40  40 255]]

 [[ 60  60  60 255]
  [ 80  80  80 255]
  [100 100 100 255]]

 [[120 120 120 255]
  [140 140 140 255]
  [160 160 160 255]]

 [[180 180 180 255]
  [200 200 200 255]
  [210 210 210 255]]]

..... come posso fare a trasformare my_bytes nella matrice giusta ??

Praticamente i numeri 0, 20, 40, 60, eccetera sono dei pixel dove il numero rappresenta un pixel in scala di grigi, e quindi devo trasformare un singolo pixel (ad esempio il 40) in un RGBA, cioè [40 40 40 255], poi devo incolonnarli rispettando il numero di righe e colonne.

Grazie mille a chi mi può dare una mano

Sergio

Offline bebo

  • python erectus
  • ***
  • Post: 195
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:matrice tridimensionale da una serie di byte
« Risposta #1 il: Aprile 27, 2018, 20:05 »
Parli di una matrice tridimensionale ma scrivi solo due delle dimensioni.

Intanto questo dovrebbe poterti aiutare:


>>> num_righe, num_colonne = 3, 4
>>> my_bytes = np.array([0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 210])
>>> my_bytes_len = my_bytes.shape[0]
>>> my_bytes = my_bytes.reshape(my_bytes_len, 1)
>>> RGB_pixel_matrix = my_bytes * np.ones((my_bytes_len, num_colonne))
>>> RGB_pixel_matrix[:, num_colonne - 1] = 255
>>> RGB_pixel_matrix
array([[  0.,   0.,   0., 255.],
       [ 20.,  20.,  20., 255.],
       [ 40.,  40.,  40., 255.],
       [ 60.,  60.,  60., 255.],
       [ 80.,  80.,  80., 255.],
       [100., 100., 100., 255.],
       [120., 120., 120., 255.],
       [140., 140., 140., 255.],
       [160., 160., 160., 255.],
       [180., 180., 180., 255.],
       [200., 200., 200., 255.],
       [210., 210., 210., 255.]])


In teoria con un ulteriore reshape dovresti poterla sistemare come vuoi te, dovrebbe bastare un:
RGB_pixel_matrix.reshape((num_righe, num_colonne, terza_dimensione))

Offline sirjo

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
Re:matrice tridimensionale da una serie di byte
« Risposta #2 il: Aprile 27, 2018, 21:00 »
grazie mille della risposta, risolto !!!

Offline bebo

  • python erectus
  • ***
  • Post: 195
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:matrice tridimensionale da una serie di byte
« Risposta #3 il: Aprile 29, 2018, 14:14 »
Sono contento! Sarebbe carino spendere due minuti per spiegare come hai risolto, cosi' da aiutare anche futuri utenti del forum, e non solo.

Offline sirjo

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
Re:matrice tridimensionale da una serie di byte
« Risposta #4 il: Maggio 07, 2018, 08:31 »
certamente  ;)

import numpy as np

my_bytes = b'x00x14x28x3cx50x64x78x8cxa0xb4xc8xd2'

num_righe = 3
num_colonne = 4

img = np.array([], dtype=np.uint8)
for ptr in range(0, num_righe * num_colonne):
img = np.append(img, [my_bytes[ptr], my_bytes[ptr], my_bytes[ptr], 255])

img = img.reshape(num_colonne, num_righe, 4)

print(img)

Offline bebo

  • python erectus
  • ***
  • Post: 195
  • Punti reputazione: 0
    • Mostra profilo
    • bebo_sudo's personal homepage
Re:matrice tridimensionale da una serie di byte
« Risposta #5 il: Maggio 07, 2018, 11:13 »
Bene! Peccato che quello sia uno dei modi piu' inefficienti di usare numpy. Generi un array vuoto, ci appendi cose come fosse una lista, e poi ne fai il reshape. Ogni volta che usi np.append stai creando una nuova copia dell'array, scartando poi quella vecchia.

In questo caso tu sai gia' perfettamente che la dimensione della tua matrice sara' (num_colonne, num_righe, 4). Ti basta inserirci dentro gli array come ti ho mostrato nell'esempio.

import numpy as np
import timeit

num_righe, num_colonne = 3, 4
my_bytes = np.array([0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 210], dtype='i2').tobytes()
numbers_array = np.fromstring(my_bytes, dtype='<i2')


def cycle_version(numbers_array):
    img = np.array([], dtype=np.uint8)
    for ptr in range(0, num_righe * num_colonne):
        img = np.append(img, [my_bytes[ptr], my_bytes[ptr], my_bytes[ptr], 255])


def without_cycle_version(numbers_array):
    numbers_array_len = numbers_array.shape[0]
    numbers_array = numbers_array.reshape(numbers_array_len, 1)
    RGB_pixel_matrix = numbers_array * np.ones((numbers_array_len, num_colonne))
    RGB_pixel_matrix[:, num_colonne - 1] = 255


print("with for cycles:", min(timeit.repeat("cycle_version(numbers_array)",
                                            "from __main__ import cycle_version, numbers_array", number=100000)))

print("without for cycles:", min(timeit.repeat("without_cycle_version(numbers_array)",
                                               "from __main__ import without_cycle_version, numbers_array", number=100000)))


Questo produce:

with for cycles: 10.967865671999789
without for cycles: 1.0567209009996077


Come vedi, 10 volte piu' lento. Ti consiglio di evitare di usare cicli for per lavorare con oggetti numpy (perche' numpy e' codice C, con delle interfacce per essere chiamato da python, mentre i cicli for sono oggetti/entita' python; se mescoli le due cose, le "interfacce" tra python e C fanno da collo di bottiglia e non riesci a sfruttare la potenza del C sottostante).

Offline sirjo

  • python unicellularis
  • *
  • Post: 4
  • Punti reputazione: 0
    • Mostra profilo
Re:matrice tridimensionale da una serie di byte
« Risposta #6 il: Maggio 14, 2018, 07:49 »
grazie mille !!
adesso me lo studio e lo modifico