我的問題是我有一個2D參數樣條的列表,我需要一個更高效的方法將它們渲染到圖像網格上。每個樣條由一系列點,線半徑/厚度(以像素爲單位)和不透明度確定。高效計算圖像上所有像素的樣條曲線距離
我想到的原始實現與討論的問題here類似,它會遍歷圖像上的每個像素,找到到曲線的最小距離,然後在最小距離低於所需距離時標記像素半徑。
import math
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate
import time
from PIL import Image
class GenePainter(object):
def __init__(self, source):
self.source = source
def render(self):
output = np.zeros(self.source.shape, dtype=np.float32)
Ny, Nx = output.shape[0], output.shape[1]
#x = np.array([5, 10, 15, 20, 5, 5])
#y = np.array([5, 5, 20, 15, 10, 30])
x = np.array(np.random.random(4) * 128, dtype=np.float32)
y = np.array(np.random.random(4) * 128, dtype=np.float32)
sx, sy = spline(x, y, 1000)
t = time.time()
for yi in xrange(Ny):
for xi in xrange(Nx):
d = min_distance(sx, sy, xi, yi)
if d < 10.: # radius
output[yi, xi, :] = np.array([1, 1, 0, 0.5])
print time.time() - t
# t = time.time()
# for _ in xrange(100):
# plt.plot(sx, sy, label='spline', linewidth=10, aa=False, solid_capstyle="round")
# print time.time() - t
plt.imshow(output, interpolation='none')
plt.show()
def score(self, image):
return np.linalg.norm(self.source - image, 2)
def spline(x, y, n):
if x.ndim != 1 or y.ndim != 1 or x.size != y.size:
raise Exception()
t = np.linspace(0, 1, x.size)
sx = scipy.interpolate.interp1d(t, x, kind='cubic')
sy = scipy.interpolate.interp1d(t, y, kind='cubic')
st = np.linspace(0, 1, n)
return sx(st), sy(st)
def min_distance(sx, sy, px, py):
dx = sx - px
dy = sy - py
d = dx ** 2 + dy ** 2
return math.sqrt(np.amin(d))
def read_image(file):
image_raw = Image.open(file)
image_raw.load()
# return np.array(image_raw, dtype=np.float32)
image_rgb = Image.new('RGB', image_raw.size)
image_rgb.paste(image_raw, None)
return np.array(image_rgb, dtype=np.float32)
if __name__ == "__main__":
# source = read_image('ML129.png')
source = np.zeros((256, 256, 4), dtype=np.float32)
p = GenePainter(source)
p.render()
的問題是,每個花鍵256×256 RGBA圖像上繪製需要因爲通過各像素,這是我的目的太慢未經優化的迭代的〜1.5秒。我計劃在單張圖像上使用多達約250個樣條,並且可以處理高達約100張圖像,總共可以處理大約1000個作業,所以我正在尋找任何可以減少減少我的計算時間。
我研究過的另一種方法是將所有樣條曲線繪製到PyPlot圖上,然後將最終圖像轉儲到可用於其他計算的numpy數組,這似乎運行得更快, 〜0.15秒來繪製100個樣條。
plt.plot(sx, sy, label='spline', linewidth=10, aa=False, solid_capstyle="round")
的問題是,線寬參數似乎與像素對應我的屏幕上,而不是像素的圖像(在256×256格)的數量,所以當我調整窗口的大小,規模線條隨窗口改變,但線寬保持不變。我希望曲線寬度對應於256 x 256網格上的像素。
我寧願通過尋找一種方法來大大優化第一個數值實現,而不是PyPlot繪圖來解決這個問題。我還研究了對圖像進行縮減採樣(僅計算像素子集而不是每個像素的距離),但即使使用10%像素,每個樣條線的0.15秒仍然太慢。
非常感謝您的幫助和建議!
你能把這個代碼運行的例子嗎?這意味着無需編輯即可複製,粘貼和運行它。在你的代碼中有很多未定義的東西,這意味着我們必須搗鼓,添加import語句,定義變量並做出假設來運行它,看看發生了什麼。我在這裏做了一個開始:http://pastebin.com/k8Mfukv1 – YXD
該代碼現在應該可以運行!謝謝參觀。 – kjzhang92