2017-03-24 5 views
0

Je tente de prendre des images non codées pour un projet de télédétection pour la cartographie de la végétation. Mon installation est un PiCamera v2 NoIR sur un Raspberry Pi 3, avec le filtre gel StoraroBlue Roscolux # 2007 inclus collé sur le capteur et un SenseHat pour l'enregistrement environnemental. Je peux prendre des photos PNG normales très bien, mais je n'arrive pas à comprendre comment lire les données binaires correctement, car toutes mes tentatives aboutissent à un désordre de couleurs.Comment lire des données binaires entrelacées à partir d'une caméra Raspberry Pi v2

Voici la section du script Python qui capture les images:

def picamera_logging_thread(): 
    logger.info('Started camera logging thread') 
    while time() < start_time + timeout: 
     with PiCamera() as camera: 
      # set values 
      camera.resolution = (3280, 2464) 

      # let automatic exposure settle 
      sleep(2) 
      image_name = 'image_' + str(int(time())) 

      # capture in PNG format at native resolution 
      camera.capture(os.path.join(image_dir, image_name + '.png')) 
      logger.info('Saved image ' + image_name + '.png') 

      # let automatic exposure settle 
      sleep(2) 
      image_name = 'image_' + str(int(time())) 

      # capture in unencoded RGB format 
      camera.capture(os.path.join(image_dir, image_name + '.bip'), 'rgb') 
      logger.info('Saved image ' + image_name + '.bip') 

     # delay the specified interval 
     sleep(picamera_logging_interval - 4) 
    logger.info('Stopped camera logging thread') 

start_time = time() 

# start logging threads 
Thread(target = sensehat_logging_thread).start() 
Thread(target = picamera_logging_thread).start() 

La documentation en ligne pour la capture non codés images RVB à l'aide de la bibliothèque Python picamera dit ceci:

Les données résultantes RVB est entrelacé. C'est-à-dire que les valeurs rouge, verte et bleue pour un pixel donné sont regroupées, dans cet ordre. Le premier octet des données est la valeur rouge pour le pixel à (0, 0), le second octet est la valeur verte pour le même pixel, et le troisième octet est la valeur bleue pour ce pixel. Le quatrième octet est la valeur rouge pour le pixel à (1, 0), et ainsi de suite.

Maintenant, je crois que cela veut dire les données binaires résultantes seront à la norme PIF (Band Interleaved par pixel) format, mais je ne suis pas sûr que leur libellé infère les pixels sont regroupés en lignes ou colonnes, parce qu'ils disent le deuxième pixel est à (1, 0), ce qui me fait penser que le deuxième pixel dans les données est à la rangée 2, Colonne 1 à la place de la Colonne 2 attendue, Ligne 1.

J'ai écrit un script dans R qui lit les données sous la forme d'une matrice d'entiers de 1 octet (0 - 255) et les ajoute à un RasterStack de trois objets RasterLayer, un pour chaque bande (RGB). J'ai même essayé d'ajouter un fichier .hdr et de l'ouvrir dans QGIS, mais c'est toujours du bruit rayé.

Voici le script R:

# This script parses BIP pixel data from a binary file, assuming order band first then rowwise 

# imports 
#install.packages("raster") 
library(raster) 

# define filename of binary data 
binary_filename <- "image_1490191326.bip" 

# define pixel dimensions of the data, width then height 
pixel_dimensions <- c(width = 3280, height = 2464) 

# open file connection in Binary Read mode 
data_file <- file(binary_filename, "rb") 

# get data (and upshift) 
binary_data <- 
    readBin(
    data_file, 
    what = "int", 
    size = 1, 
    n = pixel_dimensions["height"] * pixel_dimensions["width"] * 3 # hopefully the number of bytes in the file 
) + 128 # upshift data from (-128, 127) to (0, 255) by adding 128 

# close connection to file 
close(data_file) 

# create red raster layer of every 3rd byte, starting at the first one 
red <- 
    raster(
    matrix(binary_data[seq(from = 1, 
          to = length(binary_data), 
          by = 3)], nrow = pixel_dimensions["width"], ncol = pixel_dimensions["height"]), 
    ymn = pixel_dimensions["height"]/2 * -1, 
    ymx = pixel_dimensions["height"]/2, 
    xmn = pixel_dimensions["width"]/2 * -1, 
    xmx = pixel_dimensions["width"]/2 
) 
names(red) <- "red" 

