【问题标题】:4-point transform images4 点变换图像
【发布时间】:2010-10-14 04:52:38
【问题描述】:

我需要转换位图图像,使其 4 个角点从一个位置移动到另一个位置。

任何可以在 Windows 上运行的代码,最好是 C#/VB.NET,甚至可以帮助如何使用像 Paint.NETPhotoshop 这样的可编写脚本的程序。 Java Advanced Imaging API 听起来很有希望。

我需要它来做一个截图操作系统,它可以让你得到这样的效果:


(来源:wholetomato.com

【问题讨论】:

    标签: c# vb.net image-manipulation homography


    【解决方案1】:

    查看ImageMagick 中的Perspective warping 示例。它适用于大多数主流平台。

    【讨论】:

      【解决方案2】:

      这里的关键字是homography。 Manolis Lourakis 用 C 编写了一个 GPL 的单应性实现,可在here 获得;但是,由于它依赖于一些外部库,例如LAPACK,因此无法很容易地移植。

      【讨论】:

        【解决方案3】:

        免责声明:我在 Atalasoft 工作

        如果您愿意进行商业化,DotImage Photo 可以使用 QuadrilateralWarpCommand 完成此操作。示例 C# 代码

        // Load an image.
        AtalaImage image = new AtalaImage("test-image.jpg");
        
        // Prepare the warp positions.
        Point bottomLeft = new Point(100, image.Height - 80);
        Point topLeft = new Point(130, 45);
        Point topRight = new Point(image.Width - 60, 140);
        Point bottomRight = new Point(image.Width - 20, image.Height);
        
        // Warp the image.
        QuadrilateralWarpCommand cmd = new QuadrilateralWarpCommand(bottomLeft,
           topLeft, topRight, bottomRight, InterpolationMode.BiLinear, Color.White);
        AtalaImage result = cmd.Apply(image).Image;
        

        http://www.atalasoft.com/products/dotimage

        【讨论】:

        • 这是仿射扭曲还是透视扭曲?
        • 我不相信你可以用仿射扭曲(至少不是 2d)得到这个我们支持几种常见的仿射变换,你可以制作自己的 2D 矩阵。我们不支持 3D 转换(我认为您需要使用矩阵进行这种转换)。
        【解决方案4】:

        比使用图像处理模拟透视扭曲更容易,您可以使用 OpenGL 或 DirectX (XNA) 来实际执行透视显示。

        使用您的图像作为纹理贴图渲染一个简单的四边形。设置你的场景,渲染到一个缓冲区,你就有了你的图像。

        更新 事实证明,XNA 是一个荒谬的库(专门用于制作游戏而没有别的,打哈欠)。托管 DirectX 需要脑叶切开术。 OpenGL 易于使用,但缺少图像加载代码。剩下的就是 WPF:

        alt text http://praeclarum.org/so/persp.png

        可以通过强制 WPF 进入抗锯齿模式来改善图像(为什么哦,为什么 Microsoft 如此短视?),并且不使用 Aero 玻璃,它会在所有屏幕截图上强制使用 1 像素黑色边框(或通过删除1 像素边框)。

        (对不起,这段代码太长了,但 WPF 是一个健谈的 API。)

        public partial class Window1 : Window {
            const float ANGLE = 30;
            const float WIDTH = 8;
            public Window1() {
                InitializeComponent();
        
                var group = new Model3DGroup();
                group.Children.Add(Create3DImage(@"C:\Users\fak\Pictures\so2.png"));
                group.Children.Add(new AmbientLight(Colors.White));
        
                ModelVisual3D visual = new ModelVisual3D();
                visual.Content = group;
                viewport.Children.Add(visual);
            }
        
            private GeometryModel3D Create3DImage(string imgFilename) {
                var image = LoadImage(imgFilename);
        
                var mesh = new MeshGeometry3D();
                var height = (WIDTH * image.PixelHeight) / image.PixelWidth;
                var w2 = WIDTH / 2.0;
                var h2 = height / 2.0;
                mesh.Positions.Add(new Point3D(-w2, -h2, 0));
                mesh.Positions.Add(new Point3D(w2, -h2, 0));
                mesh.Positions.Add(new Point3D(w2, h2, 0));
                mesh.Positions.Add(new Point3D(-w2, h2, 0));
                mesh.TriangleIndices.Add(0);
                mesh.TriangleIndices.Add(1);
                mesh.TriangleIndices.Add(2);
                mesh.TriangleIndices.Add(0);
                mesh.TriangleIndices.Add(2);
                mesh.TriangleIndices.Add(3);
                mesh.TextureCoordinates.Add(new Point(0, 1)); // 0, 0
                mesh.TextureCoordinates.Add(new Point(1, 1));
                mesh.TextureCoordinates.Add(new Point(1, 0));
                mesh.TextureCoordinates.Add(new Point(0, 0));
        
                var mat = new DiffuseMaterial(new ImageBrush(image));
                mat.AmbientColor = Colors.White;
        
                var geometry = new GeometryModel3D();
                geometry.Geometry = mesh;
                geometry.Material = mat;
                geometry.BackMaterial = mat;
        
                geometry.Transform = new RotateTransform3D(
                    new AxisAngleRotation3D(new Vector3D(0,1,0), ANGLE),
                    new Point3D(0, 0, 0));
        
                return geometry;
            }
        
            public static BitmapSource LoadImage(string filename) {
                return BitmapDecoder.Create(new Uri(filename, UriKind.RelativeOrAbsolute),
                    BitmapCreateOptions.None, BitmapCacheOption.Default).Frames[0];
            }
        }
        

        以及所需的 XAML:

        <Window x:Class="Persp.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Perspective Window" Height="480" Width="640">
        <Grid>
            <Viewport3D x:Name="viewport">
                <Viewport3D.Resources>
                </Viewport3D.Resources>
                <Viewport3D.Camera>
                    <PerspectiveCamera x:Name="cam"
                          FarPlaneDistance="100"
                          LookDirection="0,0,-1"
                          UpDirection="0,1,0"
                          NearPlaneDistance="1"
                          Position="0,0,10"
                          FieldOfView="60" />
                </Viewport3D.Camera>
            </Viewport3D>
        </Grid>
        </Window>
        

        【讨论】:

        • 问题是,如何将4个点转换成3D旋转?
        猜你喜欢
        • 2020-03-06
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多