CONNEXION
  • RetourJeux
    • Tests
    • Soluces
    • Previews
    • Sorties
    • Hit Parade
    • Les + attendus
    • Tous les Jeux
  • RetourActu
    • Culture Geek
    • Astuces
    • Réalité Virtuelle
    • Rétrogaming
    • Toutes les actus
  • RetourHigh-Tech
    • Actus JVTECH
    • Bons plans
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTECH
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch
    • Xbox Series
    • Overwatch 2
    • FUT 23
    • League of Legends
    • Genshin Impact
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • PS4
  • One
  • Switch
  • Wii U
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Etoile Abonnement RSS

Sujet : Python: lecture de fichiers binaires 12 bits

DébutPage précedente
1
Page suivantePage suivante
blue-tamere blue-tamere
MP
Niveau 12
22 juin 2017 à 12:18:26

Salut,

J'essaye de me mettre au Python et de 'traduire' ce que je faisais sur une autre langage. Je me heurte à une première difficulté: lire une vidéo sauvegardée en format binaire, encodée en 12 bits (image en noir et blanc, chaque 12 bits correspondent à l'intensité d'un pixel).

Pour le même format mais en 8 ou 16 bits c'est facile (la balise <code> a pas l'air de marcher, désolé)

if nb_bit==16:
images = np.memmap(filename_video, dtype=np.uint16, mode='r', shape=(nb_frames, height, width))
elif nb_bit==8:
images = np.memmap(filename_video, dtype=np.uint8, mode='r', shape=(nb_frames, height, width))

images=np.rollaxis(images,0,3)

(np pour numpy) Donc je lis mon fichier filename_video en indiquant que les intensités lumineuses doivent être stockées dans des unsigned int 8 ou 16 bits, en précisant que les infos doivent être placées dans une matrice d'une taille donnée (je connais la hauteur et la largeur de chaque image, ainsi que le nombre d'images dans chaque video). Ce code me donne un tableau 3D images où chaque point représente une intensité lumineuse, la première dimension correspond à la hauteur, la deuxième à la largeur, et la troisième au numéro de l'image (images[:,:,12] représente par exemple la frame 12).

Ca ça marche nickel. Maintenant si mon fichier est codé en 12 bits, comment faire quelque chose de similaire? 12 ne correspond pas à un nombre entier d'octet donc il n'y a pas de type uint12, et ça complique un peux les choses. En tout cas je ne peux pas adapter directement ce que je fais pour 8/16 bits.

Est-ce que je suis obligé de lire le fichier binaire octet par octet et me débrouiller pur faire moi-même l'algo qui va bien, où est-ce qu'il existe une alternative qui torche ça en une ou deux lignes? Je suis tout nouveau sur python, et sur la lecture de fichiers binaires, donc il y a peut-être des choses évidentes auxquelles je n'ai pas pensé.

Pour info c'est pas juste pour le plaisir d'être chiant que j'ai des fichiers 12 bits: la caméra que j'utilise à un capteur dont la résolution est 12 bits. Sauvegarder en 8 ou 16 bits est une possibilité, mais dans un cas je perds de l'information, dans l'autre je perds de la mémoire (et quand les vidéos font quelques dizaines de go ça peut devenir problématique).

Merci!

godrik godrik
MP
Niveau 22
22 juin 2017 à 19:51:24

12 bits... c'est merdique ce truc...

Il n'y a pas 50 options. Je garderais un fichier en 12 bits. Et apres quand tu lis le fichier, tu transforme ca a la volee dans le format qui t'interesse. Et soit

  • tu lis en 8 bits et tu perds de la precision
  • tu lis en 16 bits et tu perds de l'espace
  • tu garde le flux de pixel (ou whatever) en 12 bits pour ne pas perdre d'information et:
    • tu reecris ton algo pour travailler en 12 bits, mais c'est la mort a ecrire
    • tu ecris ta structure de donne tableau pourqu'elle stocke en 12 bits mais retourne un entier 16 bits quand tu l'accedes, mais le code va certainement devenir plus lent
    • tu gardes une structure 12 bits, mais tu reecris l'algo pour faire le calcul par patch, et tu decompresses juste le patch dont tu as besoin dans un tableau d'entier 16 bits

