Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 31, 2015 14:32:05

leonid_10
От:
Зарегистрирован: 2010-03-28
Сообщения: 197
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

Не пойму, чего я не знаю, и, что надо узнать.
Увлекаюсь 3D. Рендер рисует открывающуюся картинку. В иных случаях за 1-10 секунд.
Не напрягаясь просчётом моделирую симуляцию рендера:

#!/usr/bin/python3
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import *
from PyQt4.QtCore import * 
import random
class Render(QWidget):
    def __init__(self, parent=None):
        super(Render, self).__init__(parent)
        self.timer = QBasicTimer()
        self.pixmap = QPixmap()
        self.pixmap.load("/home/leonid/blender/textures/green_gradient_rotate.png")
        self.step = 0;
        self.timer.start(.000000000000001, self)  
  
    def paintEvent(self, event):
        x = random.randint(1, self.pixmap.width()-1)
        y = random.randint(1, self.pixmap.height()-1)
        img = self.pixmap.toImage()
        img.setPixel(x, y,QColor(Qt.white).rgb())
        self.pixmap.convertFromImage(img, Qt.AutoColor)
        painter = QPainter(self)
        painter.drawPixmap (0, 0, img.width(), img.height(), self.pixmap)
    def timerEvent(self, event):
        if event.timerId() == self.timer.timerId():
            self.update()
        else:
            super(Render, self).timerEvent(event)
class RenderWindow(QDialog):
    def __init__(self, parent=None):
        super(RenderWindow, self).__init__(parent)
        render = Render()
        layout = QVBoxLayout()
        layout.addWidget(render)
        self.setLayout(layout)
        self.setWindowTitle("Render")
        self.resize(360, 145)
if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    win = RenderWindow()
    win.show();
    sys.exit(app.exec_())
Это тот случай, когда нужен модуль С++?



Отредактировано leonid_10 (Янв. 31, 2015 14:53:48)

Офлайн

#2 Янв. 31, 2015 17:36:41

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2757
Репутация: +  184  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

Не такой он и медленный. У меня скорость составила 8000 точек за 10 сек, что при задержке в 1мс вполне нормально.

from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import random
class Render(QWidget):
    def __init__(self, parent=None):
        super(Render, self).__init__(parent)
        self.timer = QTimer(self)
        self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.update)
        self.timer.start(1)
        self.pixmap = QtGui.QImage("/home/rodegast/0_8e0fc_8f99dbfc_XL.jpg")
        self.t1 = 0
    def paintEvent(self, event):
        x = random.randint(1, self.pixmap.width()-1)
        y = random.randint(1, self.pixmap.height()-1)
        self.pixmap.setPixel(x, y, 0)
        painter = QPainter(self)
        painter.drawImage(QtCore.QPoint(0, 0), self.pixmap)
        self.t1 += 1
        print self.t1
class RenderWindow(QDialog):
    def __init__(self, parent=None):
        super(RenderWindow, self).__init__(parent)
        render = Render()
        layout = QVBoxLayout()
        layout.addWidget(render)
        self.setLayout(layout)
        self.setWindowTitle("Render")
        self.resize(360, 145)
if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    win = RenderWindow()
    win.show();
    sys.exit(app.exec_())



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Янв. 31, 2015 17:59:26

leonid_10
От:
Зарегистрирован: 2010-03-28
Сообщения: 197
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

Rodegast
Не такой он и медленный. У меня скорость составила 8000 точек за 10 сек, что при задержке в 1мс вполне нормально.
Нет. Это не нормально. Во-первых, скорость не увеличивается с уменьшением задержки.
Во-вторых, каким образом картинка в 480 000 пикселов открывается за 5 секунд в Java или C++?
Чтобы не быть абстрактным, расскажу, что я изучаю возможность портирования кода Джавы с целью, как было сказано где-то, чтобы Питон подносил патроны…
Так вот как быть, если просчёт сцены составляет 10 секунд, а кутя это рисует 2 минуты?
Это же нонсенс, когда вычисления, задействующие сотни математических операций производятся быстрей, чем отрисовка результата:/



Офлайн

#4 Янв. 31, 2015 18:20:32

leonid_10
От:
Зарегистрирован: 2010-03-28
Сообщения: 197
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

