18

私は、基本的に、幾何学的形状を(「左のキャンバス」内の)多くの小さな三角形にカットし、いくつかの単純な数学的変換を三角形の束に適用し、それらを新しい構成で再描画するプログラムを設計しました。以下のスクリーンキャプチャを参照してください。

スクリーンキャップ1

これらの三角形を描くために、私はを使用しますQPainter::drawPolygon。右側の各三角形は左側の三角形に対応しているので、それを描くためにどの色を使用したいかがわかります。

これまでのところ、結構です。これよりもはるかに多くの三角形を描画したとしても(形状をカットするためにはるかに小さな三角形を使用する場合)、これは十分に高速です。

プログラムに機能を追加しました。単純な三角形の代わりに、画像から抽出した三角形を描画できます。次のスクリーンキャプチャを参照してください。

ここに画像の説明を入力してください

問題は、私がこれを行う方法が遅すぎることです。これが私がそれをする方法です:

  1. 私はすべての三角形を駆け抜けます
  2. 三角形ごとに、表示される各ピクセルの座標を計算します。
  3. これらのピクセルのそれぞれについて、画像上の対応するピクセルの座標を計算し(これは簡単な数学演算です)、そのピクセルの色を取得します。
  4. とを使用QPainter::setPen(QColor)QPainter::drawPoint(QPoint)てピクセルを描画します。

私はQtでのプログラミングに不慣れで、グラフィックスについて何も知らないので、これが私が思いついたものです。問題は、それが「許容できないほど」遅すぎることです(paintEventプレーンな三角形の場合の0.01秒と比較して、各キャンバスの所要時間は約0.15秒です)。

何が起こっているのかを理解するためにプロファイラーを実行しましたが、キャンバスウィジェットpaintEvent

  1. 時間の58%はQPainter::drawPoint
  2. 時間の27%がQPainter::setPen

QPainter::drawPoint複雑すぎて遅いようです。特定の色のピクセルを印刷したいだけです。それだけです。

私は自分の問題の解決策を見つけたかもしれません:QImageキャンバスに表示させたいもの全体を表す(キャンバスウィジェットのメンバー変数として)を保存し、それpaintEventをピクセルごとに完全に定義してから、一度に描画します私の最後paintEventQPainter::drawImage。これははるかに高速になるというヒントがあります。しかし、コードを書き直す前に、それが本当にやりたいことなのかどうかを知りたいと思います。

私はあなたが死ぬのを退屈させなかったことを望みます!洞察に感謝します。

4

5 に答える 5

7

OpenGLは、画像(テクスチャ)座標マッピングを非常にうまく実行します。おそらく、何らかの形式のOpenGLを使用したいと思うでしょう。Qtには、OpenGLへのバインドがあります。

于 2012-09-28T13:15:10.037 に答える
4

非OpenGlソリューション:

宛先画像にはRGBバッファーを使用します。以前と同じように、最初の3つのステップを実行します。位置とピクセルの色を見つけたら、それをこのバッファに設定します。次に、

QImage::QImage ( uchar * data, int width, int height, Format format )

前のバッファに基づいてイメージを構築します。それはあなたが提供したソリューションに近く、あなたが現在持っているものよりもはるかに高速になります。

于 2012-09-28T13:46:28.133 に答える
3

これを行う1つの方法は、QGraphicsScene / QGraphicsViewコンボの代わりに、QGLWidgetから継承するクラスを使用することです。残念ながら、OpenGLの学習曲線は少し急なものから始まります。ただし、この種の操作用に最適化されたグラフィックカード上で直接発生するため、非常に高速になります。
画像を読み込みますQGLWidget::bindTexture()
画像内のポイントを三角形メッシュに関連付け、それらすべてをグラフィックカードに送信します。OpenGLのレガシーバージョン(私の意見では新しいAPIよりも使いやすい)では、次のようになります。

glEnable(GL_TEXTURE_2D);

glBegin(GL_TRIANGLES);
for (int ii=0;ii<triangle.size();++ii) {
  for (int jj=0;jj<3;++jj) {
    glTexCoord2d(triangle[ii].tex[jj][0],triangle[ii].tex[jj][1]);
    glVertex2d(triangle[ii].point[jj[0],triangle[ii].point[jj][1]);
  }
}
glEnd();

triangle三角形の頂点と関連するマッピングを画像に保持して作成したデータ構造はどこにありますか。グラフィックカードがピクセル補間を処理します。

于 2012-09-28T13:31:16.860 に答える
1

OpenGL以外の別のオプションは、OpenCLを使用することです。これはあなたにとってより簡単かもしれません。入出力ビットマップをグラフィックカードにメモリマップし、1つの三角形を処理する小さなカーネルをCで記述してから、各三角形のカーネル実行をキューに入れる必要があります。これは、CPU上のシングルコアの100倍の速度で動作します。

ここにOpenCLホストAPIのQtラッパーがあります:

http://doc.qt.digia.com/opencl-snapshot/index.html

于 2012-09-28T14:13:00.837 に答える
0

別のアプローチは、ラスターペイントエンジン内ですでに効率的に実装されているクリッピングと変換を活用することです。2つの三角形間の変換が、3x3の拡張変換行列を使用して表現できる限り、ターゲットペインターに設定してから、ソースイメージ全体をターゲットに描画するだけです。ターゲットの三角形を埋めるためにクリップされて変換されます。プロファイリングに利点がある場合は、画像全体ではなく、ソース三角形の境界を描画することもできます。

これを並列化して、CPUコアと同じ数の三角形を並列に処理することができます。

于 2014-09-22T09:45:35.590 に答える