ValueError in NumPy: shapes not aligned - python

The code below shows error "ValueError: shapes (400,16,1) and (16,16) not aligned: 1 (dim 2) != 16 (dim 0)". How can I solve this problem? I want to create an image recognition algorithm using numpy only. Test images are 20*20 px sized. (sorry for my English, I speak Russian)
from numpy import exp, array, random, dot, squeeze, asarray
from PIL import Image
images = []
for k in range(8):
im = Image.open(f'learn\\yes\\{k + 1}.png', 'r')
a = list(im.getdata())
pixel_values = []
for i in a:
pixel_values.append((i[0] + i[1] + i[2] / 3) / 1000)
images.append(pixel_values)
im = Image.open(f'learn\\no\\{k + 1}.png', 'r')
a = list(im.getdata())
pixel_values = []
for i in a:
pixel_values.append((i[0] + i[1] + i[2] / 3) / 1000)
images.append(pixel_values)
im = Image.open(f'test\\1.png', 'r')
a = list(im.getdata())
pixel_values = []
for i in a:
pixel_values.append((i[0] + i[1] + i[2] / 3) / 1000)
print(*images, sep='\n', end='\n\n')
print(pixel_values)
# print(pixel_values3)
training_set_inputs = array([images])
training_set_outputs = array([[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]).T
random.seed(1)
print('processing...')
synaptic_weights = squeeze(asarray(3 * random.random((400, 1)) - 1))
for iteration in range(2):
print(f'starting iteration {iteration + 1}')
output = 1 / (1 + exp(-(dot(training_set_inputs, synaptic_weights))))
synaptic_weights += dot(training_set_inputs.T, (training_set_outputs - output) * output * (1 - output))
print('done!')
a = 1 / (1 + exp(-(dot(array(pixel_values), synaptic_weights))))[0]
print(a)
if a > 0.6:
print('yes')
else:
print('no')

I've solved the problem. The problem was here:
training_set_inputs = array([images])
instead of
training_set_inputs = array(images)

Related

Convert Numpy 3D array to 3 R,G,B hex-strings

I have large lists containing RGB values for pictures.
I use numpy to create patterns and/or pillow to load pictures and convert them to 3D-numpy arrays (int32). Now i want to restructure my array into hex-strings in a weird way:
Three hex-strings for R, G, B in this structure: '0000FFFF', where the first 4 characters always have to be zero, then 2 characters represent pixel n+1 and the last 2 cahracters represent pixel n.
I already have done this with a code which takes too long for larger images and i require some improvement. What i got so far:
import numpy
import numpy.matlib
#from matplotlib.colors import rgb2hex
import time
def pairwise(iterable):
"""Create a paired-list from a list."""
a = iter(iterable)
return zip(a, a)
def test(imgSize=[480,640], brightness=[255,255,255]):
#generate pattern
startPattern = time.time()
patternDescription = 'Stripe Test'
pattern = numpy.zeros((imgSize[0], imgSize[1], 3))
line = (numpy.r_[:imgSize[1]]%255)/255
colorChR = numpy.matlib.repmat(line, imgSize[0], 1)
colorChG = numpy.matlib.repmat(line, imgSize[0], 1)
colorChB = numpy.matlib.repmat(line, imgSize[0], 1)
colorChR[:, :] = 0
colorChR[:, 0:60] = 1
colorChG[:, :] = 0
colorChG[:, 0:60] = 1
colorChB[:, :] = 0
colorChB[:, 0:60] = 1
pattern[:, :, 0] = colorChR
pattern[:, :, 1] = colorChG
pattern[:, :, 2] = colorChB
stopPattern = time.time()
print('TIME: Pattern generation: ' + str(round(stopPattern-startPattern,3)) + ' s. ')
# first reshape
startReshape = time.time()
pattern[:, :, 0] = pattern[:, :, 0]*brightness[0] # red brightness multiplicator
pattern[:, :, 1] = pattern[:, :, 1]*brightness[1] # green brightness multiplicator
pattern[:, :, 2] = pattern[:, :, 2]*brightness[2] # blue brightness multiplicator
img = pattern.astype(int)
# IDEALLY I WANT TO CHANGE THE CODE ONLY FROM HERE ON
# redValues = pattern[:,:,0].astype(int)
# greenValues = pattern[:,:,1].astype(int)
# blueValues = pattern[:,:,2].astype(int)
# test = ("0000" + ("{:0>2X}" * len(redValues))).format(*tuple(redValues[::-1]))
# numpy.set_printoptions(formatter={'int':hex})
# #test = [ rgb2hex(img[i,:]) for i in range(img.shape[0]) ]
# rgb2hex = lambda r,g,b: '%02X%02X%02X' %(r,g,b)
# test = [ rgb2hex(*img[i,:]) for i in range(img.shape[0]) ]
# # img = numpy.array2string(img, formatter = {'int':lambda img: hex(img)})
imgReshape = numpy.reshape(img, (1, imgSize[0]*imgSize[1]*3)) #necessary?
redValues = imgReshape[0][0::3] #red values (0, 3, 6, ..)
greenValues = imgReshape[0][1::3] #green values (1, 4, 7, ..)
blueValues = imgReshape[0][2::3] #blue values (2, 5, 8, ..)
stopReshape = time.time()
print('TIME: Reshape into colors: ' + str(round(stopReshape-startReshape,3)) + ' s. ')
redString = ''
greenString = ''
blueString = ''
outData = dict()
startString = time.time()
for i, j in pairwise(redValues):
tempRed = "0000%02X%02X" % (int(j), int(i))
redString += tempRed
for i, j in pairwise(greenValues):
tempGreen = "0000%02X%02X" % (int(j), int(i))
greenString += tempGreen
for i, j in pairwise(blueValues):
tempBlue = "0000%02X%02X" % (int(j), int(i))
blueString += tempBlue
outData['red'] = redString
outData['green'] = greenString
outData['blue'] = blueString
stopString = time.time()
print('TIME: String formatting: ' + str(round(stopString-startString, 3)) + ' s')
print('DATATEST: First 200 red chars: ' + str(outData['red'][0:200]))
print('DATATEST: First 200 green chars: ' + str(outData['green'][0:200]))
print('DATATEST: First 200 blue chars: ' + str(outData['blue'][0:200]))
#return outData
Try to use numpy array instead:
redValues = np.random.randint(0, 255, (10, 2))
red = np.array(redValues).reshape(-1, 2)
red_channel = (red[:, 1] << 8) + red[:, 0]
redString = ''.join(map(lambda val: f'0000{val:04x}', red_channel))

Perlin noise looks streaky and not coherent

Now that my perlin generator is 'working' I created noise, to find that it is nothing like what I see on the internets...
My noise:
Notice the streaks:
What I am aiming to get (obviously with corresponding colour):
1:
Why does mine look so noisy and nasty?
Code (sorry for no stub, the Perlin noise makes up most of the program so it's important to include the full program):
from PIL import Image
from tkinter import filedialog
from random import randint, random
#Initialise width / height
width = 625
height = 625
#Import gradient picture - 200*1 image used to texture perlin noise
#R,G,B,Alpha
gradient = Image.open("image.png")
gradlist = list(gradient.getdata())
#Create new image
img = Image.new('RGBA', (width, height), color=(255, 255, 255, 255))
#Perlin noise modules --------------------------------------------------------------------------------------------------------
#Modules
from random import sample
from math import floor
p = sample([x for x in range(0, (width * height))], (width * height)) * 2
#Antialising
def fade(t):
retval = 6*(t**5) - 15*(t**4) + 10*(t**3)
return retval
#Linear interpolation
def lerp(t,a,b):
retval = a + (t * (b - a))
return retval
#Clever bitwise hash stuff - picks a unit vector from 12 possible - (1,1,0),(-1,1,0),(1,-1,0),(-1,-1,0),(1,0,1),(-1,0,1),(1,0,-1),(-1,0,-1),(0,1,1),(0,-1,1),(0,1,-1),(0,-1,-1)
def grad(hash, x, y, z):
h = hash % 15
if h < 8:
u = x
else:
u = y
if h < 4:
v = y
elif h in (12, 14):
v = x
else:
v = z
return (u if (h & 1) == 0 else -u) + (v if (h & 2) == 0 else -v)
#Perlin function
def perlin(x,y,z):
ix = int(floor(x)) & 255
iy = int(floor(y)) & 255
iz = int(floor(z)) & 255
x -= int(floor(x))
y -= int(floor(y))
z -= int(floor(z))
u = fade(x)
v = fade(y)
w = fade(z)
#Complicated hash stuff
A = p[ix] + iy
AA = p[A] + iz
AB = p[A + 1] + iz
B = p[ix + 1] + iy
BA = p[B] + iz
BB = p[B + 1] + iz
return -lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),grad(p[BA], x - 1, y, z)),lerp(u, grad(p[AB], x, y - 1, z),grad(p[BB], x - 1, y - 1, z))),lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1),grad(p[BA + 1], x - 1, y, z - 1)), lerp(u, grad(p[AB + 1], x, y - 1, z - 1),grad(p[BB + 1], x - 1, y - 1, z - 1))))
def octavePerlin(x,y,z,octaves,persistence):
total = 0
frequency = 1
amplitude = 1
maxValue = 0
for x in range(octaves):
total += perlin(x * frequency, y * frequency, z * frequency) * amplitude
maxValue += amplitude
amplitude *= persistence
frequency *= 2
return total / maxValue
z = random()
img.putdata([gradlist[int(octavePerlin((x + random() - 0.5) / 1000, (y + random() - 0.5) / 1000, z, 4, 2) * 100 + 100)] for x in range(width) for y in range(height)])
img.save(filedialog.asksaveasfilename() + ".png", "PNG")

