Related
This MATLAB code is from Main_MOHHO.m from https://www.mathworks.com/matlabcentral/fileexchange/80776-multi-objective-harris-hawks-optimization-mohho. I want to make the same code using python, but I can't make the Rabbits variabel.
clc;
clear;
close all;
%% Problem Definition
nVar=3; % Number of Decision Variables
VarSize=[1 nVar]; % Size of Decision Variables Matrix
VarMin=0; % Lower Bound of Variables
VarMax=1; % Upper Bound of Variables
nPop=5; % Population Size
%% Initialization
empty_Rabbit.Location=[];
empty_Rabbit.Cost=[];
empty_Rabbit.Sol=[];
empty_Rabbit.IsDominated=[];
empty_Rabbit.GridIndex=[];
empty_Rabbit.GridSubIndex=[];
Rabbits=repmat(empty_Rabbit,nPop,1);
for i=1:nPop
Rabbits(i).Location = rand(VarSize).*(VarMax-VarMin)+VarMin;
X(i,:) = rand(VarSize).*(VarMax-VarMin)+VarMin;
end
I try to make it on google colab like this.
import numpy as np
nVar = 3 # Number of Decision Variables
VarSize = np.array((1, nVar)) # Size of Decision Variables Matrix
VarMin = 0 # Lower Bound of Variables
VarMax = 1 # Upper Bound of Variables
nPop = 5 # Population Size
class empty_Rabbit:
Location = []
Cost = []
IsDominated = []
GridIndex = []
GridSubIndex = []
Sol = []
Rabbits = np.tile(empty_Rabbit, (nPop, 1))
X = np.zeros((nPop, nVar))
Rabbit_Location = np.zeros((VarSize))
Rabbit_Energy = math.inf
for i in range(nPop):
Rabbits[i, 0].Location = np.multiply(np.random.rand(VarSize[0], VarSize[1]),
(VarMax-VarMin) + VarMin)
print(Rabbits[i,0].Location)
But, the Rabbits_Location same for each row.
Output Google Colab
What is the correct way to create Rabbits variable in python so the output like the output with number 1 in the pic? Thank you.
Two issues exist in your code. First, np.tile repeats the same object (nPop, 1) times. So, when you change one of the objects, you actually change the same memory location. Second, you want to initialize a different object each time instead of referring to the same object, so you want to write empty_Rabbit() to create a new instance of that object. Both suggestions can be achieved using a comprehension like [empty_Rabbit() for i in range(nPop)] and reshape to any new dimensions if required.
import numpy as np
nVar = 3 # Number of Decision Variables
VarSize = np.array((1, nVar)) # Size of Decision Variables Matrix
VarMin = 0 # Lower Bound of Variables
VarMax = 1 # Upper Bound of Variables
nPop = 5 # Population Size
class empty_Rabbit:
Location = []
Cost = []
IsDominated = []
GridIndex = []
GridSubIndex = []
Sol = []
Rabbits = np.array([empty_Rabbit() for i in range(nPop)]).reshape(nPop,1)
X = np.zeros((nPop, nVar))
Rabbit_Location = np.zeros((VarSize))
Rabbit_Energy = np.inf
for i in range(nPop):
Rabbits[i, 0].Location = np.multiply(np.random.rand(VarSize[0], VarSize[1]),
(VarMax-VarMin) + VarMin)
print(Rabbits[i,0].Location)
for i in range(nPop):
print(Rabbits[i,0].Location)
Now, the output of both print statements will be identical with distinct rows:
[[0.5392264 0.39375339 0.59483626]]
[[0.53959355 0.91049574 0.58115175]]
[[0.46152304 0.43111977 0.06882631]]
[[0.13693784 0.82075653 0.49488394]]
[[0.06901317 0.34133836 0.91453956]]
[[0.5392264 0.39375339 0.59483626]]
[[0.53959355 0.91049574 0.58115175]]
[[0.46152304 0.43111977 0.06882631]]
[[0.13693784 0.82075653 0.49488394]]
[[0.06901317 0.34133836 0.91453956]]
scipy.io.loadmat uses structured arrays when loading struct from MATLAB .mat files. But I think that's too advanced for you.
I think you need to create a set of numpy arrays, rather than try for some sort of class or more complicated structure.
empty_Rabbit.Location=[];
empty_Rabbit.Cost=[];
empty_Rabbit.Sol=[];
empty_Rabbit.IsDominated=[];
empty_Rabbit.GridIndex=[];
empty_Rabbit.GridSubIndex=[];
becomes instead
location = np.zeros(nPop)
cost = np.zeros(nPop)
sol = np.zeros(nPop)
isDominated = np.zeros(nPop) # or bool dtype?
gridIndex = np.zeros(nPop)
gridSubIndex = np.zeros(nPop)
np.zeros makes a float array; for some of those you might want np.zeros(nPop, dtype=int) (if used as index).
rabbit= np.zeros(nPop, dtype=[('location',float), ('cost',float),('sol',float), ....])
could be used to make structured array, but you'll need to read more about those.
MATLAB lets you use iteration freely as in
for i=1:nPop
Rabbits(i).Location = rand(VarSize).*(VarMax-VarMin)+VarMin;
X(i,:) = rand(VarSize).*(VarMax-VarMin)+VarMin;
end
but that's slow (as it used to be MATLAB before jit compilation). It's better to use whole array calculations
location = np.random.rand(nPop,VarSize) * (VarMax-VarMin)+VarMin
will make a (nPop,VarSize) 2d array, not the 1d that np.zeros(nPop) created.
Looks like X could be created in the same way (without iteration).
I'm trying to create a program that creates an average out of an image by looping through each RGBA value in two images to average them out and create one composite image, but the right value isn't being written to my list comp_img, which contains all the new image data.
I'm using these 256x256 images for debugging.
But it just creates this as output:
While this is the composite color, the 64 gets wiped out entirely. Help is very much appreciated, thank you.
from PIL import Image
import numpy as np
from math import ceil
from time import sleep
red = Image.open("64red.png")
grn = Image.open("64green.png")
comp_img = []
temp = [0,0,0,0] #temp list used for appending
#temp is a blank pixel template
for i in range(red.width):
comp_img.append(temp)
temp = comp_img
#temp should now be a row template composed of pixel templates
#2d to 3d array code go here
comp_img = []
for i in range(red.height):
comp_img.append(temp)
reddata = np.asarray(red)
grndata = np.asarray(grn)
reddata = reddata.tolist() #its uncanny how easy it is
grndata = grndata.tolist()
for row, elm in enumerate(reddata):
for pxl, subelm in enumerate(elm):
for vlu_index, vlu in enumerate(subelm):
comp_img[row][pxl][vlu_index] = ceil((reddata[row][pxl][vlu_index] + grndata[row][pxl][vlu_index])/2)
#These print statements dramatically slowdown the otherwise remarkably quick program, and are solely for debugging/demonstration.
output = np.array(comp_img, dtype=np.uint8) #the ostensible troublemaker
outputImg = Image.fromarray(output)
outputImg.save("output.png")
You could simply do
comp_img = np.ceil((reddata + grndata) / 2)
This gives me
To get correct values it needs to work with 16bit values - because for uint8 it works only with values 0..255 and 255+255 gives 254 instead of 510 (it calculates it modulo 256 and (255+255) % 256 gives 254)
reddata = np.asarray(red, dtype=np.uint16)
grndata = np.asarray(grn, dtype=np.uint16)
and then it gives
from PIL import Image
import numpy as np
red = Image.open("64red.png")
grn = Image.open("64green.png")
reddata = np.asarray(red, dtype=np.uint16)
grndata = np.asarray(grn, dtype=np.uint16)
#print(reddata[128,128])
#print(grndata[128,128])
#comp_img = (reddata + grndata) // 2
comp_img = np.ceil((reddata + grndata) / 2)
#print(comp_img[128,128])
output = np.array(comp_img, dtype=np.uint8)
outputImg = Image.fromarray(output)
outputImg.save("output.png")
You really should work with just NumPy arrays and functions, but I'll explain the bug here. It's rooted in how you make the nested list. Let's look at the first level:
temp = [0,0,0,0] #temp list used for appending
#temp is a blank pixel template
for i in range(red.width):
comp_img.append(temp)
At this stage, comp_img is a list with size red.width whose every element/pixel references the same RGBA-list [0,0,0,0]. I don't just mean the values are the same, it's one RGBA-list object. When you edit the values of that one RGBA-list, you edit all the pixels' colors at once.
Just fixing that step isn't enough. You also make the same error in the next step of expanding comp_img to a 2D matrix of RGBA-lists; every row is the same list.
If you really want to make a blank comp_img first, you should just make a NumPy array of a numerical scalar dtype; there you can guarantee every element is independent:
comp_img = np.zeros((red.height, red.width, 4), dtype = np.uint8)
If you really want a nested list, you have to properly instantiate (make new) lists at every level for them to be independent. A list comprehension is easy to write:
comp_img = [[[0,0,0,0] for i in range(red.width)] for j in range(red.height)]
Thanks for taking a moment to read this! So, my first issue is that I'm trying to create a function, "selectionData()", to get an object's translate, rotate, and scale values and then return them as a dictionary, but find myself struggling a bit. Using the code listed below, all I keep getting is the object's name. How can I modify it to get its translate, rotate, and scale values to return as a dictionary?
My second issue is that I'm trying to create a function, "setData(data)", that takes as input the aforementioned dictionary built with selectionData() and restores the data in the dictionary to the selected objects. How do I do that?
My apologies if either of these questions are foolish, but thank you for your time, regardless! Cheers!
Current code is listed below:
from maya import cmds
sel = cmds.ls(sl = 1)
meshes =[]
for s in sel :
shape = cmds.listRelatives(s , shapes = 1 )
if shape :
if cmds.nodeType(shape[0]) == "mesh" :
meshes.append(s )
meshData = {}
for m in meshes :
pos = cmds.xform ( m , q =1 , ws = 1 , t = 1)
rot = cmds.xform( m , q =1 , ws = 1 , rotation = 1 )
scl = cmds.getAttr ( m + '.s' )[0]
currentDict = {
"pos" : pos ,
"rot" : rot ,
"scl" : scl ,
}
meshData[m] = currentDict
def selectionData( selectionDict):
for k in selectionDict :
print k
selectionData(meshData)
First of all, to list all the objects with transforms you can use this command:
cmds.ls(selection=True, transforms=True, dagObjects=True)
If you want to read/write the transforms, you don't need to get the translation, then rotation and scale separately. You can read the composite transformation matrix like this:
xform_matrix = cmds.xform(source_object, query=True, matrix=True)
You'll get a list of 16 float numbers that are ready to be applied to other objects:
cmds.xform(destination_object, matrix=xform_matrix)
I am not sure how do you want to map the transforms from one set of selected objects to another set. If you describe, I'll be able to post the complete code.
The following script will collect the composite transformation matrix of all selected objects in the dictionary with long object names as the keys:
selected_objects_matrix = {}
for current_object in cmds.ls(selection=True, transforms=True, dagObjects=True):
selected_objects_matrix[cmds.ls(current_object, long=True)] = cmds.xform(
current_object,
query=True,
matrix=True)
Then if you move/rotate/scale the objects in Maya, you can revert like that:
for current_object in selected_objects_matrix:
cmds.xform(
current_object,
matrix=selected_objects_matrix[current_object])
you really just want to do what you have in reverse
setting the q=1 sets the command into query mode.
removing this flag defaults the command to edit mode
getAttr and setAttr are their respective commands, however you need to be aware of the data that youre setting. even though youre grabbing the s attribute above youre making that only grab the x value so when you set it you need to specify sx
cmds.xform ( m , ws = 1 , t = posValues)
cmds.xform( m , ws = 1 , rotation = rotValues )
cmds.setAttr ( m + '.sx', scaleValue) # sx because you are only grabbing the X Value
I'm working on class work and am having trouble with the data structure that is generated by using the load() function on an image in Python. What I am doing here is trying to convert an entire image to HSL from RGB. The problem is, when I try to write the new values back to the data structure, they don't get written. I have successfully written to this type of structure in other places in my code, however. If that were not the case, I would have just assumed that the structure is immutable, but it seems like it is not. If anyone can explain to me what is going on, and how this particular data structure works, I would be very grateful. I suspect that I somehow need to create a new structure to write to in the function, but I don't know how to, aside from creating a new image and getting the structure from that.
def toHSL(px): #reorders values to h, s, l from h, l, s
for x in xrange(0, dim[0]):
for y in xrange(0, dim[1]):
r, g, b = px[x,y][0], px[x,y][1], px[x,y][2] #I don't really understand how to create this type of data structure, even
r, g, b = [x/255.0 for x in r, g, b] #Python uses values from 0 to 1
h, l, s = colorsys.rgb_to_hls(r, g, b)
px[x,y] = (int(h*255), int(s*255), int(l*255)) #trying to save back to the original data structure
return px
img_name = "Mandrill"
try:
im = Image.open(img_name + ".bmp")
except:
print "Unable to load image."
sys.exit()
dim = im.size
pix = im.load()
new = Image.new("RGB", dim)
newpx = new.load()
hsl = toHSL(pix)
print hsl[0,0][0], hsl[0,0][1], hsl[0,0][2] #<< gives the original values
I stand corrected, apparently it is possible to read and write pixels using that (undocumented) indexing technique, at least with some image formats. Learn something new everyday... ;-)
Anyway what's wrong with your program is the line:
r, g, b = [x/255.0 for x in r, g, b]
which changes the value ofxwhich is already being used to iterate over the pixel coordinates. Simply changing it to another variable name as shown below will make your code do what you want:
r, g, b = [c/255.0 for c in r, g, b]
(Note, better yet, change it to the following and remove the line preceding it)
r, g, b = [c/255.0 for c in px[x,y]]
After doing that, here's the image that will result — displayed as RGB, not HSL, to show that the structure is indeed mutable:
I am trying to complete an image editing task in my learning Python book. I need help with the horizontal flip.
The instructions are: Write a function called "flip_horizontal" which will flip the picture horizontally. That is, the pixel that is on the far right end of the row ends up on the far left of the row and vice versa (remember to preserve RGB order!).
My code does not flip the image horizontally when I open it. Also, how can I write my effects to different files (use the original file and apply one function the original file and output it, and then apply another function to the original file and output it to another file). Please, keep in mind that I am only 11 years old and have a very basic understanding of Python and image editing, it is just an interest of mine.
class PPM(object):
def __init__(self, infile, outfile):
self.infile=infile
self.outfile=outfile
#Read in data of image
data= open(self.infile,"r")
datain=data.read()
splits=datain.split()
#Header info
self.type=splits[0]
self.columns=splits[1]
self.row=splits[2]
self.colour=splits[3]
self.pixels=splits[4:]
def negate_red(self):
for b in range (0, (len(self.pixels)) , 3):
remainder=255-self.colour
def writetofile(self):
dataout= open(self.outfile,"w")
dataout.write(self.type +"\n" + self.columns + "\n" + self.row +"\n"+ self.colour +"\n"+ " ".join (self.pixels))
def grey_scale(self):
if int(self.columns) > 1000:
return "ERROR!! Number of columns is larger than what can be held in a buffer."
else:
for b in range(0, (len(self.pixels)) , 3):
sum = int(self.pixels[b]) + int(self.pixels[b+1]) + int(self.pixels[b+2])
avg = int(sum/3)
self.pixels[b] = str(avg)
self.pixels[b+1] = str(avg)
self.pixels[b+2] = str(avg)
def flatten_red(self):
for colour in range (0,len(self.pixels),3):
self.pixels [colour]=str(0)
#Create a 2d lists with the smaller lists containing the rgb values and append lists of lists
def horizontal_flip(self):
if int(self.columns) > 1000:
return "ERROR!! Number of columns is larger than what can be held in a buffer."
else:
temp_list = []
for b in range(int(self.row)):
column_list = []
column_list += self.pixels[0:int(self.columns) * 3]
self.pixels = self.pixels[int(self.columns) * 3 : ]
temp_list.append(column_list)
#print temp_list
new_list = []
for i in range(int(len(temp_list))):
new_list.append (temp_list[i][0])
new_list.append (temp_list[i][1])
new_list.append (temp_list[i][2])
temp_list[i] = temp_list[i][::-1]
sample= PPM("cake.ppm", "Replica.ppm")
sample.flatten_red()
sample.horizontal_flip()
sample.greyscale()
sample.negate_red()
Imagine a row of pixels.
i.imgur.com/1iZesZL.jpg
Now, what we want to do is to flip it so that the right-most pixel is on the left-most place, right?
So if we have the pixel on the far-left with the coordinates (x,y) then the pixel on the far-right has the coordinates (x+n, y) where n = the width of the picture in pixels.
i.imgur.com/EE7Qj5r.jpg
Now, a horizontal flip would look like this, right?
i.imgur.com/fbNLCuX.jpg
So what we do is we go from the far right and the far left, swap the values of the current pixels and go one step to the right and one step to the left until they meet in the middle.
In pseudo-code this might look something like this:
n = width
x = 0
y = whatever row we're on currently
while n != width/2
temporary = (x,y) # (x,y) refers to a specific pixel in the picture
(x,y) = (n, y)
(n, y) = temporary
n = n-1
x = x+1
Do you think that's enough to solve the rest yourself? Wouldn't want to take the fun out of it :-)
Are you really 11 years old?
It looks like each element of your temp_list is a column of the image to reverse the order of the columns you just have to do temp_list = temp_list[::-1], but you're doing temp_list[i] = temp_list[i][::-1] which I think flips the image up-down (I might have it backwards though). Either way, once you get the flip, you'll need to flatten the image again and replace self.pixels, something like:
pixels = []
for column in temp_list:
pixels.extend(column)
self.pixels = pixels
You're not doing much with new_list, I don't think you need it. Also if you want to save the image to different files, take the filename as an argument to writetofile, if you do that you won't need to have it in __init__, so something like:
class PPM(object):
def __init__(self, infile):
self.infile=infile
# More code here
def writetofile(self, outfile):
dataout = open(outfile,"w")
dataout.write(self.type +"\n" + self.columns + "\n" + self.row +"\n"+ self.colour +"\n"+ " ".join (self.pixels))
dataout.close()
sample = PPM("cake.ppm")
sample.horizontal_flip()
sample.writetofile("Replica1.ppm")
sample.negate_red()
sample.writetofile("Replica2.ppm")
Maybe not for you since you want to practice but I came here looking for a solution to the same Problem after Research I found this and wanted to share the following:
OpenCV provides a function to flip an image.
void flip(array src, array dst, int flipCode)
Flips a 2D array around vertical, horizontal or both axes.
Parameters:
src – The source Array
dst – The destination array; will have the same size and same type as src
flipCode – Specifies how to flip the array: 0 means flipping around the x-axis, positive (e.g., 1) means flipping around y-axis, and negative (e.g., -1) means flipping around both axes.The function flip flips the array in one of three different ways (row and column indices are 0-based).
Example code:
cv.flip(original_image,flip_image,1);