Я попробовал это реализовать, но все равно не работает
Он просит меня обратиться к безопасному импорту основного модуля с помощью:
if name == "main":
Но даже то, что я пробовал, все равно не работало, и я продолжал получать ошибки.
Вот новый код с реализацией ответа (не уверен, что сделал это правильно):
import multiprocessing
import tkinter as tk
from PIL import Image, ImageTk
import math, time
def process_tile(_x, _y, tile):
# (do processing on the tile)
pastTile = tile
def non_lerp(a: float, b: float, t: float) -> float:
"""Interpolation non linéaire entre a et b en fonction du temps t"""
return ((1 - t) * a)/1.5 + (t * b)/10
global lightposes
for x in range(_x): # on parcourt les pixels en colonne
for y in range(_y): # on parcourt les pixels en ligne
r = tile.getpixel((x, y))[0]
v = tile.getpixel((x, y))[1]
b = tile.getpixel((x, y))[2]
g = int((tile.getpixel((x,y))[0]+tile.getpixel((x,y))[1]+tile.getpixel((x,y))[2])/3)
total_light_intensites = []
if not(r == 0 and b == 0 and v == 0):
for i in range(len(lightposes)):
distance = math.sqrt((lightposes[i][0]-x)**2+(lightposes[i][1]-y)**2)
if distance <= lightposes[i][2]:
r+=lightposes[i][4][0]
v+=lightposes[i][4][1]
b+=lightposes[i][4][2]
pointlight_intensite = 0.0001
if ((distance/lightposes[i][2])+(lightposes[i][3])<=1):
pointlight_intensite = non_lerp(1,0.1,(distance/lightposes[i][2])+(lightposes[i][3]))
total_light_intensites.append(pointlight_intensite)
red_color,green_color,blue_color = 0,0,0
for i in range(len(total_light_intensites)):
red_color += int(total_light_intensites[i]*(r*g)/200)
green_color += int(total_light_intensites[i]*(v*g)/200)
blue_color += int(total_light_intensites[i]*(b*g)/200)
final_pixel_color = (red_color,green_color,blue_color)
tile.putpixel((x,y),final_pixel_color)
if pastTile != tile:
print(pastTile, tile)
return (_x, _y, tile)
fenetre=tk.Tk() # on créé la fenêtre
largeur=1000 # on définit les dimensions de la fenêtre
hauteur=600
toile = tk.Canvas(fenetre, width=largeur, height=hauteur) # on crée une "toile" dans la fen^tre dans laquelle on pourra dessiner
bouton = tk.Button(fenetre, text='Quitter', command = fenetre.destroy) # on crée un bouton pour quitter le jeu
toile.pack() # on place la toile dans la fenêtre
bouton.pack() # on place le bouton dans la fenêtre
fenetre.geometry('1000x700')
fenetre.configure(background='#7ace54')
fond1 = Image.open("img/fond.png") # on ouvre l'image à modifier
fond1 = fond1.resize((largeur, hauteur)) # on redimensionne l'image par rapport à la taille de la fenêtre
fond2 = fond1.copy() # on créé une copie de cette image
fond3 = ImageTk.PhotoImage(fond2, master = toile)
# on les ajoutes à la toile
main_image = toile.create_image(largeur/2,hauteur/2, image = fond3)
light_calculations= [main_image, fond3, fond2, fond1]
#--------------light calculations-----------------
lightposes=[] #1st = xpose, 2nd = ypose, 3rd = size, 4th = intensity (inversed), 5th = colour
#illumination globale
lightposes.append([500, 300, 1000, 0.85, [2,20,10]])
lightposes.append([1400, -200, 2050, 0.42, [0,170,60]])
lightposes.append([200, -1200, 1900, 0.01, [0,12,40]])
startTime = time.time()
with multiprocessing.Pool(4) as p:
jobs = []
for x in range(0, largeur, 64):
for y in range(0, hauteur, 64):
job = [x, y, fond2.crop((x, y, x + 64, y + 64))]
jobs.append(job)
for x, y, result in p.map(process_tile, jobs):
# (paste the result back in the image at x/y
light_calculations[2].paste(result, (x, y))
# (update the photoimage with the current result)
light_calculations[1] = ImageTk.PhotoImage(light_calculations[2], master = toile)
toile.itemconfigure(light_calculations[0], image = light_calculations[1])
print(time.time()-startTime)
fenetre.mainloop() # permet à la fenêtre "d'écouter" les évènements en boucle
ошибка:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\spawn.py", line 122, in spawn_main
exitcode = _main(fd, parent_sentinel)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\spawn.py", line 131, in _main
prepare(preparation_data)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\spawn.py", line 246, in prepare
_fixup_main_from_path(data['init_main_from_path'])
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\spawn.py", line 297, in _fixup_main_from_p
ath
main_content = runpy.run_path(main_path,
^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen runpy>", line 291, in run_path
File "<frozen runpy>", line 98, in _run_module_code
File "<frozen runpy>", line 88, in _run_code
File "d:\NSI\Cupidon\test multiprocess.py", line 77, in <module>
with multiprocessing.Pool(4) as p:
^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\context.py", line 119, in Pool
return Pool(processes, initializer, initargs, maxtasksperchild,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\pool.py", line 215, in __init__
self._repopulate_pool()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\pool.py", line 306, in _repopulate_pool
return self._repopulate_pool_static(self._ctx, self.Process,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\pool.py", line 329, in _repopulate_pool_st
atic
w.start()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\context.py", line 336, in _Popen return Popen(process_obj)
^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\popen_spawn_win32.py", line 46, in __init_
_
prep_data = spawn.get_preparation_data(process_obj._name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\spawn.py", line 164, in get_preparation_da
ta
_check_not_importing_main()
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\multiprocessing\spawn.py", line 140, in _check_not_importi
ng_main
raise RuntimeError('''
RuntimeError:
An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.
This probably means that you are not using fork to start your
child processes and you have forgotten to use the proper idiom
in the main module:
if __name__ == '__main__':
freeze_support()
...
The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.
To fix this issue, refer to the "Safe importing of main module"
section in https://docs.python.org/3/library/multiprocessing.html
Спасибо за помощь и желаю вам хорошего дня!






Ошибка типа: невозможно выбрать объект «_tkinter.tkapp»
Пиклинг — метод сериализации Python; все объекты, отправляемые в подпроцессы multiprocessing, должны быть разборчивыми.
Вы отправляете light_calculations, который включает в себя tkinter Canvas и tkinter PhotoImage — их нельзя выбрать (для упрощения, поскольку они относятся к объектам tkinter, которые действительны только в одном процессе).
Чтобы это исправить, вам придется изменить ситуацию, чтобы вы не отправляли в эти дочерние процессы ничего, связанного с Tkinter. (Более того, попытка putpixel над объектом в дочернем процессе в любом случае не изменит его в родительском процессе; дочерние элементы получают копии объектов.)
Если вы знаете, что подпроцессам не нужно все изображение для выполнения вычислений, я бы предложил отправлять фрагменты, например. 64х64 пикселей и получение то же самое. Это позволяет очень легко составить окончательное изображение в родительском процессе. Это можно легко сделать с помощью multiprocessing.Pool() и Map() (или imaping или imap_unordereding!) по плиткам, например.
def process_tile(x, y, tile):
... # (do processing on the tile)
return (x, y, tile)
with multiprocessing.Pool(4) as p:
jobs = []
for x in range(0, width, 64):
for y in range(0, height, 64):
job = [x, y, fond2.crop((x, y, x + 64, y + 64)]
for x, y, result in p.map(process_tile, jobs):
... # (paste the result back in the image at x/y)
... # (update the photoimage with the current result)
Обновлено: В общем, чтобы адаптировать ваш отредактированный вопрос:
def process_tile(job):
x_offset, y_offset, tile, lightposes = job
width, height = tile.size
for tile_x in range(width): # on parcourt les pixels en colonne
for tile_y in range(height): # on parcourt les pixels en ligne
x = x_offset + tile_x
y = y_offset + tile_y
r, v, b = tile.getpixel((tile_x, tile_y))
g = (r + v + b) / 3
total_light_intensites = []
for light_x, light_y, max_distance, intensity, light_color in lightposes:
distance = math.sqrt((light_x - x) ** 2 + (light_y - y) ** 2)
if distance <= max_distance:
r += light_color[0]
v += light_color[1]
b += light_color[2]
pointlight_intensite = 0.0001
if (distance / max_distance) + (intensity) <= 1:
pointlight_intensite = non_lerp(1, 0.1, (distance / max_distance) + (intensity))
total_light_intensites.append(pointlight_intensite)
red_color, green_color, blue_color = 0, 0, 0
for intensity in total_light_intensites:
red_color += int(intensity * (r * g) / 200)
green_color += int(intensity * (v * g) / 200)
blue_color += int(intensity * (b * g) / 200)
final_pixel_color = (red_color, green_color, blue_color)
tile.putpixel((tile_x, tile_y), final_pixel_color)
return (x_offset, y_offset, tile)
# ...
with multiprocessing.Pool(4) as p:
jobs = []
for x in range(0, largeur, 64):
for y in range(0, hauteur, 64):
job = [x, y, fond2.crop((x, y, x + 64, y + 64)), lightposes]
jobs.append(job)
Здравствуйте, большое спасибо за помощь, но это не работает (вероятно, ошибка с моей стороны), и я не могу понять почему: (я обновил пост)
а что такое переменная job? Мы не связываем ее с работой?
спасибо большое, благодаря вам наконец-то получилось! Я искренне желаю тебе хорошего дня и ты самый лучший! Спасибо
Я не вижу знака
if __name__ == "__main__"в вашем обновленном коде.