Кстати, Ваш код не работает, ибо Python 3:
Traceback (most recent call last):
File “pyprog_timer_qt.py”, line 15, in paintEvent
x = random.randint(1, self.pixmap.width()-1)
File “/usr/lib64/python3.4/random.py”, line 218, in randint
return self.randrange(a, b+1)
File “/usr/lib64/python3.4/random.py”, line 196, in randrange
raise ValueError(“empty range for randrange() (%d,%d, %d)” % (istart, istop, width))
ValueError: empty range for randrange() (1,0, -1)



Офлайн

#5 Янв. 31, 2015 18:42:16

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2757
Репутация: +  184  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

> Кстати, Ваш код не работает, ибо Python 3:
А он и не должен.

> Во-первых, скорость не увеличивается с уменьшением задержки.
У меня увеличивается.

> Во-вторых, каким образом картинка в 480 000 пикселов открывается за 5 секунд в Java или C++?
Вот видишь какой Python быстрый. В моём примере картинка разрешением 700x800 (560 000 пикселов) отрисовывалась 800 раз в секунду, а на Java / C++ меньшее изображение рисуется аж за 5 секунд.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Янв. 31, 2015 18:42:52)

Офлайн

#6 Янв. 31, 2015 19:03:48

leonid_10
От:
Зарегистрирован: 2010-03-28
Сообщения: 197
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

Rodegast
> Кстати, Ваш код не работает, ибо Python 3:А он и не должен.> Во-первых, скорость не увеличивается с уменьшением задержки.У меня увеличивается.> Во-вторых, каким образом картинка в 480 000 пикселов открывается за 5 секунд в Java или C++?Вот видишь какой Python быстрый. В моём примере картинка разрешением 700x800 (560 000 пикселов) отрисовывалась 800 раз в секунду, а на Java / C++ меньшее изображение рисуется аж за 5 секунд.

Но, одну минуточку…
Я понимаю, что Питон медленный. Я это знал и собирался как раз изучить swig. Но, мне непонятно другое. Раз уж Вы взялись за беседу со мной
normaltest
rendering 3D scene
time taken 163.617372
------------------
(program exited with code: 0)
Press return to continue
Этот код исполнил также чистый Питон:
"""
Pure Python ray-tracer :)
taken directly from http://pastebin.com/f8f5ghjz with modifications
another good one alternative at http://www.hxa.name/minilight/
some more equations for getting intersection with other 3d geometries, https://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html#SECTION00023200000000000000
"""
#IMPORTS
from math import sqrt, pow, pi
import time
import PIL,PIL.Image
#GEOMETRIES
class Vector( object ):
    def __init__(self,x,y,z):
        self.x = x
        self.y = y
        self.z = z
    def dot(self, b):
        return self.x*b.x + self.y*b.y + self.z*b.z
    def cross(self, b):
        return (self.y*b.z-self.z*b.y, self.z*b.x-self.x*b.z, self.x*b.y-self.y*b.x)
    def magnitude(self):
        return sqrt(self.x**2+self.y**2+self.z**2)
    def normal(self):
        mag = self.magnitude()
        return Vector(self.x/mag,self.y/mag,self.z/mag)
    def __add__(self, b):
        return Vector(self.x + b.x, self.y+b.y, self.z+b.z)
    def __sub__(self, b):
        return Vector(self.x-b.x, self.y-b.y, self.z-b.z)
    def __mul__(self, b):
        assert type(b) == float or type(b) == int
        return Vector(self.x*b, self.y*b, self.z*b)     
class Sphere( object ):
    def __init__(self, center, radius, color):
        self.c = center
        self.r = radius
        self.col = color
    def intersection(self, l):
        q = l.d.dot(l.o - self.c)**2 - (l.o - self.c).dot(l.o - self.c) + self.r**2
        if q < 0:
            return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self)
        else:
            d = -l.d.dot(l.o - self.c)
            d1 = d - sqrt(q)
            d2 = d + sqrt(q)
            if 0 < d1 and ( d1 < d2 or d2 < 0):
                return Intersection(l.o+l.d*d1, d1, self.normal(l.o+l.d*d1), self)
            elif 0 < d2 and ( d2 < d1 or d1 < 0):
                return Intersection(l.o+l.d*d2, d2, self.normal(l.o+l.d*d2), self)
            else:
                return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self)    
    def normal(self, b):
        return (b - self.c).normal()
