4

質問

emgucvのsaturate_castに相当するものは何ですか?

バックグラウンド

私はを持っており、Image<Bgr, byte>その中のすべてのピクセルに対して簡単な計算を実行したいと思います(ちなみに、とはalpha * val + betaどこに渡されますか)。でこれを行うには、これを行うことができます:alphabetaC++

cv::Mat new_image = cv::Mat::zeros(image.size(), image.type());
for (int y = 0; y < image.rows; y++)
{ 
    for (int x = 0; x < image.cols; x++)
    { 
        for (int c = 0; c < 3; c++)
        {
            new_image.at<cv::Vec3b>(y,x)[c] = cv::saturate_cast<uchar>(
                alpha * (image.at<cv::Vec3b>(y,x)[c]) + beta);
        }
    }
}

Emgu CVで同じことを行うための本当に遅い方法は、次のようになります。

var newImage = image.CopyBlank();
for (int y = 0; y < image.Rows; y++)
{
    for (int x = 0; x < image.Cols; x++)
    {
        MCvScalar orig = image[y, x].MCvScalar;            
        var v0 = alpha * orig.v0 + beta;
        var v1 = alpha * orig.v1 + beta;
        var v2 = alpha * orig.v2 + beta;
        var v3 = alpha * orig.v3 + beta;
        var newCol = new Bgr();
        newCol.MCvScalar = new MCvScalar(v0, v1, v2, v3);
        newImage[y, x] = newCol;
    }
}

しかし、それは私が言うように、ひどく遅い(遅すぎる)ので、次のようなことができるようにDataプロパティを使用する必要があることを読みました。

var data = image.Data;
var newImage = image.CopyBlank();
for (int y = 0; y < image.Rows; y++)
{
    for (int x = 0; x < image.Cols; x++)
    {
        for (int c = 0; c < 3; c++)
        {
            var b = data[y, x, c];
            double ret = alpha * b + beta;      

            // Eek, now I need to saturate_cast...                          
            newImage.Data[y, x, c] = (byte)ret;
        }
    }
}

しかし、私はdoubleバイトにキャストしているだけで、を実行していないので、それは正しいことをしませんsaturate_cast

Convertジェネリックメソッドを使用することもできますが、問題は同じです。バイトがあり、それに計算を適用してdoubleがありますが、バイトに戻る必要があります。

4

1 に答える 1

3

emgu cvに事前に用意されたものはないと思うので、私は自分のメソッドを書くことになりました。

saturate_castのドキュメントに基づくと、私が試した画像と同じ結果が得られるという点で) saturate_castと同等のものc#は次のようになります。

private static byte SaturateCast(double value)
{
    var rounded = Math.Round(value, 0);

    if (rounded < byte.MinValue)
    {
        return byte.MinValue;
    }

    if (rounded > byte.MaxValue)
    {
        return byte.MaxValue;
    }

    return (byte)rounded;
}

だから私の場合、これを行うことができます。これはかなりエレガントだと思います(そして私の元の方法よりもはるかに高速です):

var newImage = image.Convert(b => SaturateCast(alpha * b + beta));
于 2013-01-23T10:15:44.630 に答える