回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p>Python2.7和Windows7。你知道吗</p>
<p>我正在寻找如何快速计算脚本。首先是我的想法:</p>
<p>从一个给定的颜色开始,我想生成一个由30种以上的颜色(rgb值)组成的列表,这些颜色对于人眼来说彼此之间的区别最大,并且列表的前面比末尾更明显。你知道吗</p>
<p>目前,我估计这个脚本需要48小时才能完成。我可以让它在周末运行,但我想我会借此机会学习一些关于python性能的知识。你知道吗</p>
<p>概述代码的作用:</p>
<p><code>gen_colours()</code>包含一个运行30次的循环。每次有4个进程运行<code>multi(n, l, g)</code>,其中包含在0和255之间的r、g和b值上迭代的大循环(r值在进程之间被分割,因此它循环64次)。最内部的循环包含另一个循环,该循环将rgb值与通过调用<code>compute_dist([r, g, b], c)</code>找到的rgb值进行检查。你知道吗</p>
<p>不管怎样,如果不完全重组我的代码,帮助它加速的东西会很酷。另外,运行所有四个CPU最多48小时…有问题吗?你知道吗</p>
<p>代码:</p>
<pre><code>from math import sqrt, pow, atan2, atan, sin, cos, exp, radians, degrees
from fractions import Fraction
import time
import multiprocessing
def to_xyz(rgb):
r = rgb[0] / 255.0
g = rgb[1] / 255.0
b = rgb[2] / 255.0
f = Fraction(12, 5)
if r > 0.04045:
r = ((r + 0.055) / 1.055) ** f
else:
r /= 12.92
if g > 0.04045:
g = ((g + 0.055) / 1.055) ** f
else:
g /= 12.92
if b > 0.04045:
b = ((b + 0.055) / 1.055) ** f
else:
b /= 12.92
r *= 100
g *= 100
b *= 100
# Observer = 2 degrees, Illuminant = D65
x = r * 0.4124 + g * 0.3576 + b * 0.1805
y = r * 0.2126 + g * 0.7152 + b * 0.0722
z = r * 0.0193 + g * 0.1192 + b * 0.9505
return [x, y, z]
def to_lab(xyz):
x = xyz[0]
y = xyz[1]
z = xyz[2]
# Observer= 2deg, Illuminant= D65
x /= 95.047
y /= 100.0
z /= 108.883
f = Fraction(1, 3)
if x > 0.008856:
x **= f
else:
x = 7.787 * x + 0.13793103448
if y > 0.008856:
y **= f
else:
y = 7.787 * y + 0.13793103448
if z > 0.008856:
z **= f
else:
z = 7.787 * z + 0.13793103448
L = 116 * y - 16
a = 500 * (x - y)
b = 200 * (y - z)
return [L, a, b]
def compute_dist(rgb1, rgb2):
""" Compute the apparent difference in colours using CIEDE2000 standards """
xyz1 = to_xyz(rgb1)
xyz2 = to_xyz(rgb2)
lab1 = to_lab(xyz1)
lab2 = to_lab(xyz2)
a1 = lab1[1]
a2 = lab2[1]
b1 = lab1[2]
b2 = lab2[2]
L1 = lab1[0]
L2 = lab2[0]
c1 = sqrt(a1 * a1 + b1 * b1)
c2 = sqrt(a2 * a2 + b2 * b2)
c = (c1 + c2) / 2
crs = c ** 7
x = 0.5 - 0.5 * sqrt(crs / (crs + 6103515625))
temp = (1 + x) * a1
c1 = sqrt(temp * temp + b1 * b1)
h1 = hue(temp, b1)
temp = (1 + x) * a2
c2 = sqrt(temp * temp + b2 * b2)
h2 = hue(temp, b2)
dL = L2 - L1
dc = c2 - c1
if c1 * c2 == 0:
dh = 0
else:
temp = round(h2 - h1, 12)
if abs(temp) <= 180:
dh = h2 - h1
else:
if temp > 180:
dh = h2 - h1 - 360
else:
dh = h2 - h1 + 360
dh = sqrt(c1 * c2) * sin(radians(dh / 2))
dh += dh
lav = (L1 + L2) / 2
cav = (c1 + c2) / 2
if c1 * c2 == 0:
htot = h1 + h2
else:
temp = abs(round(h1 - h2, 12))
if temp > 180:
if h2 + h1 < 360:
htot = h1 + h2 + 360
else:
htot = h1 + h2 - 360
else:
htot = h1 + h2
htot /= 2
T = 1 - 0.17 * cos(radians(htot - 30)) + 0.24 * cos(radians(2 * htot)) + 0.32 * cos(radians(3 * htot + 6)) - 0.20 * cos(radians(4 * htot - 63))
htotdtme = (htot / 25) - 11
xPH = 30 * exp(-htotdtme * htotdtme)
cavrs = cav ** 7
scocp = sqrt(cavrs / (cavrs + 6103515625))
xRC = scocp + scocp
lavmf = lav - 50
lavmfs = lavmf * lavmf
SL = 1 + 0.015 * lavmfs / sqrt(20 + lavmfs)
SC = 1 + 0.045 * cav
SH = 1 + 0.015 * cav * T
RT = -sin(radians(xPH + xPH)) * xRC
dL /= SL
dc /= SC
dh /= SH
dE = sqrt(dL * dL + dc * dc + dh * dh + RT * dc * dh)
return dE
def hue(a, b): # Function returns CIELAB-Hue value
c = 0
if a >= 0 and b == 0:
return 0
if a < 0 and b == 0:
return 180
if a == 0 and b > 0:
return 90
if a == 0 and b < 0:
return 270
if a > 0 and b > 0:
c = 0
elif a < 0:
c = 180
elif b < 0:
c = 360
return degrees(atan(b / a)) + c
def multi(p, l, q):
f = 0
n = []
s = p * 64
e = (p + 1) * 64
for r in xrange(s, e):
for g in xrange(256):
for b in xrange(256):
s = 1000 # smallest dist
for c in l: # compare to existing colours
d = compute_dist([r, g, b], c)
if d < s:
s = d
if s > f:
n = [r, g, b]
f = s
q.put(f)
q.put(n)
def gen_colours(start_col=[68, 68, 68]):
out = open('colour_output.txt', 'w')
l = [start_col]
if __name__ == '__main__':
q0 = multiprocessing.Queue()
q1 = multiprocessing.Queue()
q2 = multiprocessing.Queue()
q3 = multiprocessing.Queue()
for h in xrange(30): # create 30 more colours
p0 = multiprocessing.Process(target=multi, args=[0, l, q0])
p1 = multiprocessing.Process(target=multi, args=[1, l, q1])
p2 = multiprocessing.Process(target=multi, args=[2, l, q2])
p3 = multiprocessing.Process(target=multi, args=[3, l, q3])
p0.start()
p1.start()
p2.start()
p3.start()
p0.join()
p1.join()
p2.join()
p3.join()
d0 = q0.get()
d1 = q1.get()
d2 = q2.get()
d3 = q3.get()
c0 = q0.get()
c1 = q1.get()
c2 = q2.get()
c3 = q3.get()
d = [d0, d1, d2, d3]
c = [c0, c1, c2, c3]
m = max(d)
i = d.index(m)
n = c[i]
l.append(n)
out.write("[" + str(n[0]) + ", " + str(n[1]) + ", " + str(n[2]) + "]\n")
print "\nnew colour added: " + str(l)
out.close()
print "Done"
gen_colours()
</code></pre>
<p>有什么建议吗?你知道吗</p>
<p>编辑:</p>
<p>一个明显的改进是我每次都在计算找到的rgb颜色的Lab值。我添加了一个列表来存储这些的Lab值,这样就不需要每次循环都这样做了。这减少了大约1/4的时间。然而,这并不是我想要的Python性能改进。你知道吗</p>