Как обрезать изображение, используя 4 угла (x, y) в imagemagick C # - PullRequest
0 голосов
/ 22 января 2019

Я использую afroge ранее, чтобы обрезать изображение, используя 4 угла изображения, как показано ниже, и оно работает нормально, и единственная проблема с Aforge - не удается обработать большие изображения, такие как 40000 X 34000, используя растровое изображение, поэтому я хочу проверить imageMagick для обрезки используя 4 угла, но кажется, что он принимает x, y и ширину и высоту изображения, чтобы обрезать, но это не будет работать, если изображение наклонено или не прямолинейно.

Я пробовал ImageMagick, используя приведенный ниже код, но он занимает только одно положение x, y, а также высоту и ширину, что приведет к неправильному обрезанному изображению

Point location = new Point();
location.X = topleft.X;
location.Y = topleft.Y;        
Size ze = new Size();
ze.Height = width;
ze.Height = height;
Rectangle rt = new Rectangle(location, ze);
MagickGeometry mgeomentory = new MagickGeometry(rt);
originalImage.Crop(mgeomentory);

aforge code - существующий код - отлично работает

List<AForge.IntPoint> corners = new List<AForge.IntPoint>();
corners.Add(new AForge.IntPoint(topleft.X, topleft.Y));
corners.Add(new AForge.IntPoint(topright.X, topright.Y));
corners.Add(new AForge.IntPoint(bottomright.X, bottomright.Y));
corners.Add(new AForge.IntPoint(bottomleft.X, bottomleft.Y));

SimpleQuadrilateralTransformation filter = new 
SimpleQuadrilateralTransformation(corners, width, height);
Bitmap newImage = filter.Apply(originalImage);

Ответы [ 3 ]

0 голосов
/ 23 января 2019

Я переписал пример кода jcupitt на C #.В этом примере используется net-vips , привязка C # для libvips .

static void Main(string[] args)
{
    if (args.Length != 8)
    {
        Console.WriteLine(
            "Usage: [input] [output] " +
            "[topLeftX] [topLeftY] " +
            "[topRightX] [topRightY] " +
            "[bottomRightX] [bottomRightY]");
        return;
    }

    Image image = Image.NewFromFile(args[0]);
    string outFilename = args[1];
    int topLeftX = int.Parse(args[2]);
    int topLeftY = int.Parse(args[3]);
    int topRightX = int.Parse(args[4]);
    int topRightY = int.Parse(args[5]);
    int bottomRightX = int.Parse(args[6]);
    int bottomRightY = int.Parse(args[7]);

    // the angle the top edge is rotated by
    int dx = topRightX - topLeftX;
    int dy = topRightY - topLeftY;
    double angle = (180 / Math.PI) * Math.Atan2(dx, dy);
    if (angle < -45 || angle >= 45)
    {
        angle = 90 - angle;
    }

    // therefore the angle to rotate by to get it straight
    angle = -angle;

    image = image.Rotate(angle);

    // the new position of the rectangle in the rotated image
    double radians = (Math.PI * angle) / 180.0;
    double c = Math.Cos(radians);
    double s = Math.Sin(radians);

    int left = Convert.ToInt32(topLeftX * c - topLeftY * s);
    int top = Convert.ToInt32(topLeftX * s + topLeftY * c);
    int width = Convert.ToInt32(Math.Sqrt(Math.Pow(topRightX - topLeftX, 2) +
                                          Math.Pow(topRightY - topLeftY, 2)));
    int height = Convert.ToInt32(Math.Sqrt(Math.Pow(topRightX - bottomRightX, 2) +
                                           Math.Pow(topRightY - bottomRightY, 2)));

    // after a rotate, the new position of the origin is given by .Xoffset, .Yoffset
    Image tile = image.Crop(left + image.Xoffset, top + image.Yoffset, width, height);

    tile.WriteToFile(outFilename);
}

