int8 array umformatieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
felue
User
Beiträge: 6
Registriert: Donnerstag 21. August 2008, 13:26

Hallo

Ich habe eine binäre Bilddatei (1=weisses Pixel, 0=schwarzes pixel) in einem int8 array gespeichert (jeweils 8 pixel in einem byte). Jetzt möchte ich gerne ein array erzeugen, das weiterhin das bild repräsentiert, jedoch mit 8 bit pro pixel. Dazu müsste ich aus jeweils einem byte im array 8 byte machen, in denen dann jeweils 0 oder 1 steht.

dazu habe ich eine Schleife programmiert. Die ist schweine langsam:

Code: Alles auswählen

def update(self, image, width, height):
		for i in range(height):
			for j in range(width/8):
				k = image[i,j]
				if (k/128):
					k=k%128
					self.mean[i,(j*8)] = 1 
				if (k/64):
					k=k%64
					self.mean[i,(j*8)+1] = 1
				if (k/32):
					k=k%32
					self.mean[i,(j*8)+2] = 1
				if (k/16):
					k=k%16
					self.mean[i,(j*8)+3] = 1
				if (k/8):
					k=k%8
					self.mean[i,(j*8)+4] = 1
				if (k/4):
					k=k%4
					self.mean[i,(j*8)+5] = 1
				if (k/2):
					k=k%2
					self.mean[i,(j*8)+6] = 1
				if (k/1):
					self.mean[i,(j*8)+7] = 1	
Gibt's da ne elegantere und schnellere Lösung?

Vielen Dank für eure Antworten
Felix

Edit (Leonidas): Code in Tags gesetzt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

1.) Nutze bitte Code-Tags
2.) Doppelpost ;-) (Kannst Du als Autor nen Thema löschen?)
3.) Du kannst eine dritte Schleife einbauen und die ifs damit auf eines zusammenstauchen! (Ob das insgesamt eine saubere Lösung ist, habe ich mir jetzt nicht überlegt!)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Eleganter ganz sicher, schneller weiß ich nicht (habe ich nicht getestet).

Probier doch mal (ungetestet):

Code: Alles auswählen

def update(self, image, width, height):
    for i in xrange(height):
        for j in xrange(width/8):
            a = image[i,j]
            p = 8*j            
            n = 7
            while a:                
                self.mean[i,p+n] = a & 1
                n -= 1
                a >>= 1
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hyperion hat geschrieben:2.) Doppelpost ;-) (Kannst Du als Autor nen Thema löschen?)
Ja, das geht. man kann seine Postings immer löschen, sofern kein anderer darauf schon geantwortet hat. Aber ich habe den Doppelpost jetzt selbt gelöscht, bevor da jemand auf die Idee kommt, darauf zu Antworten, so dass wir zwei Threads haben, die man in PHPbb nicht mergen kann.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
felue
User
Beiträge: 6
Registriert: Donnerstag 21. August 2008, 13:26

OK Danke

Leider ist das nicht schneller und genausowenig praktikabel wie vorher. Dann muss ich mir die Bilddatei schon von vornherein als Grauwertdatei einlesen. Habe dann halt 8 mal so viel Datenaufkommen im WLAN...

VG
[/quote]
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Evtl. gibt es in der PIL etwas passendes:

http://www.pythonware.com/products/pil/index.htm
BlackJack

Ansonsten könnte man noch 256 Listen mit je 8 Werten vorberechnen und/oder mal Psyco ausprobieren.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Die Variante mit Vorberechnen ist sicher die beste, zumal die 8bit eine Zahl darstellen die du gleich als Listenindex für dein Lock-Up-Table verwenden kannst. Hier mal schnell ne Variante:

Code: Alles auswählen

import numpy

def makeLUT(x):
	return numpy.array((128&x,64&x,32&x,16&x,8&x,4&x,2&x,1&x), dtype='b')!=0
LUT = [makeLUT(i) for i in range(256)]

x = numpy.array((0,1,2,3)) #dein Ausgangsarray
y = numpy.zeros((x.size*8))

for i, val in enumerate(x):
	y[i*8:(i*8)+8]=LUT[val]

>>> y # das Ergebnis
[ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  1.  0.  0.  0.  0
Aber mal ne andere Frage,... Ich hatte kürzlich das Problem andersrum, d.h. ich will aus z.b. [0,0,0,0,0,0,1,1] ne 3 machen. Da wirds mit dem LUT schwieriger, da ich ein ganzes Array vergleichen muss.
Fällt jemand da ne elegantere Lösung ein?

MFG HerrHagen
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Also Binär in Dezimal umwandeln?

Code: Alles auswählen

int(''.join(map(str, [0, 0, 0, 0, 0, 0, 1, 1])), 2)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

oder so:

Code: Alles auswählen

reduce(lambda x, y: (x << 1) | y, [0, 0, 0, 0, 0, 0, 1, 1])
Gruss
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Nein, es geht nicht einfach darum, Binärzahlen in Dezimalzahlen umzuwandeln, sondern ein Byte als Bitmuster gelesen in 8 Byte umzuwandeln:

Also z.B. 14710 = 100100112 => [1,0,0,1,0,0,1,1]
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Bei meiner Anschlussfrage schon...

Mir gings um eine performante Variante von Binär in Dezimal.

@Leonidas: Das war auch meine erste Idee. Is aber für ein großes Array sehr langsam.
Wenn ich mirs jetzt recht überleg, brauch man ein Numpy-Array ja auch nich stückweiße in Strings umwandeln sondern kann gleich x.tostring() machen (wobei man da nur binäre Nullen und Einsen und nicht das Zeichen 0 bzw 1 hat). Deshalb könnte es doch noch recht recht fix von statten gehen.

Die Variante von rayo hat aber auf jeden Fall höchste B-Noten verdient.

Mir is auch noch was eingefallen. Dürfte sogar recht fix gehen:

Code: Alles auswählen

>>> a=numpy.array((128,64,32,16,8,4,2,1), dtype='b')
>>> x=numpy.array((0,0,0,0,0,0,1,1), dtype='?')
>>> a[x].sum()
3
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

HerrHagen hat geschrieben:Bei meiner Anschlussfrage schon...
Oh sorry, das habe ich übersehen, dass es inzwischen gar nicht mehr um das ursprüngliche Problem ging ... :oops:
Antworten