C# EmguCV 调整垫子大小但保持 bounds/resolution
C# EmguCV Resize Mat but keep bounds/resolution
我已经尝试了很多东西,但是我所有的尝试都失败了。
我需要将灰色图像 (2560x1440) 调整为更低或更高的分辨率,然后我需要将边界设置为原始尺寸 (2560x1440),但将调整后的图像保持在中心。
我正在使用 EmguCV 4.3 和 Mat,我尝试了很多方法并在 Mat 构造函数和 copyTo 上使用 ROI,但没有任何效果,它总是使用调整后的边界设置新 Mat
所需示例:
源图片:(2560x1440)
50% 调整大小,但保持与源 (2560x1440) 相同的边界
300% 调整大小,但保持与源 (2560x1440) 相同的边界
我觉得应该有更优雅的方法来做到这一点,但是,我提供了两种扩展方法:
static void CopyToCenter(this Image<Gray,byte> imgScr, Image<Gray, byte> imgDst)
{
int dx = (imgScr.Cols - imgDst.Cols) / 2;
int dy = (imgScr.Rows - imgDst.Rows) / 2;
byte[,,] scrData = imgScr.Data;
byte[,,] dstData = imgDst.Data;
for(int v = 0; v < imgDst.Rows; v++)
{
for (int u = 0; u < imgDst.Cols; u++)
{
dstData[v,u, 0] = scrData[v + dy, u + dx, 0];
}
}
}
static void CopyFromCenter(this Image<Gray, byte> imgDst, Image<Gray, byte> imgScr)
{
int dx = (imgDst.Cols - imgScr.Cols) / 2;
int dy = (imgDst.Rows - imgScr.Rows) / 2;
byte[,,] scrData = imgScr.Data;
byte[,,] dstData = imgDst.Data;
for (int v = 0; v < imgScr.Rows; v++)
{
for (int u = 0; u < imgScr.Cols; u++)
{
dstData[v + dy, u + dx, 0] = scrData[v, u, 0];
}
}
}
哪个可以这样使用:
static void Main(string[] args)
{
double scaleFactor = 0.8;
Image<Gray, byte> orginalImage = new Image<Gray, byte>("Bmv60.png");
Image<Gray, byte> scaledImage = orginalImage.Resize(scaleFactor, Inter.Linear);
Image<Gray, byte> outputImage = new Image<Gray, byte>(orginalImage.Size);
if(scaleFactor > 1)
{
scaledImage.CopyToCenter(outputImage);
}
else
{
outputImage.CopyFromCenter(scaledImage);
}
}
您没有要求特定的语言,所以我希望 C# 有用。
使用 WarpAffine 对图像应用仿射变换。使用变换矩阵,您可以应用缩放和平移变换。也支持旋转,但我的示例中未涵盖。翻译值也可以是负数。
WrapAffine 方法有更多参数供您使用。
public void Test()
{
var img = new Mat("Bmv60.png", ImreadModes.Grayscale);
Mat upscaled = GetContentScaled(img, 2.0, 0.5, 0, 0);
upscaled.Save("scaled1.png");
Mat downscaled = GetContentScaled(img, 0.5, 0.5, 0, 0);
downscaled.Save("scaled2.png");
}
private Mat GetContentScaled(Mat src, double xScale, double yScale, double xTrans, double yTrans, Inter interpolation = Inter.Linear)
{
var dst = new Mat(src.Size, src.Depth, src.NumberOfChannels);
var translateTransform = new Matrix<double>(2, 3)
{
[0, 0] = xScale, // xScale
[1, 1] = yScale, // yScale
[0, 2] = xTrans + (src.Width - src.Width * xScale) / 2.0, //x translation + compensation of x scaling
[1, 2] = yTrans + (src.Height - src.Height * yScale) / 2.0 // y translation + compensation of y scaling
};
CvInvoke.WarpAffine(src, dst, translateTransform, dst.Size, interpolation);
return dst;
}
我已经尝试了很多东西,但是我所有的尝试都失败了。 我需要将灰色图像 (2560x1440) 调整为更低或更高的分辨率,然后我需要将边界设置为原始尺寸 (2560x1440),但将调整后的图像保持在中心。
我正在使用 EmguCV 4.3 和 Mat,我尝试了很多方法并在 Mat 构造函数和 copyTo 上使用 ROI,但没有任何效果,它总是使用调整后的边界设置新 Mat
所需示例:
源图片:(2560x1440)
50% 调整大小,但保持与源 (2560x1440) 相同的边界
300% 调整大小,但保持与源 (2560x1440) 相同的边界
我觉得应该有更优雅的方法来做到这一点,但是,我提供了两种扩展方法:
static void CopyToCenter(this Image<Gray,byte> imgScr, Image<Gray, byte> imgDst)
{
int dx = (imgScr.Cols - imgDst.Cols) / 2;
int dy = (imgScr.Rows - imgDst.Rows) / 2;
byte[,,] scrData = imgScr.Data;
byte[,,] dstData = imgDst.Data;
for(int v = 0; v < imgDst.Rows; v++)
{
for (int u = 0; u < imgDst.Cols; u++)
{
dstData[v,u, 0] = scrData[v + dy, u + dx, 0];
}
}
}
static void CopyFromCenter(this Image<Gray, byte> imgDst, Image<Gray, byte> imgScr)
{
int dx = (imgDst.Cols - imgScr.Cols) / 2;
int dy = (imgDst.Rows - imgScr.Rows) / 2;
byte[,,] scrData = imgScr.Data;
byte[,,] dstData = imgDst.Data;
for (int v = 0; v < imgScr.Rows; v++)
{
for (int u = 0; u < imgScr.Cols; u++)
{
dstData[v + dy, u + dx, 0] = scrData[v, u, 0];
}
}
}
哪个可以这样使用:
static void Main(string[] args)
{
double scaleFactor = 0.8;
Image<Gray, byte> orginalImage = new Image<Gray, byte>("Bmv60.png");
Image<Gray, byte> scaledImage = orginalImage.Resize(scaleFactor, Inter.Linear);
Image<Gray, byte> outputImage = new Image<Gray, byte>(orginalImage.Size);
if(scaleFactor > 1)
{
scaledImage.CopyToCenter(outputImage);
}
else
{
outputImage.CopyFromCenter(scaledImage);
}
}
您没有要求特定的语言,所以我希望 C# 有用。
使用 WarpAffine 对图像应用仿射变换。使用变换矩阵,您可以应用缩放和平移变换。也支持旋转,但我的示例中未涵盖。翻译值也可以是负数。
WrapAffine 方法有更多参数供您使用。
public void Test()
{
var img = new Mat("Bmv60.png", ImreadModes.Grayscale);
Mat upscaled = GetContentScaled(img, 2.0, 0.5, 0, 0);
upscaled.Save("scaled1.png");
Mat downscaled = GetContentScaled(img, 0.5, 0.5, 0, 0);
downscaled.Save("scaled2.png");
}
private Mat GetContentScaled(Mat src, double xScale, double yScale, double xTrans, double yTrans, Inter interpolation = Inter.Linear)
{
var dst = new Mat(src.Size, src.Depth, src.NumberOfChannels);
var translateTransform = new Matrix<double>(2, 3)
{
[0, 0] = xScale, // xScale
[1, 1] = yScale, // yScale
[0, 2] = xTrans + (src.Width - src.Width * xScale) / 2.0, //x translation + compensation of x scaling
[1, 2] = yTrans + (src.Height - src.Height * yScale) / 2.0 // y translation + compensation of y scaling
};
CvInvoke.WarpAffine(src, dst, translateTransform, dst.Size, interpolation);
return dst;
}