# create green raster layer of every 3rd byte, starting at the second one 
green <- 
    raster(
    matrix(binary_data[seq(from = 2, 
          to = length(binary_data), 
          by = 3)], nrow = pixel_dimensions["width"], ncol = pixel_dimensions["height"]), 
    ymn = pixel_dimensions["height"]/2 * -1, 
    ymx = pixel_dimensions["height"]/2, 
    xmn = pixel_dimensions["width"]/2 * -1, 
    xmx = pixel_dimensions["width"]/2 
) 
names(green) <- "green" 

# create blue raster layer of every 3rd byte, starting at the third one 
blue <- 
    raster(
    matrix(binary_data[seq(from = 3, 
          to = length(binary_data), 
          by = 3)], nrow = pixel_dimensions["width"], ncol = pixel_dimensions["height"]), 
    ymn = pixel_dimensions["height"]/2 * -1, 
    ymx = pixel_dimensions["height"]/2, 
    xmn = pixel_dimensions["width"]/2 * -1, 
    xmx = pixel_dimensions["width"]/2 
) 
names(blue) <- "blue" 

# create raster stack of the three layers 
rgb_stack <- stack(red, green, blue) 

# plot hopefully correct raster 
plot(rgb_stack) 
plotRGB(rgb_stack) 

# remove unused large data variables from memory 
rm(red, green, blue, binary_data) 

Here is a link to a Google Drive folder with the binary data, R output, and a JPG version of the PNG image.

ce que je fais mal ici? Comment pourrais-je lire ceci et extraire des données de pixels utilisables?

+0

Pouvez-vous partager une image s'il vous plaît? –

+0

chose sûre, édité pour ajouter des images –

+0

Désolé, je veux dire l'image brute de BIP. –

Répondre

0

Aha! Je pense que je l'ai résolu. L'image est en fait rembourrée avec des pixels inutilisés sur les bords droit et inférieur (que vous pouvez voir en noir dans l'image ci-dessous), donc les dimensions publicisées de 3280x2464 sont incorrectes dans le cas d'une image brute. Les bonnes sont 3296x2464 et si vous multipliez ces nombres ensemble, puis multipliez par 3 (pour R, G & B pixels), vous obtiendrez une taille de fichier qui correspond à la vôtre.

Vous pouvez convertir le fichier RGB à un JPEG avec ImageMagick qui est installé sur la plupart des distributions Linux et est disponible pour Mac OS/Mac OS X et Windows (et Raspberry Pi):

magick -depth 8 -size 3296x2464 image.rgb result.jpg 

enter image description here

Remarque 1: Si votre nom de fichier ne se termine pas réellement par .rgb, vous pouvez le préfixer avec RGB: pour donner à ImageMagick un indice quant à sa co ntents, par ex.

magick -depth ... -size ... RGB:image.xyz ... 

Note 2: Si vous utilisez une ancienne version de ImageMagick, remplacer magick avec convert.

Note 3: Si vous voulez rogner les pixels de remplissage noir avec ImageMagick, utilisez:

convert -depth 8 -size 3296x2464 image.rgb -trim result.jpg 
+0

Merci de suggérer cela, je n'ai jamais pensé à regarder taille du fichier. En supposant un rapport d'aspect 4: 3 du capteur en pleine résolution (de la documentation), et puisque Windows me dit que le fichier a une taille de 24.364.032 octets (24.367.104 sur disque), je pense que les dimensions devraient être environ 3290x2467 de l'algèbre, mais ImageMagick donne une erreur 'magick.exe: fin de fichier inattendue 'image_1490191326.rgb': Aucun fichier ou répertoire @ erreur/rgb.c/ReadRGBImage/238.' Merci encore de m'avoir indiqué un nouveau direction! Je suis coincé là-dessus depuis un moment. –

+0

Veuillez réessayer - J'ai légèrement modifié l'un des nombres pour me débarrasser du message d'erreur. –

+0

IL A TRAVAILLÉ !!! Merci beaucoup! 'magick.exe -depth 8 -size 3296x2464 image_1490191326.rgb result.tiff' a parfaitement fonctionné –