4点变换图像

我需要将位图图像的4个角点从一个位置移动到另一个位置。

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

我需要它用于截屏操作系统,它允许你获得这样的效果:

替代文字http://sofzh.miximages.com/c%23/mondoPerspectiveTrans.gif

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

这里的关键字是单应性 。 Manolis Lourakis在C中写了一个GPL的单应性实现,可以在这里找到 ; 但是,由于它依赖于某些外部库(如LAPACK) ,因此无法轻松移植。

免责声明:我在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

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

使用图像渲染一个简单的四边形作为纹理贴图。 设置场景,渲染到缓冲区,然后获得图像。

更新事实certificateXNA是一个荒谬的图书馆(面向制作游戏而不是其他任何东西,哈欠)。 管理DirectX需要脑叶切除术。 OpenGL易于使用,但缺少图像加载代码。 这让我们失去了WPF:

alt text http://sofzh.miximages.com/c%23/persp.png

可以通过强制WPF进入反别名模式来改善图像(为什么微软为什么这么近视?),并且不使用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: