Найти - Пользователи
Полная версия: Торможения таймера при зарисовки цветом
Начало » GUI » Торможения таймера при зарисовки цветом
1 2 3 4
zeze
reclosedev
Покажите код загрузки и отображения картинок.

Вот код:

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui, uic
import math
import os
import struct
bf = []
dir = os.path.join(os.getcwd(), "file")
phi = 0.0
im = QtGui.QImage(720, 492, QtGui.QImage.Format_ARGB32)
class ld(QtGui.QDialog):
    def __init__(self, parent=None):
        super(ld, self).__init__(parent)
        self.ui = uic.loadUi("ld.ui", self)
        self.connect(self.ui.radioButton_2, QtCore.SIGNAL("clicked()"), self.MyClickRect)
        self.timer = QtCore.QTimer()
        self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.MyTimer)
        self.timer.setInterval(5000)
        self.timer.start()
    def paintEvent(self, QPaintEvent):
        if self.ui.radioButton_2.isChecked():
            painterRect = QtGui.QPainter(self)
            painterRect.setBrush(QtGui.QColor('black'))
            painterRect.drawRect(50, 50, 720, 492)
            self.MyDraw()
    def MyClickRect(self):
        self.update()
    def MyRadianToGradus(self, phiedit):
        gradus = phiedit * 360/(2*math.pi)
        return gradus
    def MyGradusToRadian(self, phiedit):
        radian = phiedit * 2*math.pi / (360)
        return radian
    def MyTimer(self):
        global dir
        global phi
        global bf
        global im
        if self.ui.checkBox_4.isChecked():
            os.chdir(dir)
            try:
                fp = open('1.dat', 'rb')
            except IOError:
                print "Cannot open file read!"
            fp.seek(0, 2)
            size = fp.tell()
            fp.seek(size - (492*720), 0)
            for j in range(0, 720, 1):
                bf.append([])
                for i in range(491, -1, -1):
                    bf[j].append(struct.unpack("B", fp.read(1))[0])
            for j in range(0, 720, 1):
                for i in range(491, -1, -1):
                    im.setPixel(j, i, QtGui.QColor(bf[j][-i], bf[j][-i], bf[j][-i], 255).rgba())
        self.update()
        if self.ui.radioButton_2.isChecked():
            if int((self.MyRadianToGradus(phi)+0.5)*720)/360 < 720:
                phi += self.MyGradusToRadian(6.0)
            else:
                phi = self.MyGradusToRadian(6.0)
    def MyDraw(self):
        global im
        global bf
        Tochka = QtGui.QPainter()
        Tochka.begin(self)
        Tochka.translate(50, 50)
        Tochka.drawImage(0, 0, im, 0, 0, int((2*self.MyRadianToGradus(phi))+0.5), 492)
        Tochka.end()
        self.update()
if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = ld()
    window.show()
    sys.exit(app.exec_())

Время выполнения рисования картинки не соответствует таймеру, как я понял это из-за кода:

for j in range(0, 720, 1):
       bf.append([])
       for i in range(491, -1, -1):
              bf[j].append(struct.unpack("B", fp.read(1))[0])
for j in range(0, 720, 1):
       for i in range(491, -1, -1):
             im.setPixel(j, i, QtGui.QColor(bf[j][-i], bf[j][-i], bf[j][-i], 255).rgba())

Пыталя уменьшить циклы, смог уменьшить, только на два цикла.

for j in range(0, 720, 1):
       for i in range(491, -1, -1):
              bf = struct.unpack("B", fp.read(1))
              im.setPixel(j, i, QtGui.QColor(bf[0], bf[0], bf[0], 255).rgba())

Всё равно тормоза. Как я понял надо полностью избавится от циклов.
Но как это сделать?
А может ещё какие возможности есть?
reclosedev
Зачем загружать картинку на каждом шаге анимации? Загрузите QImage один раз, например, при старте программы, и потом используйте ее. Если их несколько, загрузите несколько.
Тогда проблема
zeze
надо полностью избавится от циклов.
должна исчезнуть.

zeze
А может ещё какие возможности есть?
Есть варианты с загрузкой с помощью PIL или numpy + PIL. Зависит от формата файла.
И все это понадобится, только если на каждый кадр нужна будет новая картинка.

Ну и не удержусь, по коду:
- global im -> self.im = …
- self.ui.checkBox_4 -> self.ui.checkBoxNeedToLoadImage (или какое-нибудь разумное имя)
- 492, 720 -> что за магические числа? заведите константы, типа WIDTH = 492, или параметры
- MyGradusToRadian(), MyRadianToGradus() -> math.radians(), math.degrees()
zeze
reclosedev
Зачем загружать картинку на каждом шаге анимации? Загрузите QImage один раз, например, при старте программы, и потом используйте ее. Если их несколько, загрузите несколько.

Ксожалению я не могу так сдеоать, так как картинок очень много и поэтому для каждого файла создавать свою переменную я считаю не верным. В добавок картинки прорисовываются не сразу, а по частям в зависимости от таймера.

reclosedev
492, 720 -> что за магические числа?

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

reclosedev
параметры
- MyGradusToRadian(), MyRadianToGradus() -> math.radians(), math.degrees()

Я не знал о таких встроенных методах. Большое спасибо.

reclosedev
Есть варианты с загрузкой с помощью PIL или numpy + PIL. Зависит от формата файла.

