我需要将位图图像的4个角点从一个位置移动到另一个位置。
任何可以在Windows上运行的代码,最好是C#/ VB.NET,甚至可以帮助如何使用Paint.NET或Photoshop之类的可编写脚本的程序。 Java Advanced Imaging API听起来很有希望。
我需要它用于截屏操作系统,它允许你获得这样的效果:
(来源:wholetomato.com)
答案 0 :(得分:4)
查看Perspective warping中的ImageMagick示例。它适用于大多数主流平台。
答案 1 :(得分:2)
此处的关键字为homography。 Manolis Lourakis在C中写了一个GPL的单应性实现here;但是,这将无法轻松移植,因为它依赖于某些外部库,例如LAPACK。
答案 2 :(得分:2)
免责声明:我在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;
答案 3 :(得分:1)
比使用图像处理模拟透视变形更容易,您可以使用OpenGL或DirectX(XNA)来实际执行透视显示。
使用图像渲染一个简单的四边形作为纹理贴图。设置你的场景,渲染到一个缓冲区,你就有了你的图像。
更新事实证明,XNA是一个荒谬的图书馆(面向制作游戏,没有别的,打哈欠)。管理DirectX需要进行脑叶切除术。 OpenGL易于使用,但缺少图像加载代码。这让我们失去了WPF:
alt text http://praeclarum.org/so/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:
<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>