Один из моих первых проектов, реализованных в python, делает моделирование перколяции в Монте-Карло. Код постоянно рос. Первой частью была визуализация перколяции палочки. В области ширины * длина заданной плотности (палочки/площади) прямых палок с определенной длиной нанесены со случайными начальными координатами и направлением. Поскольку я часто использую gnuplot, я написал сгенерированные (x, y) начальные и конечные координаты в текстовый файл, чтобы потом gnuplot их.Непосредственно «отрезки» сегментов линии до массива numpy
Я нашел here хороший способ анализа данных изображения с использованием scipy.ndimage.measurements. Изображение читается с помощью ndimage.imread в оттенках серого. Получившийся массив numpy далее сводится к логическим значениям, поскольку меня интересуют только соединения между разными палочками. Затем полученные кластеры анализируются с помощью ndimage.measurements. Это позволяет мне узнать, есть ли пути, которые соединяются с одной стороны на другую или нет. Здесь приведен минимальный пример.
import random
import math
from scipy.ndimage import measurements
from scipy.ndimage import imread
import numpy as np
import matplotlib.pyplot as plt
#dimensions of plot
width = 10
length = 8
stick_length = 1
fig = plt.figure(frameon=False)
ax = fig.add_axes([0, 0, 1, 1])
fig.set_figwidth(width)
fig.set_figheight(length)
ax.axis('off')
file = open("coordinates.txt", "w")
for i in range (300):
# randomly create (x,y) start coordinates in channel and direction
xstart = width * random.random() # xstart = 18
ystart = length * random.random() # ystart = 2
# randomly generate direction of stick from start coordinates and convert from GRAD in RAD
dirgrad = 360 * random.random()
dirrad = math.radians(dirgrad)
# calculate (x,y) end coordinates
xend = xstart + (math.cos(dirrad) * stick_length)
yend = ystart + (math.sin(dirrad) * stick_length)
# write start and end coordinates into text file for gnuplot plotting
file.write(str(i) + ":\t" + str(xstart) + "\t" + str(ystart) + "\t" + str(dirgrad) + ":\t" + str(xend) + "\t" + str(yend) + "\n")
file.write(str(i) + ":\t" + str(xend) + "\t" + str(yend) + "\n\n")
# or plot directly with matplotlib
ax.plot([xstart,xend],[ystart,yend],"black", lw=1)
fig.savefig("testimage.png", dpi=100)
# now read just saved image and do analysis with scipy.ndimage
fig1, ax1 = plt.subplots(1,1)
img_input = imread("testimage.png", flatten = True) # read image to np.ndarray in grey scales
img_bw = img_input < 255 # convert grey scales to b/w (boolean)
labeled_array, num_clusters = measurements.label(img_bw) #labeled_array: labeled clusters in array, num_clusters: number of clusters
area = measurements.sum(img_bw, labeled_array, index=np.arange(labeled_array.max() + 1)) # area of each cluster
areaImg = area[labeled_array] # label each cluster with labelnumber=area
cax = ax1.imshow(areaImg, origin='upper', interpolation='nearest', cmap = 'rainbow')
cbar = fig1.colorbar(cax)
fig1.savefig("testimage_analyzed.png")
Хотя это работает в основном только тонкие моделирования методом Монте-Карло с 1000 итераций для большего числа различных плотностей рукояти в конечном итоге работает 8 часов или больше. Отчасти это связано с тем, что созданные изображения & массивов довольно велики, и тысячи палочек построены для более высоких плотностей. Причина в том, что я хочу моделировать диапазон геометрий (например, длина между 500 и 20000 пикселей), одновременно сводя к минимуму ошибку из-за пикселизации.
Я думаю, лучший способ - не использовать данные изображения и рассматривать его как векторную проблему, но я понятия не имею, как начать алгоритм. И многие соединения могут привести к большим массивам данных.
Пребывание с описанным выше способом очевидно, что запись данных в файл и повторное чтение его не очень эффективны. Поэтому я ищу способы ускорить это. В качестве первого шага я использовал matplotlib для создания изображения, но, по крайней мере, при построении каждой палочки с помощью отдельного сюжетного вызова это до 10 раз медленнее для большего количества палочек. Создание списка палочных координат в массиве и построение полного списка с помощью одного сюжетного вызова может ускорить его, но все же оставляет узкое место в написании и чтении изображения.
Можете ли вы указать мне на эффективный метод прямого генерации массива numping типа boolean, представляющего черно-белое изображение палочек? Может ли построить список координат и каким-то образом преобразовать фигуру в массив? Я также нашел это интересное discussion, где линии нанесены на изображение PIL. Может ли это быть быстрее, чем matplotlib?
Спасибо за указание мне в этом направлении. Не использовал cython, прежде чем я впервые реализовал его в чистом питоне, который уже дал улучшение. Теперь я изо всех сил пытаюсь запустить ваш код cython. Загрузили полный пакет и сохранили в каталоге «cython». При запуске – MrCyclophil
Наконец-то он запущен под Linux. Не знаете, где можно получить Visual Studio 2010 Express, чтобы запустить его под Windows. – MrCyclophil
Просто для информации, если у кого-то также есть проблемы с установкой C-компилятора на Win8.1 64bit. Для Python 3.5 это стало намного проще. Просто загрузите и установите бесплатную версию Visual Studio 2015 Community Edition. [Этот блог] (http://blog.ionelmc.ro/2014/12/21/compiling-python-extensions-on-windows/) дает хорошее резюме для Python 2.7, 3.4 и 3.5. – MrCyclophil