Python 需要提高图像创建的速度

Python 需要提高图像创建的速度,python,image,numpy,colors,Python,Image,Numpy,Colors,我正在尝试用每种可能的颜色创建一个图像。它将从种子像素开始,然后在其周围放置随机生成的RGB像素。未来的放置将基于任意一个开放点,其周围像素的平均值最接近要放置的新颜色 from PIL import Image import numpy as np from random import randint import sys import random import itertools sys.setcheckinterval(10000) def moddistance3(x1,y1,z1

我正在尝试用每种可能的颜色创建一个图像。它将从种子像素开始,然后在其周围放置随机生成的RGB像素。未来的放置将基于任意一个开放点,其周围像素的平均值最接近要放置的新颜色

from PIL import Image
import numpy as np
from random import randint
import sys
import random
import itertools

sys.setcheckinterval(10000)

def moddistance3(x1,y1,z1,x2,y2,z2):  #get relative distance between two 3D points
    x = abs(x1 - x2)
    y = abs(y1 - y2)
    z = abs(z1 - z2)
    return (x + y + z)

def genColor(unused): #generate random color (not used anymore)
    test = 0
    while test == 0:
        red = randint(0,255)
        green = randint(0,255)
        blue = randint(0,255)
        if unused[red,green,blue] == 1:
            test = 1
    return (red,green,blue)

def surroundAvg(points,unfilled):
    surrounding = {}
    count = len(points)
    for inc in xrange(count):
        neighbors = filledNeighbors(points[inc][0],points[inc][1],unfilled)
        nearcount = len(neighbors)
        pixred = 0
        pixgreen = 0
        pixblue = 0
        for num in xrange(nearcount):
            (temp_red,temp_green,temp_blue) = pixels[neighbors[num][0],neighbors[num][1]]
            pixred = pixred + temp_red
            pixgreen = pixgreen + temp_green
            pixblue = pixblue + temp_blue
        pixred = pixred / nearcount
        pixgreen = pixgreen / nearcount
        pixblue = pixblue / nearcount
        surrounding[(points[inc][0],points[inc][1])] = (pixred,pixgreen,pixblue)
    return surrounding

def genPoint(perim,unfilled,averages,red,green,blue):
    num_test = len(perim)
    test = 0
    least_diff = 9999
    nearby = []
    for point in xrange(num_test):
        i = perim[point][0]
        j = perim[point][1]
        pixred = averages[(i,j)][0]
        pixgreen = averages[(i,j)][1]
        pixblue = averages[(i,j)][2]
        diff = abs(red - pixred) + abs(green - pixgreen) + abs(blue - pixblue)
        if diff < least_diff or test == 0:
            least_diff = diff
            newx = i
            newy = j
            test = 1
    return newx,newy

def cubegen():  #create the cube of colors with each color having its own number
    cube = np.zeros(16777216,dtype=np.object)
    num = 0
    for red in xrange(0,256):
        for green in xrange(0,256):
            for blue in xrange(0,256):
                cube[num] = [red,green,blue]
                num += 1
    return cube

def getNeighbors(x,y,unfilled):
    Prod = itertools.product
    toremove = []
    neighbors = list(Prod(range(x-1,x+2),range(y-1,y+2)))
    for num in xrange(len(neighbors)):
        i,j = neighbors[num]
        if j > 4095 or i > 4095 or unfilled[(i,j)] == 0 or j < 0 or i < 0:
            toremove.append((i,j))
    map(neighbors.remove,toremove)
    return neighbors

def filledNeighbors(x,y,unfilled):
    Prod = itertools.product
    toremove = []
    neighbors = list(Prod(range(x-1,x+2),range(y-1,y+2)))
    #neighbors = filter(lambda i,j: j < 4096 and i < 4096 and unfilled[i,j] == 0 and j > -1 and i > -1,allneighbors)
    for num in xrange(len(neighbors)):
        i,j = neighbors[num]
        if j > 4095 or i > 4095 or unfilled[(i,j)] == 1 or j < 0 or i < 0:
            toremove.append((i,j))
    map(neighbors.remove,toremove)
    return neighbors

img = Image.new('RGB', (4096,4096)) # create a new black image
pixels = img.load() # create the pixel map

colorList = range(16777216)
colorCube = cubegen()
print("Color cube created successfully")
unfilled = {}
for x in xrange(4096):
    for y in xrange(4096):
        unfilled[(x,y)] = 1
startx = 2048
starty = 2048
random.shuffle(colorList)
print("Color list shuffled successfully")
color = colorList[0]
(red,green,blue) = colorCube[color]
pixels[startx,starty] = (red,green,blue)
unfilled[(startx,starty)] = 0
perim_empty = getNeighbors(startx,starty,unfilled)
edge = []
#edge.append((startx,starty))
avg = surroundAvg(perim_empty,unfilled)
print("First point placed successfully.")
#appendEdge = edge.append
#removeEdge = edge.remove
appendPerim = perim_empty.append
removePerim = perim_empty.remove
updateAvg = avg.update


for iteration in xrange(1,16777216):
    temp = {}
    color = colorList[iteration]
    (red,green,blue) = colorCube[color]
    (i,j) = genPoint(perim_empty,unfilled,avg,red,green,blue)
    unfilled[(i,j)] = 0
    pixels[i,j] = (red,green,blue)
    new_neighbors = getNeighbors(i,j,unfilled)
    map(appendPerim,new_neighbors)
    temp = surroundAvg(new_neighbors,unfilled)
    updateAvg(temp)
    removePerim((i,j))
    #appendEdge((i,j))

    #if iteration % 20 == 0:
    #   toremove = []
    #   appendToRemove = toremove.append
    #   for num in xrange(len(edge)):
    #       nearby = getNeighbors(edge[num][0],edge[num][1],unfilled)
    #       if len(nearby) == 0:
    #           appendToRemove(edge[num])
        #for num in xrange(len(toremove)):
        #   edge.remove(toremove[num])
    #   map(removeEdge,toremove)

    if iteration % 500 == 0:
        print("Iteration %d complete" %iteration)
    if iteration == 100000 or iteration == 500000 or iteration ==1000000 or iteration == 5000000 or iteration == 10000000 or iteration == 15000000:
        img.save("Perimeter Averaging -- %d iterations.bmp" %iteration)
img.save("Perimeter Averaging Final.bmp")
img.show()
从PIL导入图像
将numpy作为np导入
从随机导入randint
导入系统
随机输入
进口itertools
系统设置检查间隔(10000)
def moddistance3(x1、y1、z1、x2、y2、z2):#获取两个3D点之间的相对距离
x=abs(x1-x2)
y=abs(y1-y2)
z=abs(z1-z2)
返回(x+y+z)
def genColor(未使用):#生成随机颜色(不再使用)
测试=0
当test==0时:
红色=randint(0255)
绿色=兰迪特(0255)
蓝色=兰迪特(0255)
如果未使用[红、绿、蓝]==1:
测试=1
返回(红色、绿色、蓝色)
def周围平均值(点,未填充):
周围={}
计数=长度(点数)
对于X范围内的inc(计数):
邻居=已填充的邻居(点数[inc][0],点数[inc][1],未填充)
nearcount=len(邻居)
pixred=0
pixgreen=0
像素蓝=0
对于xrange中的num(nearcount):
(淡红色、淡绿色、淡蓝色)=像素[邻居[num][0],邻居[num][1]]
pixred=pixred+温度
像素绿色=像素绿色+温度绿色
像素蓝=像素蓝+温度蓝
pixred=pixred/nearcount
像素绿色=像素绿色/近计数
像素蓝=像素蓝/近计数
周围[(点数[inc][0],点数[inc][1])]=(像素红色、像素绿色、像素蓝色)
返回环境
def genPoint(边缘、未填充、平均值、红色、绿色、蓝色):
num_test=len(perim)
测试=0
最小差值=9999
附近=[]
对于X范围内的点(数值测试):
i=perim[点][0]
j=周长[点][1]
pixred=平均值[(i,j)][0]
pixgreen=平均值[(i,j)][1]
pixblue=平均值[(i,j)][2]
差异=abs(红色-像素红色)+abs(绿色-像素绿色)+abs(蓝色-像素蓝色)
如果差异4095或i>4095或未填充[(i,j)]==0或j<0或i<0:
删除。追加((i,j))
映射(邻居。删除,删除)
回乡
def FILLED邻域(x、y、未填充):
产品=itertools.product
toremove=[]
邻居=列表(产品(范围(x-1,x+2),范围(y-1,y+2)))
#邻居=过滤器(λi,j:j<4096和i<4096,未填充[i,j]==0和j>-1和i>-1,所有邻居)
对于xrange中的num(len(邻居)):
i、 j=邻居[num]
如果j>4095或i>4095或未填充[(i,j)]==1或j<0或i<0:
删除。追加((i,j))
映射(邻居。删除,删除)
回乡
img=Image.new('RGB',(40964096))#创建一个新的黑色图像
像素=img.load()#创建像素贴图
颜色列表=范围(16777216)
colorCube=cubegen()
打印(“已成功创建彩色立方体”)
未填充={}
对于x范围内的x(4096):
对于X范围内的y(4096):
未填充[(x,y)]=1
startx=2048
starty=2048
随机。洗牌(颜色列表)
打印(“颜色列表洗牌成功”)
颜色=颜色列表[0]
(红、绿、蓝)=彩色立方体[颜色]
像素[startx,starty]=(红、绿、蓝)
未填充[(星形,星形)]=0
perim_empty=GetNeights(startx、starty、未填充)
边缘=[]
#追加边((startx,starty))
平均值=周围平均值(周围为空,未填充)
打印(“成功放置第一个点”)
#appendEdge=edge.append
#removedge=edge.remove
appendPerim=perim\u empty.append
removePerim=perim\u空。移除
updateAvg=avg.update
对于xrange(116777216)中的迭代:
温度={}
颜色=颜色列表[迭代]
(红、绿、蓝)=彩色立方体[颜色]
(i,j)=genPoint(perim_空、未填充、平均、红色、绿色、蓝色)
未填充[(i,j)]=0
像素[i,j]=(红、绿、蓝)
新邻居=获取邻居(i,j,未填充)
地图(附件、新邻居)
温度=周围平均值(新邻居,未填充)
updateAvg(临时)
移除perim((i,j))
#附录边((i,j))
#如果迭代%20==0:
#toremove=[]
#appendToRemove=toremove.append
#对于xrange中的num(len(edge)):
#附近=获取邻居(边[num][0],边[num][1],未填充)
#如果len(附近)==0:
#appendToRemove(边[num])
#对于xrange中的num(len(toremove)):
#删除边缘(删除[num])
#映射(删除边缘,删除)
如果迭代%500==0:
打印(“迭代%d已完成”%Iteration)
如果迭代==100000或迭代==500000或迭代==1000000或迭代==5000000或迭代==10000000或迭代==15000000:
保存(“周长平均--%d次迭代.bmp”%iteration)
保存(“周长平均最终.bmp”)
img.show()

问题是,当我尝试运行这个程序时,它甚至需要几天的时间来处理1000000种颜色,并且随着时间的推移,速度会大大减慢。我不知道如何使它花费更少的时间,我知道一定有一种方法可以做到这一点,不需要几个月。我对代码还不熟悉,正在自学,所以请原谅我完全忽略的任何明显的修复。

好的,我花了一些时间研究这个问题,并做了一些更改以加快速度。我真的很喜欢你在这个项目中实施的想法,而且结果非常好
from PIL import Image
import sys
import random
import itertools
import datetime as dt


#sys.setcheckinterval(10000)

def surroundAvg(points):
    surrounding = {}
    for inc in points:
        neighbors = filledNeighbors(inc[0],inc[1])
        nearcount = len(neighbors)
        pixred = 0
        pixgreen = 0
        pixblue = 0
        for n in neighbors:
            (temp_red,temp_green,temp_blue) = pixels[n[0],n[1]]
            pixred += temp_red
            pixgreen += temp_green
            pixblue += temp_blue
        pixred = pixred / nearcount
        pixgreen = pixgreen / nearcount
        pixblue = pixblue / nearcount
        surrounding[(inc[0],inc[1])] = (pixred,pixgreen,pixblue)
    return surrounding

def genPoint(perim,averages,red,green,blue):
    test = 0
    least_diff = 9999
    threshold = 35
    for point in perim:
        i = point[0]
        j = point[1]
        if pixels[i,j] == (0,0,0):
            pixred = averages[(i,j)][0]
            pixgreen = averages[(i,j)][1]
            pixblue = averages[(i,j)][2]
            diff = abs(red - pixred) + abs(green - pixgreen) + abs(blue - pixblue)
            if diff < least_diff or test == 0:
                least_diff = diff
                newx = i 
                newy = j 
                test = 1
                if least_diff < threshold:
                    return newx,newy,perim
        else:
            perim.pop(perim.index(point))
    return newx,newy,perim

def cubegen():  #create the cube of colors with each color having its own number
    cube = []
    num = 0
    for red in xrange(0,256):
        for green in xrange(0,256):
            for blue in xrange(0,256):
                cube.append((red,green,blue))
                num += 1
    return tuple(cube)

def getNeighbors(x,y):
    Prod = itertools.product
    toremove = []
    neighbors = list(Prod(range(x-1,x+2),range(y-1,y+2)))
    for num in xrange(len(neighbors)):
        i,j = neighbors[num]
        if j > 4095 or i > 4095 or pixels[i,j] != (0,0,0) or j < 0 or i < 0:
            toremove.append((i,j))
    map(neighbors.remove,toremove)
    return neighbors

def filledNeighbors(x,y):
    Prod = itertools.product
    toremove = []
    neighbors = list(Prod(range(x-1,x+2),range(y-1,y+2)))
    for num in xrange(len(neighbors)):
        i,j = neighbors[num]
        if j > 4095 or i > 4095 or pixels[i,j] == (0,0,0) or j < 0 or i < 0:
            toremove.append((i,j))
    map(neighbors.remove,toremove)
    return neighbors

img = Image.new('RGB', (4096,4096)) # create a new black image
pixels = img.load() # create the pixel map

print("Making list")
colorList = range(16777216)
random.shuffle(colorList)
print("Color list shuffled successfully")

print("Making cube")
colorCube = cubegen()
print("Color cube created successfully")

startx = 2048
starty = 2048
color = colorList[0]

(red,green,blue) = colorCube[color]
#start with a random color
pixels[startx,starty] = (red,green,blue)

#get it's neighboring pixels
perim_empty = getNeighbors(startx,starty)

#calc avg values (original pixel)
avg = surroundAvg(perim_empty)
print("First point placed successfully.")
appendPerim = perim_empty.append
removePerim = perim_empty.remove
updateAvg = avg.update

start = dt.datetime.now()
for iteration in xrange(1,16777216):
    temp = {}
    color = colorList[iteration]
    (red,green,blue) = colorCube[color]
    i,j,perim_empty = genPoint(perim_empty,avg,red,green,blue)
    pixels[i,j] = (red,green,blue)
    new_neighbors = getNeighbors(i,j)
    map(appendPerim,new_neighbors)
    temp = surroundAvg(new_neighbors)
    updateAvg(temp)
    removePerim((i,j))
    for p in perim_empty:
        if p[0] == i and p[1] == j:
            perim_empty.remove(p)

    if iteration % 1000 == 0:
        end = dt.datetime.now()
        print("Iteration %d complete: %f" %(iteration,(end-start).total_seconds()))
        print("Perimeter size: %d"%len(perim_empty))
        print("Averages size: %d"%sys.getsizeof(avg))
        start = dt.datetime.now()
        img.save("%06d.png" % (iteration/1000))

img.save("Perimeter Averaging Final.bmp")
img.show()