how to decode png with tensorflow 2.x API without using the palette contained in the png file - tensorflow2.0

png files are usually index values assosiated with a default palette. by default, index values can be read by PIL image, for example:
import tensorflow as tf
from PIL import Image
import numpy as np
path = '1.png'
image1 = Image.open(path)
print(image1.mode)
array1 = np.array(image1)
print(array1.shape)
print(set(list(array1.reshape(-1))))
the results:
P
(1024, 543)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
index can be converted to palette colors:
image2 = image1.convert('RGB')
print(image2.mode)
array2 = np.array(image2)
print(array2.shape)
print(set([tuple(x) for x in list(array2.reshape(-1, 3))]))
the results are
RGB
(1024, 543, 3)
{(0, 255, 255), (255, 255, 0), (0, 0, 255), (85, 255, 170), (170, 255, 85), (255, 0, 0), (255, 170, 0), (0, 170, 255), (0, 85, 255), (255, 85, 0), (0, 0, 170)}
the question is, by default, tensorflow 2.x API read palette colors, is there a way to read the index values?
tensor = tf.io.read_file(path)
tensor = tf.image.decode_png(tensor, channels=3)
array3 = tensor.numpy()
print(array3.shape)
print(set([tuple(x) for x in list(array3.reshape(-1, 3))]))
(1024, 543, 3)
{(0, 255, 255), (255, 255, 0), (0, 0, 255), (85, 255, 170), (170, 255, 85), (255, 0, 0), (255, 170, 0), (0, 170, 255), (0, 85, 255), (255, 85, 0), (0, 0, 170)}

my temporary solution is to remove all the palette assosiated with png files. Still looking for more efficient solutions
from PIL import Image
import numpy as np
img = Image.open('1.png')
img = np.array(img)
img = Image.fromarray(img)
img.save('2.png')

Ideal solution
A clean solution would be to re-implement a custom op to decode a PNG without palette conversion.
Currently, the palette conversion in TF for the decode_png-op is done at core level:
// convert palette to rgb(a) if needs be.
if (context->color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(context->png_ptr);
Work-around solution
(TF2.X)
As you've mentioned PIL in your sample code, you could wrap the PIL-call with tf.py_function in order to get the desired behavior, like:
def read_png(mask):
def read_fn(p):
return np.asarray(Image.open(p.numpy().decode()))
return tf.py_function(read_fn, [mask], tf.uint8)
and then read a paletted PNG-image without automatic palette application, like:
img = read_png(path)
img= img.numpy()
print(img.shape)
print(set(list(img.reshape(-1))))
Sample output
(1024, 543)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
Note: in TF1.X this works only in graph-mode, and you would have to use tf.py_func to wrap the TF around PIL-function (+ some minor changes).

Related

is it possible to pad a numpy array with a tuple?

I'm trying to pad a numpy array with a tuple (the array itself has only tuples)...all I can find is padding an array with 0s or 1s, which I can get to work, but that doesn't help me. Is it possible to pad with a tuple?
The crucial line is :
cells = np.pad(cells, pad_width=1, mode='constant', constant_values=material)
Replacing material, which is a 4-tuple, with a 0 works fine...but I really need it to be a tuple.
I get the error message:
operands could not be broadcast together with remapped shapes [original->remapped]: (4,) and requested shape (2,2)
Here is the code I am using, but using 0s and 1s instead:
import numpy as np
side_len = 3
a = [1 for x in range(9)]
a = np.array(a)
a = a.reshape(side_len,side_len)
a = np.pad(a, pad_width=1, mode='constant', constant_values=0)
The goal is instead of a list of 1s, to pass a list of tuples, and instead of a constant_values=0, to have constant_values=material, where material is an arbitrary 4-tuple.
A flat list of tuples are passed to this function (the function is not shown here), eg:
[(0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255), (0, 0, 255, 255)]
Which I convert to a numpy array using:
cells = np.array(cells, dtype='i,i,i,i').reshape(side_len,side_len)
Perhaps this is wonky, but the rest of my program just uses lists, I don't need numpy for it; but for this padding issue, I originally was manually iterating over my flat list and doing the padding, which took forever as the list grew, so I thought I'd try numpy because it might be faster.
the solution was:
import numpy as np
side_len = 3
material = (0,0,0,255)
a = [(255,0,0,255) for x in range(9)]
a = np.array(a,dtype='i,i,i,i').reshape(side_len,side_len)
_material = np.array(material,dtype='i,i,i,i')
a = np.pad(a, pad_width=1, mode='constant', constant_values=_material)
a
array([[( 0, 0, 0, 255), ( 0, 0, 0, 255), ( 0, 0, 0, 255),
( 0, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), (255, 0, 0, 255), (255, 0, 0, 255),
(255, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), (255, 0, 0, 255), (255, 0, 0, 255),
(255, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), (255, 0, 0, 255), (255, 0, 0, 255),
(255, 0, 0, 255), ( 0, 0, 0, 255)],
[( 0, 0, 0, 255), ( 0, 0, 0, 255), ( 0, 0, 0, 255),
( 0, 0, 0, 255), ( 0, 0, 0, 255)]],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4')])

Fuzzy logic controller - RuntimeError: Unable to resolve rule execution order

I am new to this concept and i have been trying to implement an fuzzy logic controller for shower. the input are the postion of knob from extreme left to extreme right and outputs are tempreture from very cold to very hot. i am encountering this Runtime error in the rules. Below is my stupid code
import numpy as np
import skfuzzy as fuzz
from skfuzzy import control as ctrl
pos = ctrl.Consequent(np.arange(0, 180, 1), 'pos')
temp = ctrl.Consequent(np.arange(0, 100, 1), 'temp')
pos['EL'] = fuzz.trimf(pos.universe, [0, 0, 45])
pos['L'] = fuzz.trimf(pos.universe, [0, 45, 90])
pos['C'] = fuzz.trimf(pos.universe, [45, 90, 135])
pos['R'] = fuzz.trimf(pos.universe, [90, 135, 180])
pos['ER'] = fuzz.trimf(pos.universe, [135, 180, 180])
temp['VC'] = fuzz.trimf(temp.universe, [0, 0, 10])
temp['C'] = fuzz.trimf(temp.universe, [0, 10, 40])
temp['W'] = fuzz.trimf(temp.universe, [10, 40, 80])
temp['H'] = fuzz.trimf(temp.universe, [40, 80, 100])
temp['VH'] = fuzz.trimf(temp.universe, [80, 100, 100])
rule1 = ctrl.Rule(pos['EL'], temp['VC'])
rule2 = ctrl.Rule(pos['L'], temp['C'])
rule3 = ctrl.Rule(pos['C'], temp['W'])
rule4 = ctrl.Rule(pos['R'], temp['H'])
rule5 = ctrl.Rule(pos['ER'], temp['VH'])
temp_ctrl = ctrl.ControlSystem([rule1, rule2, rule3, rule4, rule5])
temprature = ctrl.ControlSystemSimulation(temp_ctrl)
RuntimeError: Unable to resolve rule execution order. The most likely reason is two or more rules that depend on each other. Please check the rule graph for loops.
I think you might want this
pos = ctrl.Consequent(np.arange(0, 180, 1), 'pos')
to be this
pos = ctrl.Antecedent(np.arange(0, 180, 1), 'pos')
so your rules will read something like
if antecedent then consequent

color coding using scalar mappable in matplotlib

is a subplot I created using matplotlib. Is it possible to code the colors on the basis of a pre-defined range? I want to pass an additional parameter, voltage to the function drawLoadDuration and define a scale (using if-else construct?) that sets the color. Higher the voltage, darker the shade. Also, for some reason, the y-tick labels for the colorbar are not showing.
Any lead is most welcome...Thanks!
import matplotlib.cm
from pylab import *
import numpy as np
f, (ax1, ax2, ax3) = plt.subplots(3, sharex=True, sharey=False)
#other subplots
ax3.set_title('Load Profile')
ax3.patch.set_facecolor('silver')
ax3.grid(True)
cmap= plt.cm.bone_r
barHeight = 3
ticklist = []
def drawLoadDuration(period, starty, opacity):
ax3.broken_barh((period), (starty, barHeight), alpha=opacity, facecolors=cmap(opacity), lw=0.5, zorder=2)
ticklist.append(starty+barHeight/2.0)
return 0
drawLoadDuration([(0, 5), (13, 4), (19, 3), (23, 1)], 3, 0.5) #Fan
drawLoadDuration([(19, 1)], 9, 0.65) #Tube Light
drawLoadDuration([(19, 5)], 15, 0.35) #Bulb
drawLoadDuration([(7, 2), (16, 1)], 21, 0.28) #Charger
drawLoadDuration([(15, 0.5), (20, 1)], 27, 0.7) #Television
drawLoadDuration([(9, 1), (17, 1)], 33, 1) #Pump
drawLoadDuration([(2,4)], 39, 0.8) #Scooter
ax3.set_ylim(0, 45)
ax3.set_xlim(0, 24)
ax3.set_xlabel('Time (Hours)')
ax3.set_yticks(ticklist)
xticklist = np.linspace(0.5, 24, 48)
ax3.set_xticks(xticklist)
ax3.set_xticklabels(["{}{}m".format(int(h%12+12*(h%12==0)),
{0:"p",1:"a"}[(h%24)<12]) if ((h*10)%10)==0 \
else "" for h in xticklist], fontsize='9', rotation=90)
ax3.tick_params('x', colors=cmap(1.0), tick1On=True)
ax3.set_yticklabels(['Fan', 'Tube light', 'Bulb', 'Cellphone Charger', 'Television', 'Pump', 'Scooter'])
######################### Code Block for Colorbar
sm = matplotlib.cm.ScalarMappable(cmap=cmap) # create a scalarmappable from the colormap
sm.set_array([])
cbar = f.colorbar(sm, ticks=[-3, -2, -1, 0, 1, 2, 3], aspect=10, orientation='vertical', ax=ax3) # using scalarmappable to create colorbar
cbar.ax.text(3, 0.65, 'Power', rotation=90)
cbar.ax.set_yticklabels(['>1000', '>800', '>500', '>200', '>100', '<10']) #not working!!!
plt.show()
You may create a normalization instance, matplotlib.colors.Normalize(vmin=0, vmax=1000) as to map the voltage values to the range between 0 and 1, which will then be understood by the colormap. Inside the plotting function you would use this normalization as facecolors=cmap(norm(voltage)).
import matplotlib.cm
import matplotlib.pyplot as plt
import numpy as np
f, ax3 = plt.subplots()
ax3.set_title('Load Profile')
ax3.patch.set_facecolor('silver')
ax3.grid(True)
cmap= plt.cm.bone_r
# create normalization instance
norm = matplotlib.colors.Normalize(vmin=0, vmax=1000)
# create a scalarmappable from the colormap
sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
barHeight = 3
ticklist = []
def drawLoadDuration(period, starty, voltage):
ax3.broken_barh((period), (starty, barHeight), alpha=1,
facecolors=cmap(norm(voltage)), lw=0.5, zorder=2)
ticklist.append(starty+barHeight/2.0)
return 0
drawLoadDuration([(0, 5), (13, 4), (19, 3), (23, 1)], 3, 500) #Fan
drawLoadDuration([(19, 1)], 9, 650) #Tube Light
drawLoadDuration([(19, 5)], 15, 350) #Bulb
drawLoadDuration([(7, 2), (16, 1)], 21, 280) #Charger
drawLoadDuration([(15, 0.5), (20, 1)], 27, 700) #Television
drawLoadDuration([(9, 1), (17, 1)], 33, 1000) #Pump
drawLoadDuration([(2,4)], 39, 800) #Scooter
ax3.set_ylim(0, 45)
ax3.set_xlim(0, 24)
ax3.set_xlabel('Time (Hours)')
ax3.set_yticks(ticklist)
xticklist = np.linspace(0.5, 24, 48)
ax3.set_xticks(xticklist)
ax3.set_xticklabels(["{}{}m".format(int(h%12+12*(h%12==0)),
{0:"p",1:"a"}[(h%24)<12]) if ((h*10)%10)==0 \
else "" for h in xticklist], fontsize='9', rotation=90)
ax3.tick_params('x', colors=cmap(1.0), tick1On=True)
ax3.set_yticklabels(['Fan', 'Tube light', 'Bulb', 'Cellphone Charger', 'Television', 'Pump', 'Scooter'])
######################### Code Block for Colorbar
# using scalarmappable to create colorbar
cbar = f.colorbar(sm, ticks=[10,100,200,500,800,1000], aspect=10, orientation='vertical', ax=ax3, label='Power')
plt.show()

Sci-kit learn pipeline returns indexError: too many indices for array

I'm trying to get to grips with sci-kit learn for some simple machine learning projects but I'm coming unstuck with Pipelines and wonder what I've done wrong...
I'm trying to work through a tutorial on Kaggle
Here's my code:
import pandas as pd
train = pd.read_csv(local path to training data)
train_labels = pd.read_csv(local path to labels)
from sklearn.decomposition import PCA
from sklearn.svm import LinearSVC
from sklearn.grid_search import GridSearchCV
pca = PCA()
clf = LinearSVC()
n_components = arange(1, 39)
loss =['l1','l2']
penalty =['l1','l2']
C = arange(0, 1, .1)
whiten = [True, False]
from sklearn.pipeline import Pipeline
#set up pipeline
pipe = Pipeline(steps=[('pca', pca), ('clf', clf)])
#set up GridsearchCV
estimator = GridSearchCV(pipe, dict(pca__n_components = n_components, pca__whiten = whiten,
clf__loss = loss, clf__penalty = penalty, clf__C = C))
estimator
Returns:
GridSearchCV(cv=None,
estimator=Pipeline(steps=[('pca', PCA(copy=True, n_components=None, whiten=False)), ('clf', LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
intercept_scaling=1, loss='l2', multi_class='ovr', penalty='l2',
random_state=None, tol=0.0001, verbose=0))]),
fit_params={}, iid=True, loss_func=None, n_jobs=1,
param_grid={'clf__penalty': ['l1', 'l2'], 'clf__loss': ['l1', 'l2'], 'clf__C': array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]), 'pca__n_components': array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38]), 'pca__whiten': [True, False]},
pre_dispatch='2*n_jobs', refit=True, score_func=None, scoring=None,
verbose=0)
But when I try to train data:
estimator.fit(train, train_labels)
The error is:
428 for test_fold_idx, per_label_splits in enumerate(zip(*per_label_cvs)):
429 for label, (_, test_split) in zip(unique_labels, per_label_splits):
--> 430 label_test_folds = test_folds[y == label]
431 # the test split can be too big because we used
432 # KFold(max(c, self.n_folds), self.n_folds) instead of
IndexError: too many indices for array
Can anyone point me in the right direction?
It turns out that the Pandas dataframe is the wrong shape.
estimator.fit(train.values, train_labels[0].values)
works, although I also had to drop the penalty term.

