2009-03-18 15 views
6

Potrzebuję przekształcić obrazy bitmapowe z ich 4 punktami narożnymi przeniesionymi z jednej lokalizacji do drugiej.4-punktowe obrazy transformacji

Dozwolony jest dowolny kod, który może działać w systemie Windows, C#/VB.NET, a nawet pomóc w korzystaniu ze skryptów, takich jak Paint.NET lub Photoshop. Java Advanced Imaging API brzmi obiecująco.

muszę go do systemu manipulacji zrzut ekranu, który pozwala uzyskać takie efekty:

alt text http://www.wholetomato.com/images/tour/mondoPerspectiveTrans.gif

Odpowiedz

1

łatwiejsze niż symulowanie perspektywę zakłócać korzystania manipulacji obrazu, można użyć OpenGL lub DirectX (XNA) do faktycznie wykonuj wyświetlanie perspektywy.

Renderowanie prostego kwadratu z obrazem jako mapą tekstury. Ustaw scenę, wyrenderuj ją w buforze i masz swój obraz.

Aktualizacja Okazuje się, że XNA to absurdalna biblioteka (nastawiona na tworzenie gier i nic więcej, ziewanie). Zarządzany DirectX wymaga lobotomii mózgu. OpenGL jest łatwy w użyciu, ale brakuje w nim kodu ładowania obrazu. To pozostawia nas z WPF:

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

Obraz można poprawić poprzez zmuszanie WPF w trybie anti-alias (dlaczego oh dlaczego Microsoft jesteś tak krótkowzroczne?), A nie używając szklanej siły Aero tę 1-pikselową czarną ramkę na wszystkich zrzutach ekranu (lub przez usunięcie tej 1-pikselowej granicy).

(przepraszam za długość tego kodu, ale WPF jest rozmowny 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]; 
    } 
} 

i wymagana 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> 
+0

Problem polega na tym, jak przekonwertować 4 punkty na obrót 3D? –

2

słowo kluczowe tutaj jest homography. Manolis Lourakis napisał implementację homografii GPL w języku C, która jest dostępna pod numerem here; nie będzie to jednak łatwe do przeniesienia, ponieważ opiera się na niektórych bibliotekach zewnętrznych, takich jak LAPACK.

2

Zastrzeżenie: Pracuję w Atalasoft

Jeśli są chętni, aby przejść handlowa, DotImage zdjęcie może to zrobić z QuadrilateralWarpCommand. Próbka C# Code

// 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

+0

Czy jest to osnowa afiniczna lub osnowa perspektywy? –

+0

Nie wierzę, że można to uzyskać za pomocą afinicznej osnowy (przynajmniej nie 2d) Wspieramy kilka typowych transformacji afinicznych i można stworzyć własną matrycę 2D. Nie obsługujemy transformacji 3D (to jest to, co myślę, że musiałbyś dokonać tego rodzaju transformacji za pomocą macierzy). –

Powiązane problemy