1

私はガールフレンドの学士論文のために失明プログラムを書きたいと思っていました。Xミリ秒間画像を表示し、短い「ちらつき画像」(この場合は灰色のみ)を表示し、最初の画像とはわずかに異なる画像を表示します。そしてまたちらつき画像。

その後、すべてが最初から始まります。グラフィックアーティファクトだけがあります。キャンバス/ QGraphicsView は、私が思うに十分に速くリフレッシュしないので、リフレッシュ中の「線」です。

画像表示時間:70ms、フリッカー時間:30ms。したがって、100 ミリ秒 = 1 秒あたり 10 FPS です。GPUを使わなくてもこれは可能だと思いました。しかし、そうではないようです。

GPU を回避するためにダブル バッファリングなどを使用できますか? または、QGLを使用する必要がありますか? その約1メガバイトの画像。

私はそれらを一度ロードして、私が思うにそれらを表示します。シーンで間違ったことをしているのかもしれません。

ソースコードを添付します。何かアイデアがあるかもしれません。

敬具 :)

#ifndef PICTURES_H
#define PICTURES_H

#include <QMainWindow>
#include <QImage>
#include <QPixmap>
#include <QGraphicsPixmapItem>
#include <iostream>
#include <QDir>
#include <QGraphicsScene>
#include <QDebug>
#include <QTimer>


namespace Ui {
class pictures;
}

class pictures : public QMainWindow
{
    Q_OBJECT

public:
    explicit pictures(QWidget *parent = 0);
    ~pictures();

    void loadPics();
    void showPics();

public slots:
    void stopClicked();
    void clearPictures();
    void timePassed();
    void changeImage();
    void changeImageGrey();

private:
    int counter;
    int image_counter;
    int stop_time;
    Ui::pictures *ui;
    QVector<int> times;
    QTimer* timer;
    QTimer* timerImageChange;
    QTimer* timerGrey;

    int imageChangeTime;
    int greyTime;

    QVector<QGraphicsPixmapItem*> images;
    QGraphicsScene* scene;
    QGraphicsScene* scene_grey;
    QGraphicsPixmapItem* item1;
};

#endif // PICTURES_H


#include "pictures.h"
#include "ui_pictures.h"

pictures::pictures(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::pictures), times()
{
    counter = 1;
    stop_time = 0;
    image_counter = 0;
    timer = new QTimer(this);
    timerGrey = new QTimer(this);
    timerImageChange = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timePassed()));
    connect(timerImageChange, SIGNAL(timeout()), this, SLOT(changeImageGrey()));
    connect(timerGrey, SIGNAL(timeout()), this, SLOT(changeImage()));

    greyTime = 200;
    imageChangeTime = 500;


    qDebug() << "Hello im here in pictures";

    ui->setupUi(this);
    this->loadPics();
    connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(stopClicked()));
    connect(ui->pushButtonNext, SIGNAL(clicked()), this, SLOT(clearPictures()));

    timer->start(10);
    timerImageChange->start(imageChangeTime);
}

pictures::~pictures()
{
    delete ui;
}

void pictures::loadPics()
{
    qDebug() << QDir::toNativeSeparators((QDir::current().absolutePath() + QDir::separator () + "debug" + QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"1.jpg"));
    //QImage imageOne(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" + QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"1.jpg"));
    //QImage imageTwo(QString("./pics/")+counter+"/2.png");
    //QImage imageThree(QString("./pics/")+counter+"/3.jpg");
    //QImage imageFour(QString("./pics/")+counter+"/2.png");

    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"1.jpg")));
    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"2.jpg")));
    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"3.jpg")));
    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"4.jpg")));


    //QGraphicsPixmapItem* item1( QPixmap::fromImage(imageOne));
    item1 = images[image_counter];
    //QGraphicsPixmapItem item2( QPixmap::fromImage(imageTwo));
    //QGraphicsPixmapItem item3( QPixmap::fromImage(imageThree));
    //QGraphicsPixmapItem item4( QPixmap::fromImage(imageFour));
    scene = new QGraphicsScene;
    scene_grey = new QGraphicsScene;

    int maximum = item1->boundingRect().width() > item1->boundingRect().height() ? item1->boundingRect().width() : item1->boundingRect().height();
    int dimension_width  = ui->graphicsView->rect().width();
    int dimension_height = ui->graphicsView->rect().height();

    //int biggest_canvas_dimension = (((float)item1->boundingRect().width())/dimension_width) > (((float)item1->boundingRect().height())/dimension_height) ? dimension_width : dimension_height;
    int biggest_canvas_dimension = dimension_width > dimension_height ? dimension_width : dimension_height;

    if(maximum > ui->graphicsView->rect().width() || maximum > ui->graphicsView->rect().height())
    {
        dimension_width = (int) (item1->boundingRect().width() * ((float)(biggest_canvas_dimension )/maximum));
        dimension_height = (int) (item1->boundingRect().height() * ((float)(biggest_canvas_dimension)/maximum));
        item1->setPixmap(item1->pixmap().scaled(dimension_width,dimension_height));

        qDebug() << "Width: " << dimension_width << " Height " << dimension_height << " Pic High" << item1->boundingRect().height();
    }

    //item1->setPixmap(item1->pixmap().scaled(QSize(ui->graphicsView->rect().width(), ui->graphicsView->rect().height())));
    scene->setSceneRect(ui->graphicsView->rect());
    scene->addItem(item1);

    scene_grey->setSceneRect(ui->graphicsView->rect());
    scene_grey->addItem(images[1]);


    ui->graphicsView->setScene(scene);
    ui->graphicsView->adjustSize();

    //ui->graphicsView->show();


}

