Restbits in Array-Spalten zufällig aufteilen

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
Erhy
User
Beiträge: 64
Registriert: Mittwoch 2. Januar 2019, 21:09

Hallo!
Als Autodidakt zweifle ich, ob der Code effizient ist.
Bin für Kommentare zum unterstehenden Code dankbar

Erhy

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt
import imageio

filReadPathImage = r'C:\Users\gle\AppData\Local\Temp\DistDepMod\DispDepMod_2019-7-3_21_14_53.bmp'
picdata = np.asarray( imageio.imread(filReadPathImage)[:,:,:3] )  #not with transparency channel
picShape = picdata.shape
factpreci = 1 / 255.0
picw = picdata * factpreci #picw in range 0...1.0
#
# some calculations
# e.g.
refcolor = picw[ 0, 0 ]
picCalc = np.zeros_like(picw[:,:,0])
for colix in range(0, 3):
	picCalc[:,:] += np.fabs( ( refcolor[colix] - picw[:,:,colix] ) )
# calculation done

# finishing of the modified image

arrInt = (np.clip( picCalc, 0.0 , 3.0) / factpreci ).astype(np.int)

picFinished = np.ma.empty_like(picdata) #so it is uint8

picModQuot, picModRema = np.divmod(arrInt, 3 )

picFinished[:,:,0] = picFinished[:,:,1] = picFinished[:,:,2] = picModQuot
#
# distribute the remainder randomly to avoid moiré
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# perhaps this can be coded in a smarter way:
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
picRandsIxsFi = np.random.randint(3, size=(picShape[0] * picShape[1]))
picRandsIxsFirst = picRandsIxsFi.reshape((picShape[0], picShape[1]))
# picRandsIxsFirst: values from 0 to 2

#pseudo random:
picRandsRotateAmount = picRandsIxsFi[-1::-1].reshape((picShape[0], picShape[1]))

twoPartsToAdd = np.array([[0,0],[1,0],[1,1]], dtype=np.uint8 )	# remainder with 0..2 is able to access the parts
rotatedIxs = np.array([[1,2],[2,0],[0,1]])			# rotation of indices 0,1,2 by 1, and by 2
			
for i in np.ndindex(picShape[0],picShape[1]):
	r = picModRema[i[0],i[1]] #remainder
	if r != 0 :
		tLow = twoPartsToAdd[r,0] # the low significant remainder
		if tLow != 0 :
			colorIx = picRandsIxsFirst[i[0],i[1]]
			picFinished[ i[0], i[1], colorIx ]	+= tLow

		tHigh = twoPartsToAdd[r,1] # the high significant remainder
		if tHigh  != 0 :
			rotAmount = picRandsRotateAmount[i[0],i[1]] // 2 #  is not really random
			rotIx = rotatedIxs[colorIx, rotAmount ]
			picFinished[ i[0], i[1], rotIx ] += tHigh
#
# now result image picFinished was built
#
plt.imshow(picFinished)
plt.show()


Erhy
User
Beiträge: 64
Registriert: Mittwoch 2. Januar 2019, 21:09

nun der Code, welcher um mehr als 800 mal schneller zum Resultat führt

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt
import imageio

filReadPathImage = r'C:\Users\gle\AppData\Local\Temp\DistDepMod\DispDepMod_2019-7-9_16_00_19.bmp'
picdata = np.asarray( imageio.imread(filReadPathImage)[:,:,:3] )  #not with transparency channel
picShape = picdata.shape
maxValPerColor = 255
picw = picdata / maxValPerColor #picw in range 0...1.0
#
# some calculations
# e.g.
refcolor = picw[ 0, 0 ]
picCalc = np.zeros_like(picw[:,:,0])
for colix in range(0, 3):
	picCalc[:,:] += np.fabs( ( refcolor[colix] - picw[:,:,colix] ) )
# calculation done

# finishing of the image with the modifications
picCalcFlat = picCalc.reshape(picShape[0] * picShape[1]) #flat array, because it is faster to work with
arrInt = (np.clip( picCalcFlat, 0.0 , 3.0) * maxValPerColor ).astype(np.int)
picFinishFlat = np.empty((picShape[0] * picShape[1], picShape[2]), dtype=np.uint8)
picModQuot, picModRema = np.divmod(arrInt, 3 )
picFinishFlat[:,0] = picFinishFlat[:,1] = picFinishFlat[:,2] = picModQuot
#picFinishFlat[:,:] = np.expand_dims(picModQuot,axis=1) # slower as above
#
# distribute the remainder randomly to avoid moiré
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# in a smarter way:
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
picRandsIxsFirst = np.random.randint(3, size=(picShape[0] * picShape[1]), dtype=np.uint8 )
# picRandsIxsFirst: values from 0 to 2
picRandsRotateAmount = picRandsIxsFirst[-1::-1] #reverse random
# picRandsRotateAmount: also values from 0 to 2
twoPartsToAdd = np.array([[0,0],[1,0],[1,1]], dtype=np.uint8 ) # remainder parts
rotatedIxs = np.array([[1,2],[2,0],[0,1]]) # rotation of indices 0,1,2 by 1 or 2
			
restToAddArr = np.bitwise_or( \
	np.left_shift( twoPartsToAdd[picModRema[:],0] , picRandsIxsFirst[:] ),
	np.left_shift( twoPartsToAdd[picModRema[:],1] ,
						rotatedIxs[ picRandsIxsFirst[:], picRandsRotateAmount[:] // 2 ] ) )
				
picFinishFlat[:,0] += (np.bitwise_and(restToAddArr,1)).astype(bool)
picFinishFlat[:,1] += (np.bitwise_and(restToAddArr,2)).astype(bool)
picFinishFlat[:,2] += (np.bitwise_and(restToAddArr,4)).astype(bool)

picFinished = picFinishFlat.reshape(picShape[0], picShape[1], picShape[2])
#
# now result image picFinished was built
#
plt.imshow(picFinished)
plt.show()
ggamauf
User
Beiträge: 2
Registriert: Freitag 12. Juli 2019, 17:25

dieser code dokumentiert bildkordinaten?
Erhy
User
Beiträge: 64
Registriert: Mittwoch 2. Januar 2019, 21:09

in dem Code wird ein Graubild, als Gleitkomma-Array, auf die Farbkomponenten rgb aufgeteilt.
Da bei der Divisionen der Grauwerte durch 3 Reste verbleiben,
werden diese Restbits random auf die 3 Kanäle aufgeteilt,
was mir anfangs Schwierigkeiten bereitet hat.
Antworten