Finalement, de l'algorithmique d'image sur des donnees de 10GBs encode en 12 bits, tu es sur que tu as envie d'ecrire ca en python ? Tu veux faire quoi comme traitement ?

blue-tamere blue-tamere
MP
Niveau 12
23 juin 2017 à 02:41:39

Salut,

Merci pour les pistes! Pour l'instant je pense que je peux stocker mes données dans un tableau 16 bits. En réalité je n'ai pas forcément besoin de charger beaucoup de frames à la fois, si jamais je déborde trop sur la RAM je pourrai surement me débrouiller. Mais je garde les idées dans un coin au cas où ça pourrait devenir utile. D'ailleurs là j'essaye de codre quelque chose pour lire entièrement le fichier binaire mais c'est juste pour commencer, à terme j'aimerais rendre ça plus flexible en pouvant sélectionner un range de frames, et éventuellement en passer (par exemple ne lire qu'une frame sur trois).

Quand je parlais de mémoire je pensais surtout à la mémoire dure, ce qui est stockée. J'ai quelques très grosses vidéos (jusqu'à 64go max ... mais c'est marginal), la majorité sont de tailles beaucoup plus raisonnables (de quelques mo à quelques go), Mais vu que j'ai vraiment beaucoup de données c'est appréciable d'essayer de gagner de la place en les sauvegardant toutes en 12 bits au lieu de 16. Pour ce qui est du traitement c'est assez basique en fait, je pense. Principalement de la détection de contours par thresholding sur l'image de base, et/ou en utilisant le gradient et/ou des choses à base de transformée de Hough, transformée de Fourier, ... Je fais aussi pas mal de divisions et soustractions entre les images. Je m'en sors pas trop mal avec Matlab, mais le peu que j'ai joué avec j'ai l'impression que Python permet d'avoir des codes plus rapides, et pourrait me simplifier un peu la vie pour certaines choses au niveau de la programmation (plus de possibilités, plus flexible, etc...). Je pense que Python est assez adapté pour ce que je veux faire, peut-être que ça pourrait aller un poil plus vite en C (?) mais là ça devient un peu trop bas niveau pour moi et les gens avec qui je travaille, et pour faire du prototypage rapide c'est peut-être pas l'idéal (ce qu'on fait majoritairement)

Mon problème est que quand je code moi-même la lecture d'un fichier binaire 12 bits (dans une structure 16 bits), c'est vraiment très lent... Quand en utilisant memmap sur un fichier 16 bits je charge une vidéo 640*256 pixels, 150 frames, en 0.1 ms ; je charge 5 frames de la même vidéo mais cette fois-ci sauvegardée en 12 bits et avec mon propre code en ... plus de 10s.

Ce que je fais:
- j'ouvre le fichier binaire et stocke les données
- je lis 3 bytes par 3 bytes (3 bytes = 24 bits, donc correspondent à 24/12=2 pixels)

