【问题标题】:C# EmguCV Resize Mat but keep bounds/resolutionC# EmguCV 调整垫子大小但保持边界/分辨率
【发布时间】:2020-10-12 21:28:39
【问题描述】:

我尝试了很多事情,但我所有的尝试都失败了。 我需要将灰度图像 (​​2560x1440) 的大小调整为更低或更高的分辨率,然后我需要将边界设置为原始大小 (2560x1440) 但将调整大小的图像保持在中心。

我正在使用 EmguCV 4.3 和 Mat,我在 Mat 构造函数和 copyTo 上尝试了许多方法和使用 ROI,但没有任何效果,它总是使用调整大小的边界设置新 Mat

所需示例:

源图片:(2560x1440)

50% 调整大小,但保持与源相同的边界 (2560x1440)

300% 调整大小,但保持与源相同的边界 (2560x1440)

【问题讨论】:

    标签: image opencv resize emgucv


    【解决方案1】:

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

    【讨论】:

    • 这真是太棒了,而且速度惊人!正是我所需要的 :) 我知道这样的功能,经过这么多搜索和调整代码示例,我看到没有人使用它,非常感谢!如果有人觉得有用,我会为 Emgu 提供一些扩展:github.com/sn4k3/UVtools/blob/master/UVtools.Core/Extensions/…
    • @TiagoConceição 当我说应该有更优雅的方式时,这就是我的意思:)
    【解决方案2】:

    我觉得应该有更优雅的方式来做到这一点,但是,我提供了两种扩展方法:

    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# 有用。

    【讨论】:

    • 您的代码有效,但我的应用程序有一个问题,使用的调整大小因子可以在 X、Y 中不同,这意味着图像可以调整为 X=50% 和 Y=150%例子。在以前的库(ImageSharp)上可以在另一个库的顶部绘制图像,我可以选择我想要甚至负值的插入点,并且图像被绘制在另一个恰到好处的顶部,但是在 emgucv 中我正在苦苦挣扎
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多