Numpy Array Column Slicing Produces IndexError: invalid index Exception

I am using version 1.5.1 of numpy and Python 2.6.6.
I am reading a binary file into a numpy array:
>>> dt = np.dtype('<u4,<i2,<i2,<i2,<i2,<i2,<i2,<i2,<i2,u1,u1,u1,u1')
>>> file_data = np.fromfile(os.path.join(folder,f), dtype=dt)
This works just fine. Examining the result:
>>> type(file_data)
<type 'numpy.ndarray'>
>>> file_data
array([(3571121L, -54, 103, 1, 50, 48, 469, 588, -10, 0, 102, 0, 0),
(3571122L, -78, 20, 25, 45, 44, 495, 397, -211, 0, 102, 0, 0),
(3571123L, -69, -48, 23, 60, 19, 317, -26, -151, 0, 102, 0, 0), ...,
(3691138L, -53, 52, -2, -11, 76, 988, 288, -101, 1, 102, 0, 0),
(3691139L, -11, 21, -27, 25, 47, 986, 253, 176, 1, 102, 0, 0),
(3691140L, -30, -19, -63, 59, 12, 729, 23, 302, 1, 102, 0, 0)],
dtype=[('f0', '<u4'), ('f1', '<i2'), ('f2', '<i2'), ... , ('f12', '|u1')])
>>> file_data[0]
(3571121L, -54, 103, 1, 50, 48, 469, 588, -10, 0, 102, 0, 0)
>>> file_data[0][0]
3571121
>>> len(file_data)
120020
When I try to slice the first column:
>>> file_data[:,0]
I get:
IndexError: invalid index.
I have looked at simple examples and was able to do the slicing:
>>> a = np.array([(1,2,3),(4,5,6)])
>>> a[:,0]
array([1, 4])
The only difference I can see between my case and the simple example is that I am using the dtype. What I am doing wrong?
When you set the dtype like that, you are creating a Record Array. Numpy treats that like a 1D array of elements of your dtype. There's a fundamental difference between
file_data[0][0]
and
file_data[0,0]
In the first, you are asking for the first element of a 1D array and then retrieving the first element of that returned element. In the second, you are asking for the element in the first row of the first column of a 2D array. That's why you are getting the IndexError.
If you want to access an individual element using 2D notation, you can create a view and work with that. Unfortunately, AFAIK if you want to treat your object like a 2D array, all elements have to have the same dtype.