class Cylinder( object ):
    "just a copy of sphere, needs work. maybe see http://stackoverflow.com/questions/4078401/trying-to-optimize-line-vs-cylinder-intersection"
    def __init__(self, startpoint, endpoint, radius, color):
        self.s = startpoint
        self.e = endpoint
        self.r = radius
        self.col = color
    def intersection(self, l):
        q = l.d.dot(l.o - self.c)**2 - (l.o - self.c).dot(l.o - self.c) + self.r**2
        if q < 0:
            return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self)
        else:
            d = -l.d.dot(l.o - self.c)
            d1 = d - sqrt(q)
            d2 = d + sqrt(q)
            if 0 < d1 and ( d1 < d2 or d2 < 0):
                return Intersection(l.o+l.d*d1, d1, self.normal(l.o+l.d*d1), self)
            elif 0 < d2 and ( d2 < d1 or d1 < 0):
                return Intersection(l.o+l.d*d2, d2, self.normal(l.o+l.d*d2), self)
            else:
                return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self)    
    def normal(self, b):
        return (b - self.c).normal()
class LightBulb( Sphere ):
        pass
class Plane( object ):
    "infinite, no endings"
    def __init__(self, point, normal, color):
        self.n = normal
        self.p = point
        self.col = color
    def intersection(self, l):
        d = l.d.dot(self.n)
        if d == 0:
            return Intersection( vector(0,0,0), -1, vector(0,0,0), self)
        else:
            d = (self.p - l.o).dot(self.n) / d
            return Intersection(l.o+l.d*d, d, self.n, self)
class Rectangle( object ):
    "not done. like a plane, but is limited to the shape of a defined rectangle"
    def __init__(self, point, normal, color):
        self.n = normal
        self.p = point
        self.col = color
    def intersection(self, ray):
        desti = ray.dest.dot(self.n)
        if desti == 0:
                        #??
            return Intersection( vector(0,0,0), -1, vector(0,0,0), self)
        else:
            desti = (self.p - ray.orig).dot(self.n) / desti
            return Intersection(ray.orig+ray.desti*desti, desti, self.n, self)
class RectangleBox( object ):
        "not done. consists of multiple rectangle objects as its sides"
        pass
class AnimatedObject( object ):
        def __init__(self, *objs):
                self.objs = objs
        def __iter__(self):
                for obj in self.objs:
                        yield obj
        def __getitem__(self, index):
                return self.objs[index]
        def reverse(self):
                self.objs = [each for each in reversed(self.objs)]
                return self
#RAY TRACING INTERNAL COMPONENTS
class Ray( object ):
    def __init__(self, origin, direction):
        self.o = origin
        self.d = direction
class Intersection( object ):
    "keeps a record of a known intersection bw ray and obj?"
    def __init__(self, point, distance, normal, obj):
        self.p = point
        self.d = distance
        self.n = normal
        self.obj = obj
def testRay(ray, objects, ignore=None):
    intersect = Intersection( Vector(0,0,0), -1, Vector(0,0,0), None)
    for obj in objects:
        if obj is not ignore:
            currentIntersect = obj.intersection(ray)
            if currentIntersect.d > 0 and intersect.d < 0:
                intersect = currentIntersect
            elif 0 < currentIntersect.d < intersect.d:
                intersect = currentIntersect
    return intersect
def trace(ray, objects, light, maxRecur):
    if maxRecur < 0:
        return (0,0,0)
    intersect = testRay(ray, objects)       
    if intersect.d == -1:
        col = vector(AMBIENT,AMBIENT,AMBIENT)
    elif intersect.n.dot(light - intersect.p) < 0:
        col = intersect.obj.col * AMBIENT
    else:
        lightRay = Ray(intersect.p, (light-intersect.p).normal())
        if testRay(lightRay, objects, intersect.obj).d == -1:
            lightIntensity = 1000.0/(4*pi*(light-intersect.p).magnitude()**2)
            col = intersect.obj.col * max(intersect.n.normal().dot((light - intersect.p).normal()*lightIntensity), AMBIENT)
        else:
            col = intersect.obj.col * AMBIENT
    return col
