How do I change each pixel - python

I am new to Python and I still don't know what exactly Qimage's pixel returns (it seems to a tupel of rgb or rgba -the lack of type declaration doesn't help)
I want to grab each each pixel and change it.
newqim = QImage(imWidth, imHeight, QImage.Format_ARGB32)
for xstep in range(0, imWidth - 1):
for ystep in range(0, imHeight - 1):
pixelValueTuple = im.getpixel((xstep, ystep))
pixelR = pixelValueTuple[0]
pixelG = pixelValueTuple[1]
pixelB = pixelValueTuple[2]
copiedValue = qRgb(pixelR, pixelG, pixelB)
newqim.setPixel(xstep, ystep, copiedValue)
Above is the provided code ,I thought I then iterate over that newqim, but I can't get a handle on how exactly I would do that in Python.
for xstep in range(0, imWidth-1):
for ystep in range(0, imHeight -1):

I'm not sure I understood what you want, but since you are new to Python, here go a few tips...
Unpacking
This code:
pixelR = pixelR[0]
pixelG = pixelValueTuple[1]
pixelB = pixelValueTuple[2]
Is the same as:
pixelR, pixelG, pixelB = pixelValueTuple[:3]
If you are sure len(pixelValueTuple) == 3, then it is just:
pixelR, pixelG, pixelB = pixelValueTuple
PEP-8
A bit of nitpick, but python guys tend to be a little nazy about syntax. Please read PEP-8. From now on I'm naming variables according to it (camelCase for instance variables just hurt my eyes %-).
Range
You probably want range(width) instead of range(0, width-1).
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(0, 10 - 1)
[0, 1, 2, 3, 4, 5, 6, 7, 8]
Now back to your problem.
width, height = 300, 300
im = QImage(width, height, QImage.Format_ARGB32)
for x in range(im.width()):
for y in range(im.height()):
r, g, b, a = QColor(im.pixel(x ,y)).getRgb()
# ... do something to r, g, b, a ...
im.setPixel(x, y, QColor(r, g, b, a).rgb())
Example
width, height = 100, 100
im = QImage(width, height, QImage.Format_ARGB32)
for x in range(im.width()):
for y in range(im.height()):
im.setPixel(x, y, QColor(255, x * 2.56, y * 2.56, 255).rgb())
im.save('sample.png')
Result:

Related

Find parameters from the Vasicek model

I am given the following bond:
and need to fit the Vasicek model to this data.
My attempt is the following:
# ... imports
years = np.array([1, 2, 3, 4, 7, 10])
pric = np.array([0, .93, .85, .78, .65, .55, .42])
X = sympy.symbols("a b sigma")
a, b, s = X
rt1_rt = np.diff(pric)
ab_rt = np.array([a*(b-r) for r in pric[1:] ])
term = rt1_rt - ab_rt
def normpdf(x, mean, sd):
var = sd**2
denom = (2*sym.pi*var)**.5
num = sym.E**(-(x-mean)**2/(2*var))
return num/denom
pdfs = np.array([sym.log(normpdf(x, 0, s)) for x in term])
func = 0
for el in pdfs:
func += el
func = func.factor()
lmd = sym.lambdify(X, func)
def target_fun(params):
return lmd(*params)
result = scipy.optimize.least_squares(target_fun, [10, 10, 10])
I don't think that it outputs correct solution.
Your code is almost correct.
You want to maximize your function, therefore you need to place minus sign in front of lmd in your function.
def target_fun(params):
return -lmd(*params)
Additionally, the initial values are usually set to less than 1. Picking 10 is not the best choice as the algorithm might converge to a saddle point.
Consider [0.01, 0.01, 0.01].

MatPlotLib Scatter not working Inside Function

I am a beginner in Python. I have been trying my hands on MatPlotLib to compare the stats of soccer players in FIFA 20. Basically the problem I'm facing is:
def make_graph(value1, value2, namevalue, label1, label2):
print(value1, value2, namevalue)
plt.scatter(value1, value2)
plt.xlabel(label1)
plt.ylabel(label2)
for i in range(len(namevalue)):
plt.text(value1[i] + 0.3, value2[i] + 0.3, namevalue[i], fontdict=dict(color='red', size=10), bbox=dict(facecolor = 'yellow', alpha=0.5))
plt.xlim(min(value1) - 5, max(value2) + 5)
plt.ylim(min(value1) - 5, max(value2) + 5)
plt.show()
def Test():
df = xlrd.open_workbook(path)
data = df.sheet_by_index(0)
data.cell_value(0,0)
name = []
pace = []
shoot = []
for i in range(1, 450):
#print(data.cell_value(i, 3))
buff = str(data.cell_value(i,2)).strip()
if buff == "LM" or buff == "RM":
pacebuffer = int(data.cell_value(i, 4))
shootbuffer = int(data.cell_value(i, 5))
if pacebuffer >= 90:
name.append(data.cell_value(i, 3).strip("\n"))
pace.append(pacebuffer)
shoot.append(shootbuffer)
#print(name)
make_graph(pace, shoot, name, "Pace", "Shoot")
The particular code is showing me an empty graph.
BUT
When I write the same piece of code inside Test() which I wrote inside make_graph() , it gives me the desired output.
But in this way I have to rewrite that plotting thing every time I write some other functions and that's really a problem. Any idea how to fix this?
It is your x and y lims :
plt.xlim(min(value1) - 5, max(value2) + 5)
plt.ylim(min(value1) - 5, max(value2) + 5)
You should change to :
plt.xlim(min(value1) - 5, max(value1) + 5)
plt.ylim(min(value2) - 5, max(value2) + 5)
Technically your plt.scatter was working but then your x and y lims meant that you couldn't see.

how can I speed up my python code?

It's a program of import multiple images and extract feature using dct and histogram.
1) Import multiple images from folder
2) Make image size 256*256
3) Use image of 64*64 block unit with stride = 32
4) Do dct(8*8 size)
5) make histogram of dct
6) Extract features from dct coefficient histogram
The problem is that it's too slow.
I think it's because there's so many "for loop".
This is my full-code in python.
How can I change my code to speed up?
I am not familiar with python.
Please help me
import numpy as np
from scipy.fftpack import dct
from PIL import Image
import glob
import matplotlib.pyplot as plt
def find_index(x,key):
for i in range(0,len(x)):
if x[i] == key :
return i
else:
i = i+1
def image_open(path):
image_list = []
#for filename in glob.glob('path/*.jpg'):
for filename in glob.glob(path+'/*.jpg'):
im=Image.open(filename)
image_list.append(im)
return image_list
def dct_2(img):
#Get 2D Cosine Transform of Image
return dct(dct(np.asarray(img).T, norm='ortho').T, norm='ortho')
def return_array(array):
zero = [0.0, 0.0, 0.0, 0.0, 0.0]
range = int((max(array)) - min(array))
x, bins, patch = plt.hist(array, bins=range)
x = list(zero) + list(x) + list(zero)
return x
path = 'C:\\Users\\LG\\PycharmProjects\\photo' #folder that contains many images
images = image_open(path)
row = 0
array_matrix = []
label_matrix = []
for i in range(0, len(images)): #access image
box3 = (0,0,256,256)
a = images[i].crop(box3)
(y,cb,cr) = a.split() #ycbcr
width , height = y.size
y.show()
for q in range(0, height-32 , 32): #use image 64*64 block unit
for w in range(0 , width-32 ,32):
box1 =(q,w,q+64,w+64)
block = y.crop(box1)
array1 , array2 , array3 , array4 , array5 , array6 , array7 , array8 ,array9 = [],[],[],[],[],[],[],[],[]
for j in range(0,64,8): #dct
for n in range(0,64,8):
box2 = (j,n,j+8,n+8)
temp = block.crop(box2)
dct_temp = dct_2(temp)
array1.append(dct_temp[0,1])
array2.append(dct_temp[1,0])
array3.append(dct_temp[0,2])
array4.append(dct_temp[1,1])
array5.append(dct_temp[2,0])
array6.append(dct_temp[0,3])
array7.append(dct_temp[1,2])
array8.append(dct_temp[2,1])
array9.append(dct_temp[3,0])
x1 = return_array(array1) #extract feature from dct histogram
index = find_index(x1, max(x1))
u = [index - 5, index + 5, 1]
array_matrix.append(x1[u[0]:u[1] + 1:u[2]])
x2 = return_array(array2)
index = find_index(x2, max(x2))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x2[u[0]:u[1] + 1:u[2]])
x3 = return_array(array3)
index = find_index(x3, max(x3))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x3[u[0]:u[1] + 1:u[2]])
x4 = return_array(array4)
index = find_index(x4, max(x4))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x4[u[0]:u[1] + 1:u[2]])
x5 = return_array(array5)
index = find_index(x5, max(x5))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x5[u[0]:u[1] + 1:u[2]])
x6 = return_array(array6)
index = find_index(x6, max(x6))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x6[u[0]:u[1] + 1:u[2]])
x7 = return_array(array7)
index = find_index(x7, max(x7))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x7[u[0]:u[1] + 1:u[2]])
x8 = return_array(array8)
index = find_index(x8, max(x8))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x8[u[0]:u[1] + 1:u[2]])
x9 = return_array(array9)
index = find_index(x9, max(x9))
u = [index - 5, index + 5, 1]
array_matrix[row].extend(x9[u[0]:u[1] + 1:u[2]])
print(w/32)
row = row+1
print(array_matrix)
Rather than assuming that a specific section is taking longer than others, I'd recommend profiling your script. A profiler will collect metrics on how long certain parts of your program takes, and also allow you to better see how much any changes affect the code (makes it better, worse, etc).
Once you know where your problem lies, then you can take a more targeted approach at making it faster.
Have a look at the profiling module: https://docs.python.org/2/library/profile.html
Also have a look at some tutorials:
https://julien.danjou.info/blog/2015/guide-to-python-profiling-cprofile-concrete-case-carbonara
https://zapier.com/engineering/profiling-python-boss/
https://marcobonzanini.com/2015/01/05/my-python-code-is-slow-tips-for-profiling/

