5

非常によく似たトピックを見つけました: opencv cv::Mat を qimage に変換する方法、しかしそれは私の問題を解決しません。

cv::Mat を QImage に変換する関数があります

QImage cvMatToQImg(cv::Mat& mat)
{
    cv::Mat rgb;
    if(mat.channels()==1)
    {
        cv::cvtColor(mat,rgb,CV_GRAY2BGR);
        cv::cvtColor(rgb,rgb,CV_BGR2BGRA);
        QImage temp = QImage((unsigned char*)(rgb.data), rgb.cols, 
                              rgb.rows,QImage::Format_ARGB32 );

        QImage returnImage = temp.copy();
        return returnImage;
}

それは私にとってはうまくいきますが、もっと効率的にしたいと思っています。最初: 2 つの cvtColor 関数を次のように変更する理由:

cv::cvtColor(mat,rgb,CV_GRAY2BGRA)

失敗する

QImage returnImage = temp.copy() 

セグメンテーションあり。

次に、QImage のコピーを削除する方法。単純に一時画像を返すと、segfault が発生します。

そこで他の最適化を行うことができますか? 非常によく使う機能なので、できるだけ速くしたいです。

4

3 に答える 3

4

独自のソリューションを展開するのが最も簡単な場合があります。以下は、グレーからRGBA形式に移行するための現在のOpenCV実装です。

template<typename _Tp>
struct Gray2RGB
{
    typedef _Tp channel_type;

    Gray2RGB(int _dstcn) : dstcn(_dstcn) {}
    void operator()(const _Tp* src, _Tp* dst, int n) const
    {
        if( dstcn == 3 )
            for( int i = 0; i < n; i++, dst += 3 )
            {
                dst[0] = dst[1] = dst[2] = src[i];
            }
        else
        {
            _Tp alpha = ColorChannel<_Tp>::max();
            for( int i = 0; i < n; i++, dst += 4 )
            {
                dst[0] = dst[1] = dst[2] = src[i];
                dst[3] = alpha;
            }
        }
    }

    int dstcn;
};

実際のcvtColor呼び出しが発生する場所は次のとおりです。

    case CV_GRAY2BGR: case CV_GRAY2BGRA:
        if( dcn <= 0 ) dcn = 3;
        CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
        _dst.create(sz, CV_MAKETYPE(depth, dcn));
        dst = _dst.getMat();

        if( depth == CV_8U )
            CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));

このコードは、ライブラリのcolor.cppファイルに含まれていimgprocます。

ご覧のとおり、呼び出しでdstCnパラメーターを設定していないため、デフォルトで。になります。グレーからBGRAに直接移行するには、4に設定します。OpenCVのデフォルトの色の順序はBGRであるため、正しく見えるようにカラーチャネルを交換する必要があります(OpenCV関数から画像データを取得すると仮定します)。したがって、おそらく上記の例に従うか、ここで回答を使用して、独自のコンバーターを実装する価値があるかもしれません。cvtColordcn = 3dstCnypnos

また、OpenCVをQtと統合する方法に関する他の回答もご覧ください。

于 2012-06-13T15:22:50.583 に答える
4

問題の解決策は効率的ではありません。特に、リンク先の他の質問に投稿したコードよりも効率的ではありません。

問題は、グレースケールからカラー、または RGBA に変換する必要があることです。この会話が必要になるとすぐに、当然、データのコピーが必要になります。

私のソリューションは、グレースケールとカラーの間、および cv::Mat と QImage の間の変換を同時に行います。だからこそ、それはあなたが得ることができる最も効率的なものです.

あなたのソリューションでは、最初に変換を試みてから、OpenCV データの周りに QImage を直接構築して、2 番目のコピーを保存します。ただし、指し示すデータは一時的なものです。関数を終了するとすぐに、cv::Mat は関連付けられたメモリを解放するため、QImage 内でも有効ではなくなります。事前に cv::Mat の参照カウンターを手動で増やすこともできますが、後でメモリ リークが発生する可能性があります。

最終的には、きれいな方法で解決した方がよい問題に対して、汚い解決策を試みることになります。

于 2012-06-13T16:08:30.610 に答える
1

問題は、cv::Mat と QImage の両方のデータが必ずしも連続しているとは限らないことです。opencv の新しいデータ行は 32 ビット境界で開始するため (QImage については不明 - システムに依存していると思います)、行が正確に 4 バイトの倍数でない限り、メモリ ブロックをコピーできません。

Qt でこの 24 ビット イメージを出力する方法を参照してください。

于 2012-06-13T15:51:19.863 に答える