私はメモリの問題に苦しんでいます。何かを見逃したと思います。誰かが私が理解している/間違っていることを指摘してくれれば、非常に感謝しています.
私がしたいこと
私のGUIはメインスレッドで実行されます。別のスレッド T で計算を開始しています。この計算の結果は、一連の opencv イメージです。計算中にGUIに表示したい。
どうすればいいのかわからない
- 計算スレッドを起動します。
- 新しい画像が計算されたら、それを QImage に変換し、カスタム QEvent でラップして、GUI に投稿します。
- ヒープ メモリのみを使用します。
実装方法
私の計算スレッドでは、新しい画像の準備ができたら:
std::shared_ptr<cv::Mat> cvimRGB = std::shared_ptr<cv::Mat>(new cv::Mat);
cv::Mat cvimBGR;
cv::Mat cvim = MyNewComputedImage;
cvim.convertTo(cvimBGR,CV_8UC3);
cv::cvtColor(cvimBGR,*cvimRGB,cv::COLOR_BGR2RGB);
std::shared_ptr<QImage> qim = std::shared_ptr<QImage>(
new QImage((uint8_t*) cvimRGB->data,cvimRGB->cols,cvimRGB->rows,cvimRGB->step,QImage::Format_RGB888));
ImageAddedEvent* iae = new ImageAddedEvent(qim,i);
QCoreApplication::postEvent(gui, iae);
私のイベントハンドラーで:
bool mosaicage::event(QEvent * e){
if (e->type() == ImageAdded) {
ImageAddedEvent* ie = dynamic_cast<ImageAddedEvent*>(e);
QImage qim(*(ie->newImage));
QPixmap pm(QPixmap::fromImage(qim));
auto p = scene.addPixmap(pm);
images_on_display.push_back(p);
return true;
} else {
return QWidget::event(e);
}
}
私のカスタムイベントは次のように定義されています:
class ImageAddedEvent: public QEvent {
public:
ImageAddedEvent();
~ImageAddedEvent();
ImageAddedEvent(std::shared_ptr<QImage> im, int i);
std::shared_ptr<QImage> newImage;
int index;
};
何が起こるのですか
デバッグモードでは、ディスプレイにがらくたが表示されます。リリース モードで、アクセス違反エラーが発生します。cv::Mat を qimage に変換する部分については、変更していないのでかなり自信があります。以前は計算スレッドから表示を更新していましたが、よりよく学びました。ただし、機能しました(クラッシュしなかった場合)。
どのように修正したか
問題は、私がそれを構築したcv::Matによって担当されたQImageが指すメモリにありました。他の誰かが管理するデータを使用して QImage を構築するこの方法を維持したい場合は、データを有効に保つ必要があります。したがって、cv::Mat をカスタム イベントに移動しました。
class ImageAddedEvent: public QEvent {
public:
ImageAddedEvent();
~ImageAddedEvent();
ImageAddedEvent(cv::Mat im, int i);
QImage newImage;
cv::Mat cvim;
int index;
};
イベントのコンストラクターを変更して、QImage を cv::Mat データで初期化しました。
ImageAddedEvent::ImageAddedEvent(cv::Mat cvimRGB, int i) : QEvent(ImageAdded),
index(i),
cvim(cvimRGB)
{
newImage = QImage((uint8_t*) cvim.data,cvim.cols,cvim.rows,cvim.step,QImage::Format_RGB888);
}
そして今、cv::Mat をイベント コンストラクターに渡すだけです。
cv::Mat cvimBGR,cvimRGB;
cv::Mat cvim = MyNewImage;
cvim.convertTo(cvimBGR,CV_8UC3);
cv::cvtColor(cvimBGR,cvimRGB,cv::COLOR_BGR2RGB);
ImageAddedEvent* iae = new ImageAddedEvent(cvimRGB,i);
QCoreApplication::postEvent(gui, iae);
et voilà、再び、助けてくれてありがとう!