Пиксельные ошибки при повороте изображения с помощью emgucv в c # - PullRequest
0 голосов
/ 30 мая 2019

Я пытаюсь повернуть изображение с помощью emgucv с GetRotationMatrix2D и WarpAffine.Я пробовал разные методы, чтобы повернуть изображение, и хотя этот метод кажется лучшим на данный момент, иногда кажется, что он дает неправильные пиксели.

Я использовал следующие методы, чтобы прочитать изображение в объект Mat и повернуть его.

public static void LoadImage(string filepath, Mat target, ImreadModes mode = ImreadModes.Grayscale | ImreadModes.AnyDepth)
{
    using (var mat = CvInvoke.Imread(filepath, mode))
    {
        if (mat == null || mat.Size == System.Drawing.Size.Empty)
            throw new System.IO.IOException($"Image file '{filepath}'           is not readable.");
        mat.CopyTo(target);
    }
}

void rotateMat(ref Mat src, double angle)
{
    Mat r = new Mat();
    PointF pc = new PointF((float)(src.Cols / 2.0), (float)(src.Rows / 2.0));
    CvInvoke.GetRotationMatrix2D(pc, angle, 1.0, r);
    CvInvoke.WarpAffine(src, src, r, src.Size);
}

.....
Mat image = new Mat();
LoadImage("./test.tif", image);
rotateMat(ref image, frameRotation);
.....

Этот код работает без ошибок, но в некоторых случаях части изображения перекрываются друг с другом, как если бы поворот был применен к сегментам изображения отдельно.Я работаю с 16-битными файлами Tiff.

Вот результат, полученный после поворота изображения:

https://i.stack.imgur.com/xiHvk.jpg

1 Ответ

0 голосов
/ 04 июня 2019

Вместо матрицы вращения вы пробовали использовать RotatedRect? Я использую эту технику, когда хочу скопировать область интереса, определенную RotatedRect, из исходного изображения в конечное изображение. Это должно работать для любого изображения. Вот пример программы Windows Console, которая демонстрирует эту концепцию:

private static void Main(string[] args)
{
    Mat source = new Mat("dog.jpg", ImreadModes.Unchanged);

    PointF center = new PointF(Convert.ToSingle(source.Width) / 2, Convert.ToSingle(source.Height) / 2);
    Mat destination = new Mat(new System.Drawing.Size(source.Width, source.Height), DepthType.Cv8U, 3);

    RotatedRect destRect = new RotatedRect(center, source.Size, 35);
    Rectangle bbox = destRect.MinAreaRect();

    RotateImage(ref source, ref destination, destRect);
    CvInvoke.Imshow("Source", source);
    CvInvoke.Imshow("Destination", destination);

    CvInvoke.WaitKey(0);
}

private static void RotateImage(ref Mat src, ref Mat destination, RotatedRect destRect)
{
    PointF[] destCorners = destRect.GetVertices();
    PointF[] srcCorners = new PointF[] {
            new PointF(0F, src.Height),
            new PointF(0F, 0F),
            new PointF(src.Width, 0F),
            new PointF(src.Width, src.Height)
    };

    using (Mat aft = CvInvoke.GetAffineTransform(srcCorners, destCorners))
    using (Mat warpResult = new Mat(src.Size, src.Depth, src.NumberOfChannels))
    {
        CvInvoke.WarpAffine(src, warpResult, aft, destination.Size);
        warpResult.CopyTo(destination);
    }
}

В этом примере из клипа будет вырезано полученное изображение. Я оставлю читателю в качестве упражнения изменение размера места назначения, чтобы избежать отсечения.

Doug

...