I've been making a code for finding the dominant colors from an image.
I have a problem when I am printing the result (the result is in the form of a list with RGB triplets; [(244, 181, 28), (230, 146, 38)]).
I want the list to show the RGB-triplet with the most dominant color first but the result always gets printed out with the colors in random order.
Can anyone help me sort this list so I can have the most dominant first and second most and so on?
Here's the code I have so far:
class Cluster(object):
def __init__(self):
self.pixels = []
self.centroid = None
def addPoint(self, pixel):
self.pixels.append(pixel)
def setNewCentroid(self):
R = [colour[0] for colour in self.pixels]
G = [colour[1] for colour in self.pixels]
B = [colour[2] for colour in self.pixels]
R = sum(R) / len(R)
G = sum(G) / len(G)
B = sum(B) / len(B)
self.centroid = (R, G, B)
self.pixels = []
return self.centroid
class Kmeans(object):
def __init__(self, k=2, max_iterations=5, min_distance=2.0, size=200):
self.k = k
self.max_iterations = max_iterations
self.min_distance = min_distance
self.size = (size, size)
def run(self, image):
self.image = image
self.image.thumbnail(self.size)
self.pixels = numpy.array(image.getdata(), dtype=numpy.uint8)
self.clusters = [None for i in range(self.k)]
self.oldClusters = None
randomPixels = random.sample(self.pixels, self.k)
for idx in range(self.k):
self.clusters[idx] = Cluster()
self.clusters[idx].centroid = randomPixels[idx]
iterations = 0
while self.shouldExit(iterations) is False:
self.oldClusters = [cluster.centroid for cluster in self.clusters]
print iterations
for pixel in self.pixels:
self.assignClusters(pixel)
for cluster in self.clusters:
print len(cluster.pixels)
cluster.setNewCentroid()
iterations += 1
return [cluster.centroid for cluster in self.clusters]
def assignClusters(self, pixel):
shortest = float('Inf')
for cluster in self.clusters:
distance = self.calcDistance(cluster.centroid, pixel)
if distance < shortest:
shortest = distance
nearest = cluster
nearest.addPoint(pixel)
def calcDistance(self, a, b):
result = numpy.sqrt(sum((a - b) ** 2))
return result
def shouldExit(self, iterations):
if self.oldClusters is None:
return False
for idx in range(self.k):
dist = self.calcDistance(
numpy.array(self.clusters[idx].centroid),
numpy.array(self.oldClusters[idx])
)
if dist < self.min_distance:
return True
if iterations <= self.max_iterations:
return False
return True
Related
A = 300
Delta = 0.01
p0 = 100
ev0 = 0
dev = 0.001
dp0 = A*p0*dev
p = []
dp = []
ev = []
class Nonlinear():
def __init__(self):
self.p, self.dp, self.ev = p0, 0, ev0-dev
def __iter__(self):
return self
def __next__(self):
self.dp, self.p, self.ev = A*(self.p+self.dp)*dev, self.p + self.dp, self.ev+dev
p.append(self.p)
dp.append(self.dp)
if self.p > 1500:
raise StopIteration()
return p
for n in Nonlinear():
print(n)
The above are all the codes I use as an replacement of Excel in iteration. The results always provide me with all the iterative lists rather than the last that I need.
I wonder:
If there is a way for finding the last list in Python 3.8.
As the calculated results will be utilized to plot a figure using matplotlib, I want to get the relationship of p and ev calculated from iteration. Also it's also very important to swift the list into numpy array as well as gain the last iterative lists of p and ev including all evalues.
I use Python 3.8. If you have any ideas about solving the issue. Please let me know.
I think this does what you want:
class Nonlinear():
def __init__(self, p0 = 100, dp0 = 0, A = 300, dev = 0.001, maxval = 1500):
self.p = p0
self.dp = dp0
self.A = A
self.dev = dev
self.maxval = maxval
def __iter__(self):
while self.p + self.dp <= self.maxval:
self.p += self.dp
self.dp = self.A * (self.p + self.dp) * self.dev
yield self.p
n = Nonlinear()
print(*n)
# 100 130.0 178.0 245.8 339.88 470.068 650.1448 899.21128 1243.694608
Or
n = [_ for _ in Nonlinear()]
# [100, 130.0, 178.0, 245.8, 339.88, 470.068, 650.1448, 899.21128, 1243.694608]
You could also write as a generator:
def nonlinear(p = 100, dp = 0, A = 300, dev = 0.001, maxval = 1500):
Adev = A * dev
while(p + dp <= maxval):
p += dp
dp = Adev * (p + dp)
yield p
As a note, be careful how you define your variables. Entering them line by line as I've done above gives different answers for p than having them listed in one line the way you have.
I followed the pseudo code for k-means clustering to write this code. This code gives different answers when initialized the clusters' centroids with different values and none of those answers are correct. Can you help me please?
I tested with 15 nodes, tolerance = 0.00001 and iterations = 100000
Thanks in advance.
class kMeans:
def __init__(self, coordinates, tolerance, iter, nof):
self.grid = coordinates
self.N = coordinates.shape[0]
self.t = tolerance
self.nof = nof
self.f = None
def kMeans(self, nof):
assign = [0]*self.N
self.fac = np.empty([nof,2])
for i in range(nof):
for j in range(2):
self.fac[i,j] = self.grid[i+10,j]
for itr in range(iter):
for n in range(self.N):
distance = [0]*nof
for f in range(nof):
distance[f] = math.sqrt((self.grid[n,0]-self.fac[f,0])**2 + (self.grid[n,1]-self.fac[f,1])**2 )
assign[n] = np.argmin(distance)
for fa in range(nof):
l = []
x,y = 0,0
for asg in range(self.N):
if fa == assign[asg]:
l.append(asg)
x = np.mean(self.grid[l,0])
y = np.mean(self.grid[l,1])
if abs(x-self.fac[fa,0]) >= self.t:
self.fac[fa,0] = x
if abs(y-self.fac[fa,1]) >= self.t:
self.fac[fa,1] = y
continue
print('dist:',distance)
print('assign:',assign)
print('fac:',self.fac)
print('locate:', self.grid[l,1])
self.f = self.fac
return self.fac
'''
Let's say I have two objects Cell_i-1 and Cell_i
There are some data in each cell which are n, N, Q, alpha, S, R, and y
However, some value of the present cell Cell_i requires the value of data in the previous cell Cell_i-1, such as
alpha_i = 1 if n_i-1 <= Q_i
aplha_i = 5 if n_i-1 > Q_i
y_i = min {S_i-1 , R_i}
How can I use the value in the previous cell to compute the values of data in the present cell?
import numpy as np
import pandas as pd
import array as arr
class cell:
def __init__ (self, qmax ,n ,N , delta_t = 0.2 ,delta_l = 0.5 ):
self.qmax = qmax
self.Q = self.qmax * delta_t
self.n = n
self.N = N
self.alpha = []
self.S = []
self.R = []
self.y = []
def current (self):
x = np.minimum(self.Q , self.n)
self.S.append(x)
print(self.S)
def update (self)
As the title says I am trying to find all connected components in an image using recursive dfs.
I based the principle algorithm on the pseudo over here https://www.programiz.com/dsa/graph-dfs
What I get is a recursion depth exceedet error.
Usually I would troubleshoot this by checking the base case for the specific recursion, but I cant seem to find the issue.
Since every pixel is either zero or will be marked as visited at some point in time, I feel the recursion should terminate at some point.
Are there other ways for troubleshooting such recursion errors?
import cv2
import numpy as np
class Image:
def __init__(self, path):
self.img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
self.n, self.m = self.img.shape
self.visited = {(i, j): False for i in range(self.n)
for j in range(self.m)}
self.components = []
def threshold(self):
self.img[self.img >= 200] = 255
self.img[self.img < 200] = 0
def neighbours(self, px):
(i, j) = px
corners = [(i+x, j+y) for x in range(-1, 2) for y in range(-1, 2)
if (i+x, j+y) != (i, j)
and (0 <= i+x < self.n)
and (0 <= j+y < self.m)]
return corners
def dfs(self):
self.threshold()
component = 0
for i in range(self.n):
for j in range(self.m):
if not self.visited.get((i, j)) and self.img[i][j] == 255:
self.components.append([(i, j)])
self.explore((i, j), component)
component += 1
def explore(self, px, component):
self.visited[px] = True
self.components[component].append(px)
for neigh in self.neighbours(px):
if not self.visited.get(neigh) and self.img[neigh[0]][neigh[1]] == 255:
self.explore(neigh, component)
img = Image("dots.png")
img.dfs()
Solved
I had to set the maximum recursion depth
import sys
sys.setrecursionlimit(new_limit)
I have a python program in which I have a class called Vector and an empty list inside of that class which is being populated runtime.
Here is the init:
def __init__(self,n):
self.vector = [];
self.n = n;
for x in range(n):
self.vector.append(False);
And here is the eq:
def __eq__(self, other):
t = True
for x in range(self.n):
if self.vector[x] != other.vector[x]:
t = False;
return t
however, when I try to check if 2 objects of this type are equal, I always get true, even though I changed values inside of vector in Vector class.
Here is the code where I do the above:
vectors = []
n = tmp.size();
k = calculateCombinationCount(n,int(n/2))
for i in range(k):
for j in range(0,n-1):
if (tmp.vector[j] != tmp.vector[j+1]):
t = True
for x in vectors:
if x == tmp:
t = False;
if t:
vectors.append(tmp)
tmp.printVector();
tmp.swap(j,j+1);
I would appreciate any help that you can provide. Thank you :)
EDIT:
def swap(self,i,j):
tmp = self.vector[i]
self.vector[i] = self.vector[j]
self.vector[j] = tmp
def calculateCombinationCount(n,r):
k = factorial(n)/(factorial(int(r))*factorial(int(n-r)))
return int(k)
Right so I've updated your code to be much more pythonic (I can tell you come from another language, Java?).
from math import factorial
class Vector:
def __init__(self, size):
self.size = size
self.vector = [False] * size
def __eq__(self, other):
"""
Same if self.size == other.size
"""
assert self.size == other.size, (self.size, other.size)
return self.vector == other.vector
def print_vector(self):
print(self.vector)
def swap(self, i, j):
"""
More efficient and pythonic
"""
self.vector[i], self.vector[j] = self.vector[j], self.vector[i]
def calculate_combination_count(n, r):
"""
This is slow, I'd replace it with scipy.special.comb
https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.comb.html#scipy.special.comb
"""
return factorial(n) // (factorial(r) * factorial(n-r))
tmp = Vector(10)
vectors = []
n = tmp.size
k = calculate_combination_count(n, n // 2)
for i in range(k):
for j in range(0, n-1):
if tmp.vector[j] != tmp.vector[j + 1]:
if not any(vec == tmp for vec in vectors): # much more efficient
vectors.append(tmp)
tmp.print_vector()
tmp.swap(j, j + 1)
else: # Just to prove why it doesn't work
print('tmp.vector is all False: {}'.format(not all(tmp.vector)))
This prints out tmp.vector is all False: True repeatedly. I think this is your problem.
If you