How would you count overlapping grain on rice in python? - python

Given the image provided, how would you use python to count the grains of rice. As you can see, they are overlapping.
Any help is much appreciated.
I have tried this code below, but it failed. I tried: I = cv2.imread("name_of_file.jpg")
1
from sys import argv; from PIL import Image
# Init
I = Image.open(argv[1]); W, H = I.size; A = W * H
D = [sum(c) for c in I.getdata()]
Bh = [0] * H; Ch = [0] * H
Bv = [0] * W; Cv = [0] * W
# Flood-fill
Background = 3 * 255 + 1; S = [0]
while S:
i = S.pop(); c = D[i]
if c != Background:
D[i] = Background
Bh[i / W] += c; Ch[i / W] += 1
Bv[i % W] += c; Cv[i % W] += 1
S += [(i + o) % A for o in [1, -1, W, -W] if abs(D[(i + o) % A] - c) < 10]
# Eliminate "trapped" areas
for i in xrange(H): Bh[i] /= float(max(Ch[i], 1))
for i in xrange(W): Bv[i] /= float(max(Cv[i], 1))
for i in xrange(A):
a = (Bh[i / W] + Bv[i % W]) / 2
if D[i] >= a: D[i] = Background
# Estimate grain count
Foreground = -1; avg_grain_area = 3038.38; grain_count = 0
for i in xrange(A):
if Foreground < D[i] < Background:
S = [i]; area = 0
while S:
j = S.pop() % A
if Foreground < D[j] < Background:
D[j] = Foreground; area += 1
S += [j - 1, j + 1, j - W, j + W]
grain_count += int(round(area / avg_grain_area))
# Output
print grain_count

This is a rather complicated question of image analysis. You might train a neural network to count the grains of rice but it is not so easy. You would need many pictures where you have already counted the grains of rice to train the network.

Related

Heat equation divide by zero issue

I'm writing a code that solves a heat equation implementing an implicit method. The problem is that the values between first and last layer of the matrix are NaNs. What could be the problem?
From my problem of view, the main issue might be with the 105th line, which represents the convrsion of original function to the one that includes the boundary function.
Boundary functions code:
def func(x, t):
return x*(1 - x)*np.exp(-2*t)
# boundary function for x = 0 and x = 1
def q0(t):
return t*np.exp(-t/0.1)*np.cos(t) # граничное условие при x = 0
def q1(t):
return t*np.exp(-t/0.5)*np.cos(t) # граничное уcловие при x = 1
def derivative(f, x0, step):
return (f(x0+step) - f(x0))/step
# boundary function that for t = 0
def u_x0(x):
return (-x + 1)*x
Function that solves the three-diagonal matrix equation
def solution(a, b):
n = len(a)
x = [0 for k in range(0, n)]
# forward
v = [0 for k in range(0, n)]
u = [0 for k in range(0, n)]
# first string (t = 0)
v[0] = a[0][1] / (-a[0][0])
u[0] = ( - b[0]) / (-a[0][0])
for i in range(1, n - 1):
v[i] = a[i][i+1] / ( -a[i][i] - a[i][i-1]*v[i-1] )
u[i] = ( a[i][i-1]*u[i-1] - b[i] ) / ( -a[i][i] - a[i][i-1]*v[i-1] )
# last string (t = 1)
v[n-1] = 0
u[n-1] = (a[n-1][n-2]*u[n-2] - b[n-1]) / (-a[n-1][n-1] - a[n-1][n-2]*v[n-2])
x[n-1] = u[n-1]
for i in range(n-1, 0, -1):
x[i-1] = v[i-1] * x[i] + u[i-1]
return x
Coefficent matrix values:
A = -t/h**2
B = 1 + 2*t/h**2
C = -t/h**2
Code that actually solves the matrix:
i = 1
X =[]
while i < 99:
X = solution(cool_array, f)
k = 0
while k < len(x_i):
#line-105
X[k] += 0.01*(func(x_i[k], x_i[i]) - (1 - x_i[i])*derivative(q0, x_i[i], 0.01) - (x_i[i])*derivative(q1, x_i[i], 0.01))
k+=1
a = 1
while a < 98:
w_h_t[i][a] = X[a]
a+=1
f = X
f[0] = w_h_t[i][0]
f[99] = w_h_t[i][99]
i+=1
print(w_h_t)
As far as I understand, the algorith solution(a, b) is written properly, so I guess the problem might be with the boundary functions or with the 105th line. The output I expect is at least an array of number, not NaNs.

how to get the pixel coordinate of image using python