Попробую прочесть про эти возможности и использовать одну из этих двух.
reclosedev
zeze
Ксожалению я не могу так сдеоать, так как картинок очень много и поэтому для каждого файла создавать свою переменную я считаю не верным.
Из кода этого не понять. Очень много - это сколько? Если все не уберутся в память, создайте список (или dequeue c maxlen) из 5-10 штук и обновляйте его при необходимости.

zeze
В добавок картинки прорисовываются не сразу, а по частям в зависимости от таймера.
Я так понимаю, это эффективнее сделать методами painter'a (отображением региона или сокрытием) а не частичной загрузкой.

zeze
Тут ничего могического, это значения по высоте и ширене они в каждом двоичном файле не изменны.
Ничего магического - только для вас, для других это не очевидно. И если это значение изменится, придется везде искать его и менять.
zeze
reclosedev
Очень много - это сколько?

Около 900, но может быть и за 1000.

reclosedev
И если это значение изменится, придется везде искать его и менять.

Эти значения ни когда не меняются.
zeze
reclosedev
Очень много - это сколько?

Около 900, но может быть и за 1000.

reclosedev
И если это значение изменится, придется везде искать его и менять.

Эти значения ни когда не меняются.
reclosedev
zeze
Около 900, но может быть и за 1000.
Т.е. на каждом шаге анимации загружается новая картинка?
Скиньте штук 5 файлов, попробовать можно кое-что без PIL.
zeze
reclosedev
Т.е. на каждом шаге анимации загружается новая картинка?

Если картинка первая, то на каждом шаге таймера картинка рисуеться всё больше и больше и на 60 шаге картинка полностью прорисовано.
Если первая и вторая картинка, то на каждом шаге таймера вторая картинка рисуется, а первая картинка стирается, и на 60 шаге стирается полностью первая картинка и полностью появляется вторая картинка.

и так далее.

reclosedev
Скиньте штук 5 файлов, попробовать можно кое-что без PIL.

Ксожалению эти файлы я не могу передать, так как это закрытая информация.
Впринципе там хранятся, только значения модели RGB. То есть каждый байт файл это значение RGB.
R = 1-й байт
G = 1-й байт
B = 1-й байт
На следующей стадии цикла будет
R = 2-й байт
G = 2-й байт
B = 2-й байт
и так далее

Так, что достаточно с эмулировать разные цвета и можно тестировать.
reclosedev
Если правильно понял формат:
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
 
try:
    import numpy
except ImportError:
    numpy = None
 
class BinImage(QtGui.QImage):
    def __init__(self, path, width=720, height=492):
        with open(path, "rb") as fp:
            fp.seek(-width * height, 2)
            self._data = self.load_transposed(fp, width, height)
        QtGui.QImage.__init__(self, self._data,
                              width, height, self.Format_Indexed8)
     
    if numpy is not None: 
         # быстрая версия, с использованием numpy, >120x быстрее попиксельного
        def load_transposed(self, fp, width, height):
            a = numpy.fromfile(fp, dtype=numpy.uint8)
            a = numpy.flipud(a.reshape((height, width), order='F'))
            return a.tostring()
    else:  
        # если numpy не установлен, 20х быстрее попиксельного
        # думаю, можно сделать еще быстрее
        def load_transposed(self, fp, width, height, next=next):
            data = [[0] * width for _ in xrange(height)]
            it = iter(fp.read(width * height))
            for x in xrange(width):
                for y in xrange(height - 1, -1, -1):
                    data[y][x] = next(it)
            return ''.join(''.join(row) for row in data)
Использование
img = BinImage("img.dat")
Нужно проверить на реальных данных.
Тут используется numpy, он очень сильно ускоряет. Если numpy нет, есть другой метод, но возможно, есть способ написать его оптимальнее. В любом случае, numpy не обойти.

zeze
Если картинка первая, то на каждом шаге таймера картинка рисуеться всё больше и больше и на 60 шаге картинка полностью прорисовано.
Если первая и вторая картинка, то на каждом шаге таймера вторая картинка рисуется, а первая картинка стирается, и на 60 шаге стирается полностью первая картинка и полностью появляется вторая картинка.
Значит, нужно загружать две картинки один раз в 60 кадров, хранить их в переменных/атрибутах и использовать их. А сам переход делать средствами painter'а. Это уже сами.
zeze
reclosedev
Если правильно понял формат:

Большое спасибо, всё верно!
Не могли бы Вы пояснить немного вот этот участок кода.

if numpy is not None: 
         # быстрая версия, с использованием numpy, >120x быстрее попиксельного
        def load_transposed(self, fp, width, height):
            a = numpy.fromfile(fp, dtype=numpy.uint8)
            a = numpy.flipud(a.reshape((height, width), order='F'))
            return a.tostring()

Зачем строка?

return a.tostring()

Зачем это делать, так как двухмерный массив значений построен уже?

И если возможно можно немного переделать пример таким образом, что бы вывод “a” был сразу, а не передавался бы для выполнения в класс.

То есть хотелось бы, что бы было, что то на подобее:

if numpy is not None: 
         # быстрая версия, с использованием numpy, >120x быстрее попиксельного
        def load_transposed(self, fp, width, height):
            a = numpy.fromfile(fp, dtype=numpy.uint8)
            a = numpy.flipud(a.reshape((height, width), order='F'))
            # Заполнение объект QImage значениями "a" без циклов или сам вывод "a" буз циклов

Ппошу прощения, я не очень ещё хорошо разбираюсь в Python и я запутался. Извините, если я побеспокоил Вас.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB