Повернуть математику изображения (С#)

У меня есть изображение с двумя точками, выровнено примерно так:

|----------------|
|                |
|    .           |
|                |
|          .     |
|                |
|----------------|

У меня есть координаты X, Y для обеих точек, и мне нужно повернуть изображение X градусов, чтобы оно выглядело следующим образом:

|----------------|
|                |
|                |
|    .     .     |
|                |
|                |
|----------------|

В принципе, они выравниваются рядом друг с другом, что математика для этого? (Пример кода на С# будет еще лучше, но не требуется)

Ответ 1

Это зависит от того, какой пункт вы хотите использовать в качестве "центра" для вашего вращения. Позвольте называть точку в верхнюю и левую точку A, а одну - вправо и ниже точки B. Если вы хотите повернуть вокруг точки A так, чтобы точка B совпадала с ней, вычисление угла поворота в радианах будет выглядеть следующим образом:

double angle = Math.Atan2(pointB.Y - pointA.Y, pointB.X - pointA.X);

Я не понимаю, как вы обрабатываете свое изображение, поэтому следующее применимо только в том случае, если вы используете System.Drawing.Graphics:

myImage.TranslateTransform(-pointA.X, -pointA.Y);
myImage.RotateTransform((float) angle, MatrixOrder.Append);
myImage.TranslateTransform(pointA.X, pointA.Y, MatrixOrder.Append);

Надеюсь, что это поможет.

Ответ 2

Нет кода, извините, но стратагия.

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

Код просто сканирует каждую строку изображения результата и сопоставляет пиксель с исходным изображением. Вы можете сделать простой:

for (int plotY = 0; plotY < resultHeight; plotY++)
{
   for (int plotX = 0; plotX < resultWidth; plotX++)
   {
         resultImage.PlotPixel(getOriginalPixel(plotX, plotY, angleOfRotation));
   } 
}

Итак, теперь нам просто нужен магический метод getOriginalPixel, и именно здесь появляются математика.

Если мы поворачиваем изображение на 0 градусов, то plotX, plotY - это просто X/Y исходного изображения. Но это не весело.

pickX = x * cos(angle) - y * sin(angle)
pickY = y * cos(angle) + x * sin(angle)

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

Ответ 3

Нижеприведенный код работает

  Matrix mRotate = new Matrix();
    mRotate.Translate(Convert.ToInt32(Width.Value) / -2, Convert.ToInt32(Height.Value) / -2, MatrixOrder.Append);
    mRotate.RotateAt(theta, new Point(0, 0), MatrixOrder.Append);

    using (GraphicsPath gp = new GraphicsPath())
    {  // transform image points by rotation matrix
        gp.AddPolygon(new Point[] { new Point(0, 0), new Point(Convert.ToInt32(Width.Value), 0), new Point(0, Convert.ToInt32(Height.Value)) });
        gp.Transform(mRotate);
        PointF[] pts = gp.PathPoints;

        // create destination bitmap sized to contain rotated source image
        Rectangle bbox = boundingBox(bmpSrc, mRotate);
        Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height);


        using (Graphics gDest = Graphics.FromImage(bmpDest))
        {  // draw source into dest


            Matrix mDest = new Matrix();
            mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append);
            gDest.Transform = mDest;
            gDest.DrawImage(bmpSrc, pts);
            gDest.DrawRectangle(Pens.Transparent, bbox);
            //drawAxes(gDest, Color.Red, 0, 0, 1, 100, "");
            return bmpDest;
        }
    }

Ответ 4

Вам нужно искать геометрические матрицы вращения: Подробнее см. на этом сайте

Однако для достижения наилучших результатов вам необходимо преобразовать из адресата в источник, а затем использовать преобразование для каждого пикселя назначения:

m = rotation matrix

for each point p in destination
  p' = p.m
  get pixel p' from source
  set pixle p in destination

В методах .NET Framework есть все, что можно сделать: System.Drawing.Graphics.RotateTransform и System.Drawing.Graphics.TranslateTransform. Вам нужно будет настроить перевод, чтобы переместить точку поворота изображения в начало координат, затем применить поворот, а затем другой перевод, чтобы вернуть его в исходное положение. Вам нужно будет поэкспериментировать с этими функциями, чтобы понять, как они себя ведут - я нахожусь на работе в данный момент, и у меня нет времени на то, чтобы сработать код, который работает.: - (

Ответ 5

Сначала найдите центральную точку:

Point p = new Point((x1-x2)/2, (y1-y2)/2)

Затем используйте тригонометрию для решения для угла. Я собираюсь предположить, что мы перевели начало координат в нашу центральную точку, поэтому теперь у меня есть новые x3 и y3 для одной из точек.

hypotenuse = SqrRt(x3^2 + y3^2)

Мы решаем для неизвестного угла TH

Sin(TH) = opposite / hypotenuse

Итак, для решения для TH нам нужно:

TH = Asin(y3 / hypotenuse)

Повернуть на TH.

См. Википедия для справки тригонометрических функций

Ответ 6

Выполнение общего двумерного преобразования включает в себя решение пары eqautions с 6 неизвестными.

'x = xA + yB + C

'y = xD + yE + D

Учитывая 3 соответствующие точки, у вас будет 6 известных и система может быть решена. В этом случае у вас всего 4 балла, так как вы не заботитесь о сдвиге, но вы можете представить себе 3-ю точку на 90 градусов по линии, образованной двумя другими точками. Создание повернутого изображения затем (псевдокодически) означает что-то вроде:

for ( y = 0; y < height; y++ )
 for ( x = 0; x < width; x++ )
  {
    newx = x*A + y*B + C;
    newy = x*D + y*D + E;
    newimage(x,y ) = oldimage( newx, newy );
  }
}

Если производительность важна, умножения во внутреннем цикле можно оптимизировать, заметив, что y * B только изменяет внешний вид и что newx, новое изменение константами A и D во внутреннем цикле.