void pictures::timePassed()
{
    stop_time += 10;
}

void pictures::stopClicked()
{
    timerImageChange->stop();
    timerGrey->stop();
    times.append(stop_time);
    ui->pushButtonStop->setEnabled(false);
    ui->pushButtonNext->setEnabled(true);
    counter++;
    qDebug() << "Time: " << stop_time;

    stop_time = 0;
    timer->stop();
}

void pictures::clearPictures()
{
    scene->deleteLater();
    images.clear();
    loadPics();
    ui->pushButtonStop->setEnabled(true);
    ui->pushButtonNext->setEnabled(false);
    timer->start(10);
    timerImageChange->start(imageChangeTime);
}

void pictures::changeImageGrey()
{
    timerGrey->start(greyTime);
    timerImageChange->stop();
    image_counter = (image_counter+1)%4;

    //scene_grey->removeItem(scene_grey->items().at(0));
    //scene_grey->addItem(images[image_counter]);

    scene->removeItem(scene->items().at(0));
    scene->addItem(images[image_counter]);



    /*int maximum = item1->boundingRect().width() > item1->boundingRect().height() ? item1->boundingRect().width() : item1->boundingRect().height();
    int dimension_width  = ui->graphicsView->rect().width();
    int dimension_height = ui->graphicsView->rect().height();

    int biggest_canvas_dimension = dimension_width > dimension_height ? dimension_width : dimension_height;

    if(maximum > ui->graphicsView->rect().width() || maximum > ui->graphicsView->rect().height())
    {
        dimension_width = (int) (item1->boundingRect().width() * ((float)(biggest_canvas_dimension )/maximum));
        dimension_height = (int) (item1->boundingRect().height() * ((float)(biggest_canvas_dimension)/maximum));
        item1->setPixmap(item1->pixmap().scaled(dimension_width,dimension_height));
    }*/
    //scene->setSceneRect(ui->graphicsView->rect());

    //ui->graphicsView->setScene(scene_grey);

}

void pictures::changeImage()
{
    timerImageChange->start(imageChangeTime);
    timerGrey->stop();
    image_counter = (image_counter+1)%4;

    qDebug() << "    item1 = images[" + QString::number(image_counter) + "]";

    scene->removeItem(scene->items().at(0));

    item1 = images[image_counter];

    //qDebug() << QDir::toNativeSeparators((QDir::current().absolutePath() + QDir::separator () + "debug" + QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+ QString::number(image_counter+1) +".jpg"));


    int maximum = item1->boundingRect().width() > item1->boundingRect().height() ? item1->boundingRect().width() : item1->boundingRect().height();
    int dimension_width  = ui->graphicsView->rect().width();
    int dimension_height = ui->graphicsView->rect().height();

    int biggest_canvas_dimension = dimension_width > dimension_height ? dimension_width : dimension_height;

    if(maximum > ui->graphicsView->rect().width() || maximum > ui->graphicsView->rect().height())
    {
        dimension_width = (int) (item1->boundingRect().width() * ((float)(biggest_canvas_dimension )/maximum));
        dimension_height = (int) (item1->boundingRect().height() * ((float)(biggest_canvas_dimension)/maximum));
        item1->setPixmap(item1->pixmap().scaled(dimension_width,dimension_height));
    }

    //item1->setPixmap(item1->pixmap().scaled(QSize(ui->graphicsView->rect().width(), ui->graphicsView->rect().height())));
    //scene->setSceneRect(ui->graphicsView->rect());
    scene->addItem(item1);
    //ui->graphicsView->setScene(scene);

    //ui->graphicsView->setScene(scene);
    //ui->graphicsView->adjustSize();

    //ui->graphicsView->show();

}
4

1 に答える 1

3

モニターのリフレッシュ レートが 60 Hz の場合、各画像は 16 ミリ秒に 1 回再描画されることに注意してください。30 ミリ秒のような正確なタイミングで描画することはできません。16.666 ミリ秒間隔でのタイミングのみが可能です。少なくとも Windows では、モニターに表示される画像がいつ変化するかを簡単に知ることはできません。たとえば、コードが 10 ミリ秒間画像を表示する場合、画像が表示されるか、表示されないかのどちらかです。画像を 25 ミリ秒表示すると、画像が 1 回 (16.666 ミリ秒) または 2 回 (33.333 ミリ秒) 表示されます。

本当に正確なタイミングが必要な場合は、モニターの垂直同期情報を使用して描画のタイミングを調整できる OpenGL を使用することをお勧めします。

描画中に表示される線は、おそらく破れています。モニターの垂直同期情報を使用することでも、それを回避できます。

また、Qt のタイマーを使用して 10 ミリ秒間隔をカウントしています。それはうまくいきません。タイムアウトは少なくとも 10 ミリ秒ですが、正確に 10 ミリ秒であるとは限りません。実際にはそれ以上であるため、100 回のタイムアウトの合計時間はおそらく約 1100 ミリ秒です。オペレーティングシステムによっては、さらに多くのことができます。Windows では、デフォルトのタイマー分解能は 16 ミリ秒です。次に、100 回のタイムアウトを合計すると、約 1700 ミリ秒になります。timeBeginPeriodを使用してタイマーの解像度を変更できます。

より正確なタイミングを得るには、待機する期間のタイマーを開始します。70 ミリ秒後に何かをしたい場合は、10 ミリ秒のタイムアウトを 7 回行う代わりに、タイマー間隔を 70 ミリ秒に変更します。

于 2012-06-17T12:03:10.477 に答える