Understanding how to create a montage of images for data visualization?

I read a reference code for creating a montage of images, and there's a few lines of code I don't quite understand.
This is the full code:
def montage(images, saveto='montage.png'):
"""Draw all images as a montage separated by 1 pixel borders.
Also saves the file to the destination specified by `saveto`.
Parameters
----------
images : numpy.ndarray
Input array to create montage of. Array should be:
batch x height x width x channels.
saveto : str
Location to save the resulting montage image.
Returns
-------
m : numpy.ndarray
Montage image.
"""
if isinstance(images, list):
images = np.array(images)
img_h = images.shape[1]
img_w = images.shape[2]
n_plots = int(np.ceil(np.sqrt(images.shape[0])))
if len(images.shape) == 4 and images.shape[3] == 3:
m = np.ones(
(images.shape[1] * n_plots + n_plots + 1,
images.shape[2] * n_plots + n_plots + 1, 3)) * 0.5
else:
m = np.ones(
(images.shape[1] * n_plots + n_plots + 1,
images.shape[2] * n_plots + n_plots + 1)) * 0.5
for i in range(n_plots):
for j in range(n_plots):
this_filter = i * n_plots + j
if this_filter < images.shape[0]:
this_img = images[this_filter]
m[1 + i + i * img_h:1 + i + (i + 1) * img_h,
1 + j + j * img_w:1 + j + (j + 1) * img_w] = this_img
plt.imsave(arr=m, fname=saveto)
return m
For the creation of m, I get the idea that the author is trying to create a scaffold of sorts to multiply the image on later, but how is the value of images.shape[1] * n_plots + n_plots + 1 calculated? Why must the ones be multiplied by 0.5?
Why can't it be images.shape[1] * n_plots only, since the shape should b sufficient for the number of images that could be included in the montage?

