Incorrect results when applying operations to a matrix - python

I am trying to make an image of a circle by transforming a numpy matrix to an image, but I am getting weird missing lines on the image when the input is 50 or more. How can I fix this?
The input determines the size of the matrix, an input of 50 makes a 50 by 50 matrix. I'm a beginner programmer, and this is my first time asking a question on stack overflow, so please don't be to harsh :) This is my code.
from PIL import Image
import itertools
np.set_printoptions(threshold=np.inf)
inp = int(input("Input size of matrix"))
dt = np.dtype(np.int8)
M = np.zeros((inp, inp), dtype=dt)
A = (list(itertools.product(range(0, inp), repeat=2)))
count1 = 0
for n in A:
x = (int(n[0]) / (inp - 1)) * 2
y = (int(n[1]) / (inp - 1)) * 2
if (x ** 2) + (y ** 2) - (2 * x) - (2 * y) <= -1:
M[int(x * (inp - 1)/2), int(y * (inp - 1)/2)] = 1
count1 += 1
print(M)
im = Image.fromarray(M * 255)
im.show()
print("Approximation of pi: " + str(4 * (count1 / inp ** 2))) ```

The problem is in this line: M[int(x * (inp - 1)/2), int(y * (inp - 1)/2)] = 1
Actually, this line assigns 1 twice in some indices and misses some indices because you are using int(). Use round() to get nearest integer. That will help. Change this line: M[int(x * (inp - 1)/2), int(y * (inp - 1)/2)] = 1 to this line: M[round(x * (inp - 1)/2), round(y * (inp - 1)/2)] = 1
Your code should look like this:
from PIL import Image
import itertools
np.set_printoptions(threshold=np.inf)
inp = int(input("Input size of matrix"))
dt = np.dtype(np.int8)
M = np.zeros((inp, inp), dtype=dt)
A = (list(itertools.product(range(0, inp), repeat=2)))
count1 = 0
for n in A:
x = (int(n[0]) / (inp - 1)) * 2
y = (int(n[1]) / (inp - 1)) * 2
if (x ** 2) + (y ** 2) - (2 * x) - (2 * y) <= -1:
M[round(x * (inp - 1)/2), round(y * (inp - 1)/2)] = 1
count1 += 1
print(M)
im = Image.fromarray(M * 255)
im.show()
print("Approximation of pi: " + str(4 * (count1 / inp ** 2)))
I think this is another solution that has the expected output also and it is an easy solution without any conversion of float to integer (for indices):
import itertools
import numpy as np
np.set_printoptions(threshold=np.inf)
inp = int(input("Input size of matrix"))
dt = np.dtype(np.int8)
M = np.zeros((inp, inp), dtype=dt)
A = (list(itertools.product(range(0, inp), repeat=2)))
# assign the center
cx,cy=int(inp/2), int(inp/2)
# assign the radius
rad=int(inp/2)
count1 = 0
for n in A:
# calculate distance of a point from the center
dist = np.sqrt((n[0]-cx)**2+(n[1]-cy)**2)
# Assign 1 where dist < rad.
if dist < rad:
M[n[0], n[1]] = 1
count1 += 1
print(M)
im = Image.fromarray(M * 255)
im.show()
print("Approximation of pi: " + str(4 * (count1 / inp ** 2)))

Related

Make connections with vertices

I have a function to generate the vertices of a sphere, but I don't know how I would also generate the edges/connections of the sphere. Does anyone have an idea of how I could accomplish this?
This is how I generate the sphere vertices:
def uv_sphere_vertices(position, radius, stackcount : int, sectorcount : int):
verts = []
sectorstep = 2 * math.pi / sectorcount
stackstep = math.pi / stackcount
for num in range(stackcount):
stackangle = math.pi / 2 - num * stackstep
for num2 in range(sectorcount):
sectorangle = num2 * sectorstep
x = radius * math.cos(stackangle) * math.cos(sectorangle)
y = radius * math.cos(stackangle) * math.sin(sectorangle)
z = radius * math.sin(stackangle)
verts.append([x,y,z])
return verts
This is what I currently have:
I need the connections to be the indexes of the vertices in the verts list. This is an example of what the connections need to be:
I've tried the way they did it in http://www.songho.ca/opengl/gl_sphere.html , but that didn't really work. I converted what was there to:
for num in range(stackcount):
k1 = num * (sectorcount + 1)
k2 = k1 + sectorcount + 1
for num2 in range(sectorcount):
if num != 0:
edges.append([k1,k2,k1+1])
if num != stackcount-1:
edges.append([k1+1,k2,k2+1])
k1 += 1
k2 += 1
and got this result which is extremely laggy and not at all the desired result:
I came up with a fix. It turns out, I need to add one to the range values. Here is my final code:
def uv_sphere_vertices(position, radius, stackcount : int, sectorcount : int):
verts = []
edges = []
sectorstep = 2 * math.pi / sectorcount
stackstep = math.pi / stackcount
for num in range(stackcount+1):
stackangle = math.pi / 2 - num * stackstep
for num2 in range(sectorcount+1):
sectorangle = num2 * sectorstep
x = radius * math.cos(stackangle) * math.cos(sectorangle)
y = radius * math.cos(stackangle) * math.sin(sectorangle)
z = radius * math.sin(stackangle)
verts.append([x,y,z])
for num in range(stackcount):
cstack = num * (sectorcount + 1)
nstack = cstack + sectorcount + 1
for num2 in range(sectorcount):
if num != 0:
edges.append([cstack, nstack, cstack + 1])
if num != stackcount - 1:
edges.append([cstack + 1, nstack, nstack + 1])
cstack += 1
nstack += 1
return verts,edges

How to find correlation between two images

I need to find correlation between two images, using numpy, but basic math only. I have the problem:"*
IndexError: index 5434 is out of bounds for axis 0 with size 5434*". And i have a code. Tell me what to do, pls.
img = PIL.Image.open("SR1.png").convert("L")
im = numpy.array(img)
img2 = PIL.Image.open("SR61.png").convert("L")
im2 = numpy.array(img2)
np.array(im,dtype=float)
np.array(im2,dtype=float)
import math
import cmath
def correlationCoefficient(X, Y, n) :
sum_X = 0
sum_Y = 0
sum_XY = 0
squareSum_X = 0
squareSum_Y = 0
i = 0
for i in range(n) :
sum_X = sum_X + X[i]
sum_Y = sum_Y + Y[i]
sum_XY = sum_XY + X[i] * Y[i]
squareSum_X = squareSum_X + X[i] * X[i]
squareSum_Y = squareSum_Y + Y[i] * Y[i]
i = i + 1
corr = (n * sum_XY - sum_X * sum_Y)/(cmath.sqrt((n * squareSum_X - sum_X * sum_X)* (n * squareSum_Y - sum_Y * sum_Y)))
return corr
X = im.flatten()
Y = im2.flatten()
n = len(X)
print ('{0:.6f}'.format(correlationCoefficient(X, Y, n)))
Here's a vectorized version of your function:
import numpy as np
def correlationCoefficient(X, Y):
n = X.size
sum_X = X.sum()
sum_Y = Y.sum()
sum_XY = (X*Y).sum()
squareSum_X = (X*X).sum()
squareSum_Y = (Y*Y).sum()
corr = (n * sum_XY - sum_X * sum_Y)/(np.sqrt((n * squareSum_X - sum_X * sum_X)* (n * squareSum_Y - sum_Y * sum_Y)))
return corr
It is also important to normalize your image arrays to avoid overflow:
from PIL import Image
img1 = Image.open("1.jpg").convert("L")
im1 = np.array(img1)/255
img2 = Image.open("2.jpg").convert("L")
im2 = np.array(img2)/255
print ('{0:.6f}'.format(correlationCoefficient(im1, im2)))
You can use the function corrcoef in numpy to find Peason correlation. First you need to flatten both image arrays:
np.corrcoef(im1.flatten(), im2.flatten())

The program does not print the result

Now, I am working with the following program, but I can't get the Image Moments, Centroid etc. that I need.
Code:
import cv2
import numpy
from matplotlib.pyplot import imread
from numpy import mgrid, sum
image = imread('imagemoment.png')
def moments2e(image):
assert len(image.shape) == 2 # only for grayscale images
x, y = mgrid[:image.shape[0], :image.shape[1]]
moments = {}
moments['mean_x'] = sum(x * image) / sum(image)
moments['mean_y'] = sum(y * image) / sum(image)
# raw or spatial moments
moments['m00'] = sum(image)
moments['m01'] = sum(x * image)
moments['m10'] = sum(y * image)
moments['m11'] = sum(y * x * image)
moments['m02'] = sum(x ** 2 * image)
moments['m20'] = sum(y ** 2 * image)
moments['m12'] = sum(x * y ** 2 * image)
moments['m21'] = sum(x ** 2 * y * image)
moments['m03'] = sum(x ** 3 * image)
moments['m30'] = sum(y ** 3 * image)
# central moments
moments['mu01']= sum((y-moments['mean_y'])*image) # should be 0
moments['mu10']= sum((x-moments['mean_x'])*image) # should be 0
moments['mu11'] = sum((x - moments['mean_x']) * (y - moments['mean_y']) * image)
moments['mu02'] = sum((y - moments['mean_y']) ** 2 * image) # variance
moments['mu20'] = sum((x - moments['mean_x']) ** 2 * image) # variance
moments['mu12'] = sum((x - moments['mean_x']) * (y - moments['mean_y']) ** 2 * image)
moments['mu21'] = sum((x - moments['mean_x']) ** 2 * (y - moments['mean_y']) * image)
moments['mu03'] = sum((y - moments['mean_y']) ** 3 * image)
moments['mu30'] = sum((x - moments['mean_x']) ** 3 * image)
# opencv versions
# moments['mu02'] = sum(image*(x-m01/m00)**2)
# moments['mu02'] = sum(image*(x-y)**2)
# wiki variations
# moments['mu02'] = m20 - mean_y*m10
# moments['mu20'] = m02 - mean_x*m01
# central standardized or normalized or scale invariant moments
moments['nu11'] = moments['mu11'] / sum(image) ** (2 / 2 + 1)
moments['nu12'] = moments['mu12'] / sum(image) ** (3 / 2 + 1)
moments['nu21'] = moments['mu21'] / sum(image) ** (3 / 2 + 1)
moments['nu20'] = moments['mu20'] / sum(image) ** (2 / 2 + 1)
moments['nu03'] = moments['mu03'] / sum(image) ** (3 / 2 + 1) # skewness
moments['nu30'] = moments['mu30'] / sum(image) ** (3 / 2 + 1) # skewness
return moments
Can you help me solve this problem, please?
Thank you very much.
One issue I can see at the first glance is, you have defined the function moments2e(image) but have not called it. You need to call the moments2e(image) function outside the function definition.
import cv2
import numpy
from matplotlib.pyplot import imread
from numpy import mgrid, sum
image = imread('imagemoment.png')
def moments2e(image):
assert len(image.shape) == 2 # only for grayscale images
x, y = mgrid[:image.shape[0], :image.shape[1]]
.
.
.
return moments
moments = moments2e(image)
print(moments)

HSI image is equalized incorrectly in Python

I have implemented equalization for HSI color based images. I used numpy and math modules.
Firstly, I convert RGB image into HSI using this functions:
import math
import numpy as np
def rgb2hsi_px(px):
eps = 0.00000001
r, g, b = float(px[0]) / 255, float(px[1]) / 255, float(px[2]) / 255
# Hue component
numerator = 0.5 * ((r - g) + (r - b))
denominator = math.sqrt((r - g) ** 2 + (r - b) * (g - b))
theta = math.acos(numerator / (denominator + eps))
h = theta
if b > g:
h = 2 * math.pi - h
# Saturation component
num = min(r, g, b)
den = r + g + b
if den == 0:
den = eps
s = 1 - 3 * num / den
if s == 0:
h = 0
# Intensity component
i = (r + g + b) / 3
return h, s, i
def rgb2hsi(image):
hsi_image = np.zeros_like(image).astype('float')
height, width, _ = image.shape
for x in range(height):
for y in range(width):
px = rgb2hsi_px(image[x, y])
hsi_image[x, y] = px
return np.array(hsi_image)
Then I equalize an intensity value of converted image. The equalize function was implemented using this article:
import math
import numpy as np
def equalize(img):
eps = 0.000000000001
h, w, _ = img.shape
num_of_pxs = h * w
mean = 0.0
new_img = np.array(img)
while not abs(mean - 0.5) < eps:
for i in range(h):
for j in range(w):
mean += new_img[i, j, 2]
mean /= num_of_pxs
if mean != 0.5:
theta = math.log(0.5, math.e) / math.log(mean, math.e)
for x in range(h):
for y in range(w):
px = list(new_img[x, y])
px[2] = (px[2] ** theta)
new_img[x, y] = px
return new_img
After, I convert HSI image back to RGB using the next code:
import math
import numpy as np
def hsi2rgb_px(px):
h, s, i = float(px[0]), float(px[1]), float(px[2]) * 255
if 0 <= h < 2 * math.pi / 3:
b = i * (1 - s)
r = i * (1 + (s * math.cos(h)) / math.cos(math.pi / 3 - h))
g = 3 * i - (r + b)
elif 2 * math.pi / 3 <= h < 4 * math.pi / 3:
r = i * (1 - s)
g = i * (1 + (s * math.cos(h - 2 * math.pi / 3) / math.cos(math.pi / 3 - (h - 2 * math.pi / 3))))
b = 3 * i - (r + g)
elif 4 * math.pi / 3 <= h <= 2 * math.pi:
g = i * (1 - s)
b = i * (1 + (s * math.cos(h - 4 * math.pi / 3) / math.cos(math.pi / 3 - (h - 4 * math.pi / 3))))
r = 3 * i - (g + b)
else:
raise IndexError('h is out of range: {}'.format(h))
return round(r), round(g), round(b)
def hsi2rgb(image):
rgb_image = np.zeros_like(image).astype(np.uint8)
height, width, _ = image.shape
for x in range(height):
for y in range(width):
px = hsi2rgb_px(image[x, y])
rgb_image[x, y] = px
return np.array(rgb_image)
But an equalization gives an incorrect result. The size (in megabytes) of equalized image is larger than the original one. I'm not sure if it's normal but if yes, please, let me know. And another problem is that an output image has worse quality.
Here is an original image:
And the equalized image:
Can someone help me to fix my code, or reference me to similar article/question?
[UPDATE]
Driver program to test an algorithm:
import matplotlib.image as mp_img
input_img = mp_img.imread('input.bmp')
hsi_img = rgb2hsi(input_img)
equalized_img = equalize(hsi_img)
out_img = hsi2rgb(equalized_img)
mp_img.imsave('out.bmp', out_img)

multithreaded mandelbrot set

Is it possible to change the formula of the mandelbrot set (which is f(z) = z^2 + c by default) to a different one ( f(z) = z^2 + c * e^(-z) is what i need) when using the escape time algorithm and if possible how?
I'm currently using this code by FB36
# Multi-threaded Mandelbrot Fractal (Do not run using IDLE!)
# FB - 201104306
import threading
from PIL import Image
w = 512 # image width
h = 512 # image height
image = Image.new("RGB", (w, h))
wh = w * h
maxIt = 256 # max number of iterations allowed
# drawing region (xa < xb & ya < yb)
xa = -2.0
xb = 1.0
ya = -1.5
yb = 1.5
xd = xb - xa
yd = yb - ya
numThr = 5 # number of threads to run
# lock = threading.Lock()
class ManFrThread(threading.Thread):
def __init__ (self, k):
self.k = k
threading.Thread.__init__(self)
def run(self):
# each thread only calculates its own share of pixels
for i in range(k, wh, numThr):
kx = i % w
ky = int(i / w)
a = xa + xd * kx / (w - 1.0)
b = ya + yd * ky / (h - 1.0)
x = a
y = b
for kc in range(maxIt):
x0 = x * x - y * y + a
y = 2.0 * x * y + b
x = x0
if x * x + y * y > 4:
# various color palettes can be created here
red = (kc % 8) * 32
green = (16 - kc % 16) * 16
blue = (kc % 16) * 16
# lock.acquire()
global image
image.putpixel((kx, ky), (red, green, blue))
# lock.release()
break
if __name__ == "__main__":
tArr = []
for k in range(numThr): # create all threads
tArr.append(ManFrThread(k))
for k in range(numThr): # start all threads
tArr[k].start()
for k in range(numThr): # wait until all threads finished
tArr[k].join()
image.save("MandelbrotFractal.png", "PNG")
From the code I infer that z = x + y * i and c = a + b * i. That corresponds f(z) - z ^2 + c. You want f(z) = z ^2 + c * e^(-z).
Recall that e^(-z) = e^-(x + yi) = e^(-x) * e^i(-y) = e^(-x)(cos(y) - i*sin(y)) = e^(-x)cos(y) - i (e^(-x)sin(y)). Thus you should update your lines to be the following:
x0 = x * x - y * y + a * exp(-x) * cos(y) + b * exp(-x) * sin(y);
y = 2.0 * x * y + a * exp(-x) * sin(y) - b * exp(-x) * cos(y)
x = x0
You might need to adjust maxIt if you don't get the level of feature differentiation you're after (it might take more or fewer iterations to escape now, on average) but this should be the mathematical expression you're after.
As pointed out in the comments, you might need to adjust the criterion itself and not just the maximum iterations in order to get the desired level of differentiation: changing the max doesn't help for ones that never escape.
You can try deriving a good escape condition or just try out some things and see what you get.

Categories

Resources