Seite 1 von 1

int8 array umformatieren

Verfasst: Donnerstag 21. August 2008, 14:28
von felue
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.

Verfasst: Donnerstag 21. August 2008, 14:30
von Hyperion
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!)

Verfasst: Donnerstag 21. August 2008, 15:14
von numerix
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

Verfasst: Donnerstag 21. August 2008, 16:01
von Leonidas
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.

Verfasst: Donnerstag 21. August 2008, 16:53
von felue
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]

Verfasst: Donnerstag 21. August 2008, 17:09
von numerix
Evtl. gibt es in der PIL etwas passendes:

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

Verfasst: Donnerstag 21. August 2008, 20:21
von BlackJack
Ansonsten könnte man noch 256 Listen mit je 8 Werten vorberechnen und/oder mal Psyco ausprobieren.

Verfasst: Samstag 23. August 2008, 09:38
von HerrHagen
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

Verfasst: Samstag 23. August 2008, 11:25
von Leonidas
Also Binär in Dezimal umwandeln?

Code: Alles auswählen

int(''.join(map(str, [0, 0, 0, 0, 0, 0, 1, 1])), 2)

Verfasst: Samstag 23. August 2008, 11:29
von rayo
Hi

oder so:

Code: Alles auswählen

reduce(lambda x, y: (x << 1) | y, [0, 0, 0, 0, 0, 0, 1, 1])
Gruss

Verfasst: Samstag 23. August 2008, 12:10
von numerix
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]

Verfasst: Samstag 23. August 2008, 12:55
von HerrHagen
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

Verfasst: Samstag 23. August 2008, 13:22
von numerix
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: