2009-03-18 8 views
6

Ho bisogno di trasformare le immagini bitmap con i loro 4 punti d'angolo spostati da una posizione all'altra.Immagini di trasformazione a 4 punti

Qualsiasi codice che può essere eseguito su Windows, C#/VB.NET preferibilmente, anche aiuto su come utilizzare programmi con script come Paint.NET o Photoshop sarebbe accettato. L'API Java Advanced Imaging sembra promettente.

ho bisogno di un sistema di manipolazione screenshot, che consente di ottenere tali effetti:

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

risposta

1

Più facile che la simulazione di un punto di vista distorto utilizzando la manipolazione delle immagini, è possibile utilizzare OpenGL o DirectX (XNA) a effettivamente eseguire la visualizzazione prospettica.

Renderizza un quad semplice con l'immagine come la mappa texture. Imposta la tua scena, renderizza in un buffer e hai la tua immagine.

Aggiornamento Si scopre che XNA è una biblioteca ridicola (orientata verso la realizzazione di giochi e nient'altro, sbadiglio). Managed DirectX richiede una lobotomia cerebrale. OpenGL è facile da usare, ma manca di codice di caricamento dell'immagine. Questo ci lascia con WPF:

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

L'immagine potrebbe essere migliorata forzando WPF in modalità anti-alias (perché oh perché Microsoft sei così miope?), E non usando il vetro Aero quale le forze quel bordo nero da 1 pixel su tutti gli screenshot (o rimuovendo quel bordo da 1 pixel).

(Scusate per la lunghezza di questo codice, ma WPF è un'API loquace.)

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]; 
    } 
} 

E il XAML richiesta:

<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

Il problema è, come si convertono i 4 punti in una rotazione 3D? –

2

La parola chiave qui è homography. Manolis Lourakis ha scritto un'implementazione di omografia GPL in C disponibile here; tuttavia, questo non sarà possibile effettuare il porting molto facilmente perché si basa su alcune librerie esterne come LAPACK.

2

Disclaimer: io lavoro a Atalasoft

Se siete disposti ad andare commerciale, DotImage foto può farlo con il QuadrilateralWarpCommand. Esempio di codice 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

+0

Si tratta di un curvaccio affine o di una curvatura prospettica? –

+0

Non credo che tu possa ottenere questo risultato con un Distorsione Affine (almeno non 2d) Supportiamo diverse trasformazioni affini comuni e puoi creare la tua matrice 2D. Non supportiamo le trasformazioni 3D (che è ciò che penso che avresti bisogno di fare questo tipo di trasformazione usando una matrice). –