Обратите внимание, что если вам нужна поддержка OpenSlide в Windows, вам придется использоватьдистрибутив libvips -all.По соображениям безопасности NetVips включает только дистрибутив -web libvips x86 / x64.Смотрите здесь для полного урока.

0 голосов
/ 23 января 2019

Преобразуйте ваши четыре угла (при условии, что прямоугольник не повернут) в WxH + X + Y, а затем используйте Imagemagick.

Если мы предположим, что 4 точки расположены по часовой стрелке от верхнего левого угла как (верхний левый, верхний правый, нижний правый, нижний левый), то математически мы вычислим:

W=(top-right-x - top-left-x)
H=(bottom-left-y -top-left-y)
X=top-left-x
Y=top-left-y


Затем в командной строке Imagemagick 6:

convert image -crop WxH+X+Y +repage croppedimage

Если я неправильно понимаю вашу проблему, пожалуйста, уточните.

ДОПОЛНИТЕЛЬНО:

Если у вас естьповерните прямоугольник, определяемый 4 точками, затем вы можете вычислить ограничивающий прямоугольник и преобразовать его в WxH + X + Y, чтобы обрезать с помощью команды выше.

Для этого получите min-x, min-y,max-x, max-y из ваших 4 баллов.Тогда

W=(max-x - min-x)
H=(max-y - min-y)
X=min-x
Y=min-y
0 голосов
/ 22 января 2019

Вы можете попробовать net-vips , привязку C # для libvips . Это ленивая, потоковая, управляемая по требованию библиотека обработки изображений, поэтому она может выполнять такие операции без необходимости загружать все изображение.

Нет операции, которая могла бы напрямую выполнить наклонную обрезку, но ее легко сделать самостоятельно с помощью небольшого триггера.

Например, используя привязку libvips для Python (извините, у меня здесь не установлен C #, но API тот же):

#!/usr/bin/python3

import sys
import math
import pyvips

image = pyvips.Image.new_from_file(sys.argv[1])
out_filename = sys.argv[2]
top_left_x = int(sys.argv[3])
top_left_y = int(sys.argv[4])
top_right_x = int(sys.argv[5])
top_right_y = int(sys.argv[6])
bottom_right_x = int(sys.argv[7])
bottom_right_y = int(sys.argv[8])

# the angle the top edge is rotated by
dx = top_right_x - top_left_x
dy = top_right_y - top_left_y
angle = math.degrees(math.atan2(dx, dy))
if angle < -45 or angle >= 45:
    angle = 90 - angle

# therefore the angle to rotate by to get it straight
angle = -angle

image = image.rotate(angle)

# the new position of the rectangle in the rotated image
c = math.cos(math.radians(angle))
s = math.sin(math.radians(angle))
left = top_left_x * c - top_left_y * s
top = top_left_x * s + top_left_y * c
width = math.hypot(top_right_x - top_left_x, top_right_y - top_left_y)
height = math.hypot(top_right_x - bottom_right_x, top_right_y - bottom_right_y)

# after a rotate, the new position of the origin is given by .xoffset, .yoffset
tile = image.crop(left + image.xoffset, top + image.yoffset, width, height)

tile.write_to_file(out_filename)

Я могу запустить его на большом изображении:

$ vipsheader ~/pics/openslide/bild.ndpi 
/home/john/pics/openslide/bild.ndpi: 126976x98304 uchar, 4 bands, rgb, openslideload
$ time ./angled_crop.py ~/pics/openslide/bild.ndpi x.jpg 680 760 936 836 484 1552
real    0m0.304s
user    0m0.388s
sys 0m0.040s

Таким образом, требуется 0,3 с, чтобы обрезать небольшую угловую область из изображения с разрешением 127000 x 98000 пикселей.

Изображения Openslide представляют собой (приблизительно) мозаичный рисунок, поэтому для декодирования необходимо только декодировать части входного изображения.

Это будет работать и на несвязанных изображениях, хотя сначала нужно будет декодировать все изображение целиком. Он будет декодироваться в память для изображений размером менее 100 МБ, а во временный файл в противном случае.

...