0

私は、そのとんでもないパンとズーム効果を備えたスライドショー アプリを作成しています。私はパイゲームを使用しています。

したがって、メイン ディスプレイはリアルタイム 30fps+ であり、新しい画像をロードする必要があるときにスタッタリングしたくありません。これには 1/30 秒以上かかります。

そこで、いくつかの並列プロセスを使用して画像を準備し、クラスのインスタンスであるこれらのオブジェクトをメイン プロセスにフィードしたいと考えました。

スレッド化とマルチプロセスで試しました。スレッド化は「機能」しますが、まだびくびくしています (私はpythonのせいです) - スレッドがビジー状態になると、全体が遅くなります! そのため、コードは実行されましたが、継続的にスムーズな表示を可能にするという目標を達成できませんでした。

しかし、メインプロセスから受け取った準備済みイメージでメソッドを呼び出すとすぐに、マルチプロセスのセグメンテーション違反が発生します。(pygame parachute)パイプ通信とキュー通信を試しましたが、どちらも同じ問題が発生します。メソッドは、への呼び出しを行うまで実行されます

sized = pygame.transform.scale(self.image, newsize )

次に、セグメンテーション違反です。このクラスには、メイン プロセスからの依存関係はありません。

pygame はマルチプロセッシングが好きではないのですか? 互換性のある別の方法はありますか?スレッド化メソッドの実行を停止する可能性のあるセカンダリ スレッドを「ナイス」にする方法はありますか?

どんな助けでも大歓迎です。もっと多くのコードを投稿できてうれしいです。コメントで質問してください。

前もって感謝します!

編集

これは私ができる限り短いです。下部のコンストラクターで jpeg ファイルへの 3 つのパスを指定する必要があります

#!/usr/bin/env python2
import pygame
import sys
import time
import re
import os
import pickle
from random import randrange, shuffle
from multiprocessing import Process, Pipe
import Queue


class Img:
    """The image objects I need to pass around"""
    def __init__(self, filename=None):
        image = pygame.image.load(filename).convert()
        self.image = pygame.transform.scale(image, (640,480))

    def getSurface(self):
        """Get a surface, blit our image onto it in right place."""
        surface = pygame.Surface((640,480))
        # xxx this next command fails
        sized = pygame.transform.scale(self.image, (640,480))
        surface.blit(sized, (0,0))
        return surface

class Floaty:
    """demo"""
    def __init__(self, fileList):
        self.fileList = fileList
        pygame.init()
        self.screen = pygame.display.set_mode((640,480))

        # open the first image to get it going
        self.img = Img(self.fileList.pop())

        # Set up parallel process for opening images
        self.parent_conn, child_conn = Pipe()
        self.feeder = Process(target=asyncPrep, args=(child_conn,))
        self.feeder.start()

    def draw(self):
        """draw the image"""
        # collect image ready-prepared by other process
        if self.parent_conn.poll():
            self.img = self.parent_conn.recv()
            print ("received ", self.img)

        # request new image
        self.parent_conn.send(self.fileList.pop())

        self.screen.blit(self.img.getSurface(), (0, 0))
        pygame.display.flip()

def asyncPrep(conn):
    """load up the files"""

    while True:
        if conn.poll(1):
            filename = conn.recv()
            print ("doing ", filename)
            img = Img(filename)
            conn.send(img)


if __name__ == '__main__':
    fileList = ['/path/to/a.jpg', 'path/to/b.jpg', 'path/to/c.jpg']
    f = Floaty(fileList)
    clock = pygame.time.Clock()
    while 1:
        f.draw()
        clock.tick(4);

これを実行すると (Python 2.7.6)、次のようになります。

('doing ', '/path/to/a.jpg')
('received ', <__main__.Img instance at 0x7f2dbde2ce60>)
('doing ', '/path/to/b.jpg')
Fatal Python error: (pygame parachute) Segmentation Fault
zsh: abort (core dumped)
4

1 に答える 1

0

マルチプロセッシングを使用してこれを解決しました。Img クラスで画像を文字列バッファーにロードし、プロパティにpostReceive格納してから、画像プロパティに格納されているサーフェスにそれをロードするメソッドを追加しました。

このメソッドは、子からオブジェクトをpostReceive受け取った後、親プロセスによって呼び出されます。Img

したがって、子によって作成されたオブジェクトは、pygame-y にバインドされません。

    self.imageBuffer = pygame.image.tostring(
      pygame.transform.scale(image, (640,480)),
      'RGB')

次に、新しいメソッドImgは次のとおりです。

def: postReceive(self):
    self.image = pygame.image.frombuffer( self.imagebuffer, 'RGB' )

ここに呼び出しを追加します。

    # collect image ready-prepared by other process
    if self.parent_conn.poll():
        self.img = self.parent_conn.recv().postReceive()
        print ("received ", self.img)
于 2015-03-03T09:20:22.763 に答える