4-точечные преобразования изображений - PullRequest
6 голосов
/ 19 марта 2009

Мне нужно преобразовать растровые изображения с перемещением их 4 угловых точек из одного места в другое.

Любой код, который может работать в Windows, предпочтительно на C # / VB.NET, даже поможет в использовании таких программ, таких как Paint.NET или Photoshop . Java Advanced Imaging API звучит обнадеживающе.

Мне это нужно для системы управления скриншотами, которая позволяет получить такие эффекты:

alt text
(источник: wholetomato.com )

Ответы [ 4 ]

4 голосов
/ 19 марта 2009

Посмотрите Перспективные деформации примеры из ImageMagick . Он доступен для большинства основных платформ.

2 голосов
/ 19 марта 2009

Ключевое слово здесь гомография . Манолис Лоракис написал реализацию гомографии под GPL на C, которая доступна здесь ; однако, это не будет легко портировать, потому что он зависит от некоторых внешних библиотек, таких как LAPACK .

2 голосов
/ 19 марта 2009

Отказ от ответственности: я работаю в Atalasoft

Если вы хотите выйти на коммерческий рынок, DotImage Photo может сделать это с помощью четырехстороннегоWarpCommand. Образец кода 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

1 голос
/ 19 марта 2009

Проще, чем имитировать искажение перспективы с помощью манипуляций с изображениями, вы можете использовать OpenGL или DirectX (XNA) для фактического отображения перспективы.

Визуализация простого четырехугольника с вашим изображением в качестве карты текстуры. Настройте свою сцену, выполните рендеринг в буфер, и у вас будет ваше изображение.

Обновление Оказывается, XNA - нелепая библиотека (ориентированная на создание игр и ничего больше, зевок). Управляемый DirectX требует лоботомии мозга. OpenGL прост в использовании, но в нем отсутствует код загрузки изображения. Это оставляет нас с WPF:

альтернативный текст 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...