Emgu CV中与OpenCV的saturate_cast函数相对应的是什么?

4

问题

saturate_castemgucv中有什么等效的函数?

背景

我有一个Image<Bgr, byte>,我想对其中的每个像素执行一个简单的计算(顺便说一下:alpha * val + beta,其中alphabeta是传入的参数)。为了在C ++中实现这个功能,我可以这样做:

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;
    }
}

但是,正如我所说的那样,那太慢了(太慢了),所以我阅读到应该使用数据属性,这样我就可以做到这样:

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强制转换为byte,而没有执行saturate_cast

我也可以使用Convert通用方法,我有点喜欢这种方法,但问题是相同的 - 我有一个byte,我对它进行计算并得到一个double,但我需要回到byte

1个回答

3

由于我认为在 emgu cv 中没有任何预先准备好的方法,因此最终我编写了自己的方法。

根据saturate_cast 的文档,我认为(它可以产生与我尝试的图像相同的结果)在 c# 中等效于 saturate_cast 的是:

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));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接