def gammaCorrection(color,factor):
    return (int(pow(color.x/255.0,factor)*255),
            int(pow(color.y/255.0,factor)*255),
            int(pow(color.z/255.0,factor)*255))
#USER FUNCTIONS
class Camera:
    def __init__(self, cameraPos, zoom=50.0, xangle=-5, yangle=-5):
        self.pos = cameraPos
        self.zoom = zoom
        self.xangle = xangle
        self.yangle = yangle
def renderScene(camera, lightSource, objs, imagedims, savepath):
        imgwidth,imgheight = imagedims
        img = PIL.Image.new("RGB",imagedims)
        #objs.append( LightBulb(lightSource, 0.2, Vector(*white)) )
        print ("rendering 3D scene")
        t=time.clock()
        for x in range(imgwidth):
                #print x
                for y in range(imgheight):
                        ray = Ray( camera.pos, (Vector(x/camera.zoom+camera.xangle,y/camera.zoom+camera.yangle,0)-camera.pos).normal())
                        col = trace(ray, objs, lightSource, 10)
                        img.putpixel((x,imgheight-1-y),gammaCorrection(col,GAMMA_CORRECTION))
        print ("time taken", time.clock()-t)
        img.save(savepath)
def renderAnimation(camera, lightSource, staticobjs, animobjs, imagedims, savepath, saveformat):
        "NOTE: savepath should not have file extension, but saveformat should have a dot"
        time = 0
        while True:
                print ("time",time)
                timesavepath = savepath+"_"+str(time)+saveformat
                objs = []
                objs.extend(staticobjs)
                objs.extend([animobj[time] for animobj in animobjs])
                renderScene(camera, lightSource, objs, imagedims, timesavepath)
                time += 1
#SOME LIGHTNING OPTIONS
AMBIENT = 0.05 #daylight/nighttime
GAMMA_CORRECTION = 1/2.2 #lightsource strength?
#COLORS
red = (255,0,0)
yellow = (255,255,0)
green = (0,255,0)
blue = (0,0,255)
grey = (120,120,120)
white = (255,255,255)
purple = (200,0,200)
def origtest():
        print ("")
        print ("origtest")
        #BUILD THE SCENE
        imagedims = (1000,1000)
        savepath = "3dscene_orig.png"
        objs = []
        objs.append(Sphere( Vector(-2,0,-10), 2, Vector(*green)))      
        objs.append(Sphere( Vector(2,0,-10), 3.5, Vector(*red)))
        objs.append(Sphere( Vector(0,-4,-10), 3, Vector(*blue)))
        objs.append(Plane( Vector(0,0,-12), Vector(0,0,1), Vector(*grey)))
        lightSource = Vector(0,10,0)
        camera = Camera(Vector(0,0,20))
        #RENDER
        renderScene(camera, lightSource, objs, imagedims, savepath)
def normaltest():
        print ("")
        print ("normaltest")
        #BUILD THE SCENE
        """
        the camera is looking down on the surface with the spheres from above
        the surface is like looking down on the xy axis of the xyz coordinate system
        the light is down there together with the spheres, except from one of the sides
        """
        imagedims = (1200,1200)
        savepath = "3dscene.png"
        objs = []
        objs.append(Sphere( Vector(-4, -2, 1), 1, Vector(*red)))
        objs.append(Sphere( Vector(-2, -2, 1), 1, Vector(*blue)))
        objs.append(Sphere( Vector(-2, -4, 1), 1, Vector(*green)))
        objs.append(Plane( Vector(0,0,0), Vector(0,0,1), Vector(*grey)))
        lightSource = Vector(-2.4, -3, 2)
        camera = Camera(Vector(-19,-19,2), zoom=2.0, xangle=-30, yangle=-30)
        #RENDER
        renderScene(camera, lightSource, objs, imagedims, savepath)
