saturate_cast中emgucv的等效内容是什么?
我有一个Image<Bgr, byte>
,我希望对其中的每个像素执行简单的计算(顺便提一下:alpha * val + beta
传递alpha
和beta
。要在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;
}
}
但就像我说的那样,这只是非常缓慢(太慢),所以我read应该使用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转换为byte而不执行saturate_cast
。
我也可以使用我更喜欢的Convert泛型方法,但问题是一样的 - 我有一个byte,我将计算应用到它并且有一个{{3但我需要回到double。
答案 0 :(得分:2)
我最后编写了自己的方法,因为我认为emgu cv中没有任何预先设定的内容。
基于saturate_cast的文档,我认为(因为它与我尝试过的图像产生相同的结果)相当于{{1}中的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;
}