So Question is a bit changed:
I Have this piece of code:
import re
from PIL import Image
def rgb_to_hex(rgb_color):
[r, g, b] = rgb_color
assert 0 <= r <= 255
assert 0 <= g <= 255
assert 0 <= b <= 255
r = hex(r).lstrip('0x')
g = hex(g).lstrip('0x')
b = hex(b).lstrip('0x')
r = (2 - len(r)) * '0' + r
g = (2 - len(g)) * '0' + g
b = (2 - len(b)) * '0' + b
hex_color = '#' + r + g + b
return hex_color
img = Image.open('img.png')
pix_val = list(img.getdata())
x, y = img.size
a = 0
for element in pix_val:
element = list(element)
del element[-1]
print(rgb_to_hex(element))
a += 1
if a == x:
a = 0
print("")
what this code does is it opens a image file and reads it's data & then column by column it prints the hex code of the pixel or a particular row & column
so what i want is that i also want to print the coordinate of the pixel.
for example i have this image
so i want the coordinate of the pixel whose pixel value i am printing.
Please help me
Thanks for answering in advance
You can also use fstring introduced in python 3.6 like:
from PIL import Image
img = Image.open('img.png')
pixels = img.load()
width, height = img.size
for x in range(width):
for y in range(height):
r, g, b = pixels[x, y]
# in case your image has an alpha channel
# r, g, b, a = pixels[x, y]
print(x, y, f"#{r:02x}{g:02x}{b:02x}")
which outputs:
0 0 #4777b9
0 1 #4878ba
0 2 #4a77ba
0 3 #4a75b9
0 4 #4b73b8
0 5 #4d75ba
...
Reference:
Converting a RGB color tuple to a six digit code, in Python - Stack Overflow
What’s New In Python 3.6 — Python 3.9.1 documentation
python - Getting list of pixel values from PIL - Stack Overflow
you can try this:
import re
from PIL import Image
def rgb_to_hex(rgb_color):
[r, g, b] = rgb_color
assert 0 <= r <= 255
assert 0 <= g <= 255
assert 0 <= b <= 255
r = hex(r).lstrip('0x')
g = hex(g).lstrip('0x')
b = hex(b).lstrip('0x')
r = (2 - len(r)) * '0' + r
g = (2 - len(g)) * '0' + g
b = (2 - len(b)) * '0' + b
hex_color = '#' + r + g + b
return hex_color
img = Image.open('img.png')
pix_val = list(img.getdata())
x, y = img.size
a = 0
for element in pix_val:
element = list(element)
del element[-1]
print(rgb_to_hex(element))
# this line of code here:
print(f"x:{a%x} y:{int(a/x)}")
a += 1

Subtle mistakes of one implementation of decision stump

Note: this question arises because of implementation details instead of decision stump ERM algorithm itself.
I am trying to implement the decision stump algorithm by myself and compare it with a correct implementation (both implementations are shown below).
To my understanding, my implementation is essentially the same as the correct implementation, where I do the sorting of x, D and y together but correct implementation does not sort D and y and uses curr_idx instead.
But after running the following test codes, of 10000 different test cases, I got 6213 incorrect test cases.
np.random.seed(0)
cor_count = 0
err_count = 0
for iter in range(10000):
X = np.random.randint(1, 100, size=(10, 2))
D = np.random.rand(10)
D /= np.sum(D)
y = np.random.choice([-1, 1], size=(10,))
my_res = my_decision_stump(X, D, y)
res = decision_stump(X, D, y)
if my_res == res:
cor_count += 1
else:
err_count += 1
print("Number of correct cases {}".format(cor_count))
print("Number of error cases {}".format(err_count))
My implementation and correct implementation are shown below.
def my_decision_stump(X, D, y):
Fs = np.inf
optimal_j = None
optimal_b = None
optimal_theta = None
m, d = X.shape
for j in range(d):
record = np.hstack((X[:, j].reshape(-1, 1), D.reshape(-1, 1), y.reshape(-1, 1)))
record_sorted = record[record[:, 0].argsort()]
x = record_sorted[:, 0]; D = record_sorted[:, 1]; y = record_sorted[:, 2]
x = np.hstack((x, x[-1]+1))
F_pos = np.sum(D[y == 1])
F_neg = np.sum(D[y == -1])
if F_pos < Fs or F_neg < Fs:
optimal_theta = x[0] - 1; optimal_j = j
if F_pos < F_neg:
Fs = F_pos; optimal_b = 1
else:
Fs = F_neg; optimal_b = -1
for i in range(m):
F_pos -= y[i] * D[i]
F_neg += y[i] * D[i]
if (F_pos < Fs or F_neg < Fs) and x[i] != x[i+1]:
optimal_theta = 0.5 * (x[i] + x[i+1]); optimal_j = j
if F_pos < F_neg:
Fs = F_pos; optimal_b = 1
else:
Fs = F_neg; optimal_b = -1
return (optimal_j, optimal_b, optimal_theta)
def decision_stump(X, D, y):
Fs = np.inf
optimal_j = None
optimal_b = None
optimal_theta = None
m, d = X.shape
for j in range(d):
index = np.argsort(X[:, j])
x = np.zeros(m+1)
x[:-1] = X[index, j]
x[-1] = x[-2] + 1
F_pos = np.sum(D[y == 1])
F_neg = np.sum(D[y == -1])
if F_pos < Fs or F_neg < Fs:
optimal_theta = x[0] - 1; optimal_j = j
if F_pos < F_neg:
Fs = F_pos; optimal_b = 1
else:
Fs = F_neg; optimal_b = -1
for i in range(m):
curr_idx = index[i]
F_pos -= y[curr_idx] * D[curr_idx]
F_neg += y[curr_idx] * D[curr_idx]
if (F_pos < Fs or F_neg < Fs) and x[i] != x[i+1]:
optimal_theta = 0.5 * (x[i] + x[i+1]); optimal_j = j
if F_pos < F_neg:
Fs = F_pos; optimal_b = 1
else:
Fs = F_neg; optimal_b = -1
return (optimal_j, optimal_b, optimal_theta)
I am not sure what (maybe subtle) mistake I have made.
Could anyone help me, thank you in advance.
I made a stupid mistake...
In my implementation, due to the abuse of variable name D and y, it turns out that every time D and y changes (i.e. D = record_sorted[:, 1] but in next iteration this D is used, the same with y) since I do the sorting but they SHOULD NOT.
This example shows the great hazard of abusing variable name.