def animtest():
        print ("")
        print ("falling ball test")
        #BUILD THE SCENE
        imagedims = (200,200)
        savepath = "3d_fallball"
        saveformat = ".png"
        staticobjs = []
        staticobjs.append(Sphere( Vector(-4, -2, 1), 1, Vector(*red)))
        staticobjs.append(Sphere( Vector(-2, -4, 1), 1, Vector(*green)))
        staticobjs.append(Plane( Vector(0,0,0), Vector(0,0,1), Vector(*purple)))
        animobjs = []
        fallingball = AnimatedObject(Sphere( Vector(-2, -2, 20), 1, Vector(*yellow)),
                                     Sphere( Vector(-2, -2, 15), 1, Vector(*yellow)),
                                     Sphere( Vector(-2, -2, 9), 1, Vector(*yellow)),
                                     Sphere( Vector(-2, -2, 5), 1, Vector(*yellow)),
                                     Sphere( Vector(-2, -2, 1), 1, Vector(*yellow)))
        animobjs.append(fallingball)
        lightSource = Vector(-4,-4,10)
        camera = Camera(Vector(0,0,30))
        #RENDER
        renderAnimation(camera, lightSource, staticobjs, animobjs, imagedims, savepath, saveformat)
#RUN TESTS
#origtest()
normaltest()
#animtest()
Меня интересует, почему Питон вычисляет неадекватно?
Или существует иной способ отрисовки?
Программа вычисляет цвет пиксела, затем создаёт массив, из которого формируется изображение.
Цикл, понятно, всё посчитает, затем выдаст результат.
Но, как получить результат промежуточного вычисления, который обычно отображают программы рендера?
Я пытаюсь конролировать процесс



Отредактировано leonid_10 (Янв. 31, 2015 19:10:06)

Офлайн

#7 Янв. 31, 2015 19:13:29

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2757
Репутация: +  184  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

> Я понимаю, что Питон медленный. Я это знал и собирался как раз изучить swig.

Вот ты чудак. Я тебе пишу что он быстрый, а ты думаешь что медленный. Сначала ВНИМАТЕЛЬНО прочти то что я написал, а потом уже и делай выводы про swig.

> Но, как получить результат промежуточного вычисления, который обычно отображают программы рендера?

Делай мозаичную отрисовку.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Янв. 31, 2015 19:16:06)

Офлайн

#8 Янв. 31, 2015 19:38:13

leonid_10
От:
Зарегистрирован: 2010-03-28
Сообщения: 197
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

Rodegast
> Я понимаю, что Питон медленный. Я это знал и собирался как раз изучить swig.Вот ты чудак. Я тебе пишу что он быстрый, а ты думаешь что медленный. Сначала ВНИМАТЕЛЬНО прочти то что я написал, а потом уже и делай выводы про swig.> Но, как получить результат промежуточного вычисления, который обычно отображают программы рендера?Делай мозаичную отрисовку.

Подумаю, ибо конкретного не жду, но, всё же…
Но, оно ж считает построчно….
Мозаика будет также составляться из цвета каждого отдельного пиксела…
Допустим, насчиталось их 400, я из них рисую Qimage…
Ага!
Всё-равно непонятно…
Картинка 200Х200. Посчиталось 200 пикселов, из них рисую qimage from data. Так?

Да, помоги ж ты токарю. Честное слово, я - токарь.



Отредактировано leonid_10 (Янв. 31, 2015 19:40:34)

Офлайн

#9 Янв. 31, 2015 21:11:25

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2757
Репутация: +  184  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

> Всё-равно непонятно…

Тот алгоритм который сейчас отрисовывает по таймеру 1 пиксел за 1мс (ставить очень маленькие значения задержки не имеет смысла) т.е. его максимальная скорость работы будет не более 1000 пикселей в сек и от языка это никак не зависит. При мозаичной отрисовки по таймеру будет выводится не пиксел, а фрагмент изображения и следовательно производительность будет намного выше.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Янв. 31, 2015 21:11:58)

Офлайн

#10 Фев. 1, 2015 09:48:22

leonid_10
От:
Зарегистрирован: 2010-03-28
Сообщения: 197
Репутация: +  3  -
Профиль   Отправить e-mail  

PyQt4:Что ж так медленно рисует?

Rodegast
> Всё-равно непонятно…Тот алгоритм который сейчас отрисовывает по таймеру 1 пиксел за 1мс (ставить очень маленькие значения задержки не имеет смысла) т.е. его максимальная скорость работы будет не более 1000 пикселей в сек и от языка это никак не зависит. При мозаичной отрисовки по таймеру будет выводится не пиксел, а фрагмент изображения и следовательно производительность будет намного выше.

Ясно, спасибо.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version