Numpy: Setting an array element with a sequence

I'm not sure what i did wrong with this code:
import cv2
from matplotlib import image as img
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.pyplot import axis
img = cv2.imread('popi.png', 0)
cv2.imshow('lel', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
a = np.shape(img)
iloscpixeli = a[0] * a[1]
print(iloscpixeli)
b = np.zeros((256, 1))
H = np.zeros((a[0], a[1]))
# czest = np.zeros((256, 1))
# probf = np.zeros((256, 1))
# probc = np.zeros((256, 1))
# cum = np.zeros((256, 1))
dim = np.shape(img)
wyjscie = np.zeros(dim)
H = np.zeros(dim)
print("dim", dim)
czest = np.zeros(dim)
probc = np.zeros(dim)
# print("r",czest)
probf = np.zeros(dim)
cum = np.zeros(dim)
for i in range(1, a[0]):
for j in range(1, a[1]):
wartosc = img[i, j]
czest[wartosc + 1] = (czest[wartosc + 1] + 1)
probf[wartosc + 1] = czest[wartosc + 1] / iloscpixeli
suma = 0
nobins = 255
d = np.zeros((256, 1))
d1 = np.shape(d)
d11 = d1[0]
for i in range(1, d11):
suma = suma + czest[i]
cum[i] = suma
probc[i] = cum[i] / iloscpixeli
wyjscie[i] = np.around(probc[i] * nobins)
wyjscie=wyjscie.tolist()
for i in range(1, a[0]):
for j in range(1, a[1]):
H[i, j] = wyjscie[img[i,j] + 1]
cv2.imshow('wyrownany', H)
And this line(yeah last :C) :
H[i, j] = wyjscie[img[i,j] + 1]
Gives me error ValueError: setting an array element with a sequence. Trying to repair checked about change the 'wyjscie' from array to list.. but doesnt work well.
I looking for any help. It's great when you look for code, probably I do something stupid and...but there is line czest[wartosc + 1] = (czest[wartosc + 1] + 1) and it works well...
H is a numpy-array with dtype=float as it's default. It's shape is 2d
You want to insert wyjscie[img[i,j] + 1]
wyjscie itself is a numpy-array with shape 2d
you convert wyjscie to a list, but this list will be a nested list because original dim is 2d
you index in nested list, therefore obtain a list and put this list into a cell which holds a float = putting a sequence/list into array element ERROR
(you are polish :-D)

Scikit-learn: How to run KMeans on a one-dimensional array?

I have an array of 13.876(13,876) values between 0 and 1. I would like to apply sklearn.cluster.KMeans to only this vector to find the different clusters in which the values are grouped. However, it seems KMeans works with a multidimensional array and not with one-dimensional ones. I guess there is a trick to make it work but I don't know how. I saw that KMeans.fit() accepts "X : array-like or sparse matrix, shape=(n_samples, n_features)", but it wants the n_samples to be bigger than one
I tried putting my array on a np.zeros() matrix and run KMeans, but then is putting all the non-null values on class 1 and the rest on class 0.
Can anyone help in running this algorithm on a one-dimensional array?
You have many samples of 1 feature, so you can reshape the array to (13,876, 1) using numpy's reshape:
from sklearn.cluster import KMeans
import numpy as np
x = np.random.random(13876)
km = KMeans()
km.fit(x.reshape(-1,1)) # -1 will be calculated to be 13876 here
Read about Jenks Natural Breaks. Function in Python found the link from the article:
def get_jenks_breaks(data_list, number_class):
data_list.sort()
mat1 = []
for i in range(len(data_list) + 1):
temp = []
for j in range(number_class + 1):
temp.append(0)
mat1.append(temp)
mat2 = []
for i in range(len(data_list) + 1):
temp = []
for j in range(number_class + 1):
temp.append(0)
mat2.append(temp)
for i in range(1, number_class + 1):
mat1[1][i] = 1
mat2[1][i] = 0
for j in range(2, len(data_list) + 1):
mat2[j][i] = float('inf')
v = 0.0
for l in range(2, len(data_list) + 1):
s1 = 0.0
s2 = 0.0
w = 0.0
for m in range(1, l + 1):
i3 = l - m + 1
val = float(data_list[i3 - 1])
s2 += val * val
s1 += val
w += 1
v = s2 - (s1 * s1) / w
i4 = i3 - 1
if i4 != 0:
for j in range(2, number_class + 1):
if mat2[l][j] >= (v + mat2[i4][j - 1]):
mat1[l][j] = i3
mat2[l][j] = v + mat2[i4][j - 1]
mat1[l][1] = 1
mat2[l][1] = v
k = len(data_list)
kclass = []
for i in range(number_class + 1):
kclass.append(min(data_list))
kclass[number_class] = float(data_list[len(data_list) - 1])
count_num = number_class
while count_num >= 2: # print "rank = " + str(mat1[k][count_num])
idx = int((mat1[k][count_num]) - 2)
# print "val = " + str(data_list[idx])
kclass[count_num - 1] = data_list[idx]
k = int((mat1[k][count_num] - 1))
count_num -= 1
return kclass
Use and visualization:
import numpy as np
import matplotlib.pyplot as plt
def get_jenks_breaks(...):...
x = np.random.random(30)
breaks = get_jenks_breaks(x, 5)
for line in breaks:
plt.plot([line for _ in range(len(x))], 'k--')
plt.plot(x)
plt.grid(True)
plt.show()
Result:

Categories