создание потока Python в обратном вызове, а не окончание - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь сохранить буферы изображений в формате .png с помощью Python API в Blender (но это в основном только вопрос Python) Я пытаюсь ускорить процесс создания потока для сохранения изображения, и функция, которая создает поток, вызывается из обработчика обратного вызова, который активируется всякий раз, когда обновляется трехмерный экран, вот полный код (его немного грязно):

import base64, io, os, bgl, gpu, bpy, threading, time, sys
import numpy as np
from gpu_extras.presets import draw_texture_2d
from PIL import Image
import multiprocessing.pool as mpool

finalPath = bpy.context.scene.render.filepath + "hithere.png"


WIDTH = 1920
HEIGHT = 1080



offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT)

def draw2():
    global finalPath
    global array
    global WIDTH
    global HEIGHT
    global needsSaving
    context = bpy.context
    scene = context.scene

    view_matrix = scene.camera.matrix_world.inverted()

    projection_matrix = scene.camera.calc_matrix_camera(
        context.depsgraph, x=WIDTH, y=HEIGHT)

    offscreen.draw_view3d(
        scene,
        context.view_layer,
        context.space_data,
        context.region,
        view_matrix,
        projection_matrix)

    bgl.glDisable(bgl.GL_DEPTH_TEST)
    draw_texture_2d(offscreen.color_texture, (0, -125), WIDTH, HEIGHT)

    buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4)
    bgl.glReadBuffer(bgl.GL_BACK)
    bgl.glReadPixels(0, -125, WIDTH, HEIGHT, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)


    needle = threading.Thread(target=saveIt,args=[buffer, finalPath, WIDTH, HEIGHT])
    needle.daemon = True
    needle.start()
  ####  thread.start_new_thread(saveIt,(buffer, finalPath, WIDTH, HEIGHT))



def coby(scene):
    frame = scene.frame_current
    folder = scene.render.filepath
    myFormat = "png"#scene.render.image_settings.renderformat.lower()
    outputPath = os.path.join(folder, "%05d.%s" % (frame, myFormat))
    global finalPath
    finalPath = outputPath



h = bpy.types.SpaceView3D.draw_handler_add(draw2, (), 'WINDOW', 'POST_PIXEL')
bpy.app.handlers.frame_change_pre.clear()
bpy.app.handlers.frame_change_pre.append(coby)


def saveIt(buffer, path, width, height):
    array = np.asarray(buffer, dtype=np.uint8)
    myBytes = array.tobytes()
    im = Image.frombytes("RGBA",(width, height), myBytes)
    rawBytes = io.BytesIO()
    im.save(rawBytes, "PNG")
    rawBytes.seek(0)
    base64Encoded = base64.b64encode(rawBytes.read())
    txt =  "data:image/png;base64," + base64Encoded.decode()
    f = open(finalPath, "wb")
    f.write(base64.decodebytes(base64Encoded))
    f.close()

на самом деле это работает, за исключением того, что когда я играю на временной шкале в blender (который вызывает обратный вызов frame_pre, а также обратный вызов 3D view-refresh (хотя и не уверен, в каком порядке), большинство моих изображений заменяются, за исключением некоторых , как видно на этом скриншоте: [! [введите описание изображения здесь] [1]] [1]

Первоначально у меня были все изображения с синей плоскостью, затем я пропустил сценарий через поток, и он заменил почти все из них, за исключением того, что некоторые из изображений с синей плоскостью все еще остаются (по-видимому, с произвольным интервалом). Это работало нормально, если я вызываю .join () сразу после создания потока или вообще не использую поток, но, похоже, поток - единственный способ заставить его работать намного быстрее.

Я искал, как использовать потоки с очередями и пулами ( Как использовать многопроцессорную обработку Python Pool.map в цикле , Что случилось с thread.start_new_thread в питоне 3 , Как сделать фоновый, неблокирующий цикл ввода в python? , Создание потоков в python ),

SO: Почему не заканчиваются все темы? [1]: https://i.stack.imgur.com/nJCwH.png .................

...