En code ça donne (j'espère que les noms des variables non définies sont assez explciites)


with open(filename_video, 'rb') as f:
    data=f.read()
images=np.zeros(int(2*len(data)/3),dtype=np.uint16)
ii=0
for jj in range(0,int(len(data))-2,3):
    a=bitstring.Bits(bytes=data[jj:jj+3],length=24) #3 bytes
    images[ii],images[ii+1] = a.unpack('uint:12,uint:12')
    ii=ii+2
images = np.reshape(images,(nb_frames,height,width))

Encore une fois je m'y connais pas trop en Python ni en lecture de fichiers binaires, ni en algorithmique de manière générale d'ailleurs, mais vu que ça donne quelque chose de 10^6 fois moins rapide que ce à quoi je pourrais m'attendre je pense que ça peut être un poil optimisé. Par contre je ne vois pas trop comment.... (si ça peut aider je peux fournir un exemple de fichier vidéo)

godrik godrik
MP
Niveau 22
23 juin 2017 à 04:52:29

Si tu es encore en phase de prototypage, python est pas mal en effet. Mais je n'ecrirais pas ces algos la en python. Mais avec un peu de chance, il y a des implem opensource en C avec des bindings python.

Mon problème est que quand je code moi-même la lecture d'un fichier binaire 12 bits (dans une structure 16 bits), c'est vraiment très lent... Quand en utilisant memmap sur un fichier 16 bits je charge une vidéo 640*256 pixels, 150 frames, en 0.1 ms ; je charge 5 frames de la même vidéo mais cette fois-ci sauvegardée en 12 bits et avec mon propre code en ... plus de 10s.

bah c'est la magie de python ca... L'annee derniere, j'ai reecrit un code python tout con (50 lignes) en C. J'ai gagner un facteur 10,000

Tu as mesure le temps plus precisement pour voir si c'est la boucle jj qui prend du temps ?

J'ai aucune idee de ce que ca fait la classe bitstring. Mais ca peut etre couter en fonction de comment c'est implementer. Perso, je regarderais a coup d'operateur de shift.

Je peux regarder plus en details si tu ne t'en sors pas. Ca doit meme etre relativement simple d'ecrire un module C qui fait ca bien, si c'est utile.

blue-tamere blue-tamere
MP
Niveau 12
23 juin 2017 à 12:16:33

Ok, je vais quand même essayer encore un peu de bidouiller avec Python et je repasserai pour dire où ça en est. Merci! Si c'est pas très concluant et qu'utiliser un petit programme C appelable depuis Python peut rendre les choses beaucoup plus rapides assez simplement j'explorerai cette piste aussi. Quand je parle de prototypage je pense à l'image processing en lui-même. Là j'essaye de coder la fonction qui sera appelée au début de chaque programme, donc c'est assez légitime de se prendre un peu plus la tête dessus.

C'est bien la boucle jj qui prend >99% du temps d'exécution. D'ailleurs en modifiant le code ci-dessus pour faire une boucle jj deux fois plus courte mais en lisant plus de bytes d'un coup avec (6 bytes=4 pixels au lieu de 3), le code est significativement plus rapide. Enfin "siginficativement": je gagne un facteur 1.5 alors que je voudrais parler en puissances de 10, mais c'est déjà ça. Donc il y a en effet des chances que ce soit le bitstring qui soit le bottleneck si l'appeler prend un temps significatif. J'ai pas encore regardé les alternatives, mais je prends note du mot clef bitshift operator, je vais regarder comment ça marche.
(en réalité je ne sais pas trop ce que bitstring faitt non plus, j'ai trouvé ça dans un code quelconque sur internet en cherchant comment lire des fichiers binaires).

godrik godrik
MP
Niveau 22
23 juin 2017 à 17:08:38

Ah oui. Ca ressemble au probleme classique du for range en python;
for jj in range(0,int(len(data))-2,3):
C'est la merde ca. Il ne faut pas utiliser de forrange en python si tu veux de la performance. Parceque ca cree un tableau de de longeur int(len(data))/3 et ca fait iterer la dessus. Du cou, tu as une allocation memoire en plus, et l'iteration devien impredictible par le compilateur/interpreteur. C'est pour ca que tu gagne en perf en deroullant la boucle, ca permet au compilateur/interpreteur de voirplus decode et d'optimiser un peu mieux. Change en boucle while. Et tu gagnera de la performance.

Oui, c'est de la merde python...

DébutPage précedente
1
Page suivantePage suivante
Répondre
Prévisu
?
Victime de harcèlement en ligne : comment réagir ?
Infos 0 connecté(s)

Gestion du forum

Modérateurs : godrik, LGV
Contacter les modérateurs - Règles du forum

Sujets à ne pas manquer

La vidéo du moment