Tensorflowjs count black pixels from image - tensorflow.js

I am reading RGB images in tensorflow.js and need to find out the number of black pixels [0,0,0] in that image? Is there any method to do this operation?

A tensor image is a 3d tensor without the transparency
Given t a tensor image, the following will return the number of black pixels
t = tf.tensor([0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 0], [2, 2, 3])
t.sum(-1).equal(tf.zeros(t.shape.slice(0, -1))).sum().print() // 2
We sum each pixel value (sum over the axis -1) and create a 2d tensor with same width and height as initial tensor. Both tensors are compared and the last tf.sum will count where the first tf.sum tensor has 0 values.

Related

Is it possible to write to OpenGL texture 4 different planes

I'm trying to write data to different planes to opengl texture, is it possible?
I tried following code
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_UNSIGNED_BYTE, (void*)&pixel);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_GREEN, GL_UNSIGNED_BYTE, (void*)&pixel);
It doesn't work as I expected, triangle is green instead of yellow, pixel value is 255.
No it is not. The missing channels are "filled" with 0.0 for red, green and blue, respectively 1.0 for the alpha channel.
See OpenGL 4.6 API Core Profile Specification - 8.4.4.4 Final Expansion to RGBA:
[...] Each group is converted to a group of 4 elements as follows: if a group does not contain an A element, then A is added and set to one for integer components or 1.0 for floating-point components. If any of R, G, or B is missing from the group, each missing element is added and assigned a value of 0 for integer components or 0.0 for floating-point components.

ValueError: setting an array element with a sequence - passing a list in a dictionary to DataGenerator

I am working on a keras multilabel problem. In order to work with big amount of data to avoid memory issues, I implemented a custom data generator.
So far I work with a csv file with IDs, Filenames and their corresponding labels (21 in total), which looks like this:
Filename label1 label2 label3 label4 ... ID
abc1.jpg 1 0 0 1 ... id-1
def2.jpg 1 0 0 1 ... id-2
ghi3.jpg 1 0 0 1 ... id-3
...
I put the the ids and the labels in dictionaries which have the following output:
partition: {'train': ['id-1','id-2','id-3',...], 'validation': ['id-7','id-14','id-21',...]}
labels: {'id-0': [1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
'id-1': [1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
'id-2': [1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
...}
All my images are converted to arrays and saved in single npy files. id-1.npy, id-2.npy...
Then I am executing my code:
import numpy as np
import keras
from keras.layers import *
from keras.models import Sequential
class DataGenerator(keras.utils.Sequence):
'Generates data for Keras'
def __init__(self, list_IDs, labels, batch_size=32, dim=(224,224), n_channels=3,
n_classes=21, shuffle=True):
'Initialization'
self.dim = dim
self.batch_size = batch_size
self.labels = labels
self.list_IDs = list_IDs
self.n_channels = n_channels
self.n_classes = n_classes
self.shuffle = shuffle
self.on_epoch_end()
def __len__(self):
'Denotes the number of batches per epoch'
return int(np.floor(len(self.list_IDs) / self.batch_size))
def __getitem__(self, index):
'Generate one batch of data'
# Generate indexes of the batch
indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]
# Find list of IDs
list_IDs_temp = [self.list_IDs[k] for k in indexes]
# Generate data
X, y = self.__data_generation(list_IDs_temp)
return X, y
def on_epoch_end(self):
'Updates indexes after each epoch'
self.indexes = np.arange(len(self.list_IDs))
if self.shuffle == True:
np.random.shuffle(self.indexes)
def __data_generation(self, list_IDs_temp):
'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)
# Initialization
X = np.empty((self.batch_size, *self.dim, self.n_channels))
y = np.empty((self.batch_size), dtype=int)
# Generate data
for i, ID in enumerate(list_IDs_temp):
# Store sample
X[i,] = np.load('Folder with npy files/' + ID + '.npy')
# Store class
y[i] = self.labels[ID]
return X, keras.utils.to_categorical(y, num_classes=self.n_classes)
# Parameters
params = {'dim': (224, 224),
'batch_size': 32,
'n_classes': 21,
'n_channels': 3,
'shuffle': True}
# Datasets
partition = partition
labels = labels
# Generators
training_generator = DataGenerator(partition['train'], labels, **params)
validation_generator = DataGenerator(partition['validation'], labels, **params)
# Design model
model = Sequential()
model.add(Conv2D(32, (3,3), input_shape=(224, 224, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
...
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dense(21))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
# Train model on dataset
model.fit_generator(generator=training_generator,
validation_data=validation_generator)
and the following Error raises:
ValueError: setting an array element with a sequence
the following part of the error seems to be crucial:
<ipython-input-58-fedc63607310> in __getitem__(self, index)
31
32 # Generate data
---> 33 X, y = self.__data_generation(list_IDs_temp)
34
35 return X, y
<ipython-input-58-fedc63607310> in __data_generation(self, list_IDs_temp)
53
54 # Store class
---> 55 y[i] = self.labels[ID]
56
57 return X, keras.utils.to_categorical(y, num_classes=self.n_classes)
as soon as i replace labels from the beginning with the following, the code gets executed:
labels = {'id-0': 0,
'id-1': 2,
'id-2': 1,
...}
I still want to pass multiple labels to the DataGenerator, therefore I chose to put a list in the dictionary, as shown in the beginning, but this gives me the ValueError. How can I anyway pass multiple values for a single ID to the DataGenerator as suggested? What do I have to adjust?
A hint or a snippet of code I appreciate a lot.
If i understand well your code here is the problem :
y = np.empty((self.batch_size), dtype=int)
You are creating an emty 1D array, but here :
y[i] = self.labels[ID]
You are filling it with a sequence :
'id-0': [1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
In order to work you need to create your label array with the shape of your batch_size and the lenght of your sequence :
y = np.empty((self.batch_size, len(sequence)), dtype=int)
EDIT
to_categorical is to encode categorical feature to be arrays like [0, 0, 0, 1], [0, 0, 1, 0], etc But you are feeding sequences, not categorical features.
By feeding sequences to your network, you don't want to one_hot encode it so replace :
return X, keras.utils.to_categorical(y, num_classes=self.n_classes)
by :
return X, y
Recommendation from last comment
The problem is that your Softmax activation will try to give the best score to the correct class, but here you give sequence array that softmax will interpret with multiple "correct class" :
For exemple : if you have 3 labels [1, 2, 3], by one_hot encoding you will have [1, 0, 0], [0, 1, 0], [0, 0, 1], there is only one "1" per encoded label array, one correct class, softmax will try to get this class score bigger as possible.
But in you case your are giving arrays with multiple "1's" :
with that : [1, 0, 1] softmax don't know to which class give the best score.
So i would recommand that, you start with your 21 labels [0,1,2,3, ..] and then you one_hot encode this array and you give it to your network.
If you really need that sequence, you have to find an other solution !
Hope i'm clear !

Loop through 2d array within a dictionary

I am looping through all values in a 2d array which is held in a dictionary with the key Band_1
{'Band_1': array([[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
...,
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0],
[0, 0, 0, ..., 0, 0, 0]], dtype=uint16)}
The code runs, but the array is 2650 x 2650 and I have 150+ dictionaries to process at each step, so it's very slow.
Note: for this example, there is only one key per dictionary, but that will not always be the case.
I have tried 3 different methods to loop through the array:
Method 1:
for key, bands in img.iteritems():
for pixel in bands:
for x in pixel:
if x != noDataVal:
x = x - dark_val
else:
x = noDataVal
Method 2:
for key, bands in img.iteritems():
for pixel in bands.flat:
if pixel != noDataVal:
pixel = pixel - dark_val
else:
pixel = noDataVal
Method 3:
img = {k:[[i-dark_val for i in line if i != noDataVal] for line in data] for k, data in img.items()}
Method 4:
for key, band in image.iteritems():
band = image[key]
band_m = np.ma.masked_array(band, mask=noDataVal)
band_m = band_m - dark_val
where:
dark_val = 75
noDataVal = 0
with timeit values over 5 loops as follows:
This is the first method: 18.446967368
This is the second method: 18.6967543083
This is the third method: 19.0136934398
This is the fourth method: 0.6860613911
Any improvement on these methods in terms of speed/efficiency?

how to create a pandas DataFrame by combining a list of column_names and a numpy array, and then adding more column(s)?

I have a list of names and a numpy array as below, respectively. How could I combine these two to make a pandas DataFrame? (My actual problem is larger than this, as I have more than 700 column names and hundred thousand inputs in the array). Your help will be so invaluable to me. Thank you.
column_names = [u'Bars', u'Burgers', u'Dry Cleaning & Laundry', u'Eyewear & Opticians', u'Local Services', u'Restaurants', u'Shopping']
values = array([[1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0]], dtype=int64)
UPDATE
Thank you very much for the quick inputs. I am sorry that I did not fully explain the final goal that I would like to achieve -- I would like to add another column score, which is a list [4, 4.5, 5, 5.5, 3], to the pandas data frame. Then I would like to extract all columns except of score as predictors to predict score in a linear regression model. I think the essential part here is how to add a new column in an efficient way? I know that I can do
data = pd.DataFrame({"Bars": Bars, "Burgers": Burgers, "Dry Clearning & Laundry": Dry Cleaning & Laundry, ..."score": score})
However, this seems very unlikely to do as I have way too many columns.
I also use dd = pd.DataFrame(values, columns=column_names), and ddd = pd.DataFrame(dd, scores).
This yields:
Out[185]:
Bars Burgers Dry Cleaning & Laundry Eyewear & Opticians Local Services \
3 0.0 0.0 0.0 0.0 0.0
5 NaN NaN NaN NaN NaN
5 NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN
Restaurants Shopping
3 1.0 0.0
5 NaN NaN
5 NaN NaN
4 NaN NaN`
Once again thank you very much!!
import pandas as pd
import numpy as np
column_names = [u'Bars', u'Burgers', u'Dry Cleaning & Laundry', u'Eyewear & Opticians', u'Local Services', u'Restaurants', u'Shopping']
values = array([[1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0]], dtype=int64)
df = pd.DataFrame(data=values, columns=column_names)
df.loc[:,'Scores'] = pd.Series(score, index=df.index)
I think I figured out. I can make scores another data frame. Then concatenate the first data frame dd = pd.DataFrame(values, columns=column_names) with the second data frame scores.
pd.concat([dd, scores], axis=1)
This can generate a new data frame.

How do I rotate values in a cvMat?

I am making a steerable derivative line filter. I want to be able to rotate it by an arbitrary angle. The desired situation will be the following:
cvMat myMat;
contains:
0, 0, 0
0, 0, 1
0, 0, 0
float angle = radians(45);
UnknownRotateMethod(myMat, angle);
myMat desired result:
0, 0, 0
0, 0, 0
0, 0, 1
(or similar due to discretization and aliasing)
Note I am using the C OpenCV API.
Edit: even though my example shows it, I would like to spell out that I want the rotation to be done on an axis point different from the (0,0). In this example I want the pivot to be at the center point of the matrix.
Solved:
cv2DRotationMatrix(pivot,angleDegrees,scale,outRotationMat);
cvWarpAffine(myMat,myMat,outRotationMat);

Resources