convert image to rgb array using PIL and manually convert it to CMYK array

I'm trying to convert an image to cmyk array manually and reconstruct the image but i didn't get any image then i decide to separate c,m,y,k and display it but there is no proper image .so i just tried to save every data in file for verification,i can't find any error in that data.can any one tell me why this happens and what is the error that i done here.i post my entire code below.
from PIL import Image
import numpy as np
im = Image.open('idcard.jpg').convert('RGB')
np_image = np.array(im)
num_list = np_image.tolist()
print( len(num_list))
str1 =str(num_list)
print( len(str1))
f=open("idcardforgb.txt","w")
f.write(str1)
f.close()
cyan = 0
magenta = 0
yellow = 0
key = 0
cmyk_scale = 255
t=np.shape(np_image)
print (t)
i=(int)(t[0])
j=(int)(t[1])
k=(int)(t[2])
c_final=[[[0 for f in range(4)]for g in range(j)]for h in range(i)]
for z in range(i):
temp_z=z
for y in range(j):
temp_y=y
for x in range(3):
if x==0:
r = np_image[z][y][x]
if x==1:
g = np_image[z][y][x]
if x==2:
b = np_image[z][y][x]
if (r == 0) and (g == 0) and (b == 0):
cyan=0
magenta=0
yellow=0
key=cmyk_scale
c_final[temp_z][temp_y][0]=cyan
c_final[temp_z][temp_y][1]=magenta
c_final[temp_z][temp_y][2]=yellow
c_final[temp_z][temp_y][3]=key
else:
c = 1 - r / 255.
m = 1 - g / 255.
y = 1 - b / 255.
min_cmy = min(c,m,y)
c = (c - min_cmy) / (1 - min_cmy)
m = (m - min_cmy) / (1 - min_cmy)
y = (y - min_cmy) / (1 - min_cmy)
k = min_cmy
cyan =(int) (c*cmyk_scale)
magenta =(int) (m*cmyk_scale)
yellow = (int)(y*cmyk_scale)
key = (int)(k*cmyk_scale)
c_final[temp_z][temp_y][0]=cyan
c_final[temp_z][temp_y][1]=magenta
c_final[temp_z][temp_y][2]=yellow
c_final[temp_z][temp_y][3]=key
np_image1 = np.array(c_final)
t1=np.shape(np_image1)
print(t1)
cnum_list = np_image1.tolist()
print( len(cnum_list))
str1c =str(cnum_list)
print( len(str1c))
f=open("idcardcmyk.txt","w")
f.write(str1c)
f.close()
im = Image.fromarray(np_image1, mode='CMYK')
im.save('testing.jpg')
##im = Image.fromarray(im, mode="CMYK")
print("test ok")
ct = np_image1[:, :, 0]
cyan_list=ct.tolist()
str_c =str(cyan_list)
f=open("idcard_cp.txt","w")
f.write(str_c)
f.close()
print("test ok")
img= Image.fromarray(ct)
img.save('idcard_c.png')
mt = np_image1[:, :, 1]
imm= Image.fromarray(mt)
imm.save('idcard_m.png')
yt = np_image1[:, :, 2]
imm = Image.fromarray(yt)
imm.save('idcard_y.png')
kt = np_image1[:, :, 3]
imm = Image.fromarray(kt)
imm.save('idcard_k.png')

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