ValueError: object too deep for desired array, when I try to use scipy's convolve2d method

Here's the code:
x = range(-6,7)
tmp1 = []
for i in range(len(x)):
tmp1.append(math.exp(-(i*i)/(2*self.sigma*self.sigma)))
max_tmp1 = max(tmp1)
mod_tmp1 = []
for i in range(len(tmp1)):
mod_tmp1.append(max_tmp1 - i)
ht1 = np.kron(np.ones((9,1)),tmp1)
sht1 = sum(ht1.flatten(1))
mean = sht1/(13*9)
ht1 = ht1 - mean
ht1 = ht1/sht1
print ht1.shape
h = np.zeros((16,16))
for i in range(0, 9):
for j in range(0, 13):
h[i+3, j+1] = ht1[i, j]
for i in range(0, 10):
ag = 15*i
np.append(h, scipy.misc.imrotate(h, ag, 'bicubic'))
R = []
print h.shape
print self.img.shape
for i in range(0, 11):
print 'here'
R[i] = scipy.signal.convolve2d(self.img, h[i], mode = 'same')
rt = np.zeros(self.img.shape)
x, y = self.img.shape
The error I get states:
ValueError: object of too small depth for desired array
It looks to me as if the problem is that you're setting h up wrongly. I assume you want h[i] to be a 16x16 array suitable for convolving with, but that's not what you've actually made it, for a couple of different reasons.
I suggest you change the loop with the imrotate calls to this:
h = [scipy.misc.imrotate(h, 15*i, 'bicubic') for i in range(10)]
(What your existing code does is: first set up h as a single 16x16 array; then, repeatedly: compute a rotated version, "flatten" both h and that to make 256-element vectors, compute the result of appending them to make a 512-element vector, and throw the result away. numpy.append doesn't operate in place, and defaults to flattening its arguments before it appends. Neither of those is what you want!)
The list comprehension above will give you a 10-element Python list containing rotated versions of your convolution kernel.
... Oh, I see that your loop computing R actually wants 11 kernels, not 10. Make it range(11), then. (Your original code generated rotations of 0, 0, 15, 30, ..., 135 degrees, but I'm guessing 0, 15, 30, ..., 150 degrees is more likely to be what you want.)

python: adjust imported coordinates

I have a python script where i import coordinates of triangular elements, and element definitions from two seperate text files. I first define unique nodes for each triangluar element and then define a new rectangular element in between the triangular elements (this python scripts writes an input file for an FEM-calculation).
The coordinate file looks like the following:
id,x,y,
1, 0, 0
2, 0, 1
3, 0, 2
4, 1, 0
5, 1, 1
6, 1, 2
7, 2, 0
8, 2, 1
9, 2, 2
The element file looks like this:
id, n1, n2, n3
1, 1, 2, 4
2, 1, 2, 5
3, 2, 3, 5
4, 3, 5, 6
5, 5, 6, 8
6, 6, 8, 9
7, 5, 7, 8
8, 4, 5, 7
What i want to happend is that the coordinates of the nodes of the triangular elements are moved towarts the centre of mass of the triangular element, on this way the rectangular element in between the triangular elements will get a fysical thickness.
However i do something wrong in my python script (see below).
The part in the script between the horizontal lines should change the coordinates.
But for my script extra coordinates are added, instead of the (for the example here) 9 initial coordinates.
And the coordinates are also not moved in the correct direction.
Why does this happen and how can i solve this?
#!/usr/bin/env python
# Inlezen coordinaten
open("D://Documents//SkyDrive//afstuderen//99 EEM - Abaqus 6.11.2//scripting//_COORDINATEN.txt", "r")
import csv
import itertools
with open("_COORDINATEN.txt") as file:
data = csv.reader(file)
next(data)
coords = []
coords = ([[float(x) for x in line[1:]] for line in data])
#inlezen elementen
open("D://Documents//SkyDrive//afstuderen//99 EEM - Abaqus 6.11.2//scripting//_ELEMENTEN.txt", "r")
import csv
import itertools
with open("_ELEMENTEN.txt") as file:
data2 = csv.reader(file)
next(data2)
elems = []
elems = ([[int(x)-1 for x in line[1:]] for line in data2])
#Flip the original elements if required
for i,elem in enumerate(elems):
ecoords = [coords[e] for e in elem]
a = [x2-x1 for x1,x2 in zip(ecoords[0],ecoords[1])]
b = [x2-x1 for x1,x2 in zip(ecoords[1],ecoords[2])]
n = a[0]*b[1]-a[1]*b[0]
if n < 0:
elems[i] = [ elem[0], elem[2], elem[1] ]
#bewerking elementen
newcoords = []
newelems = []
for elem in elems:
ecoords = [coords[e] for e in elem]
newelem = range( len(newcoords), len(newcoords)+len(ecoords) )
newcoords += ecoords
newelems.append( newelem )
cohelems = []
for e,elem in enumerate(elems):
for edge in [[0,1],[1,2],[2,0]]:
eedge = [elem[i] for i in edge]
for e2,elem2 in enumerate(elems[e+1:]):
e2 += e+1
for edge2 in [[0,1],[1,2],[2,0]]:
eedge2 = [elem2[i] for i in edge2]
if all([i in eedge2 for i in eedge]):
newedge = [newelems[e][i] for i in edge ]
newedge += [newelems[e2][i] for i in edge2]
cohelems.append( newedge[-1::-1] )
#---------------------------------------------------------------------
def add_vectors(*points):
new_x = 0.0
new_y = 0.0
for point in points:
new_x += point[0]
new_y += point[1]
return [new_x, new_y]
def subtract_vectors(a, b):
new_x = a[0] - b[0]
new_y = a[1] - b[1]
return [new_x, new_y]
def mul_by_scalar(vector, scalar):
new_x = vector[0] * scalar
new_y = vector[1] * scalar
return [new_x, new_y]
new_triangles = []
for elem in elems:
new_triangles += [coords[e] for e in elem]
print 'new_triangles =', new_triangles
CM = mul_by_scalar(add_vectors(*new_triangles), 1.0/3)
point_to_CM_vectors = []
for point in new_triangles:
point_to_CM_vectors.append(subtract_vectors(CM, point))
new_triangle2 = []
#for e,elem in enumerate(elems):
for elem in elems:
for point, motion in zip(new_triangles, point_to_CM_vectors):
new_triangle2.append(add_vectors(point, mul_by_scalar(motion, 0.01)))
# new_triangle2 += [add_vectors(point, mul_by_scalar(motion, 0.01))]
print 'new_triangle2 =', new_triangle2
#---------------------------------------------------------------------
Thank you all in advance for the help!

Categories