2009-01-23 12 views
10

Tôi có một hình ảnh với hai điểm, một cái gì đó phù hợp như thế này:Xoay hình ảnh toán học (C#)

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

Tôi có cả X, Y tọa độ cho cả hai điểm và tôi cần phải xoay độ hình ảnh X nên nó trông giống như thế này thay thế:

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

Về cơ bản để chúng được căn chỉnh bên cạnh nhau, toán học là gì? (Một ví dụ mã trong C# sẽ là tốt hơn nhưng không bắt buộc)

+0

Đây là một chủ đề cũ, nhưng tôi sẽ chỉ đề cập đến mà tôi đã đăng một phương pháp C# WinForms xoay hình ảnh ở đây: http://stackoverflow.com/questions/2163829/how-do-i-rotate-a-picture-in-c-sharp – RenniePet

Trả lời

14

Nó phụ thuộc vào điểm mà bạn muốn sử dụng như là một "trung tâm" cho vòng quay của bạn. Hãy gọi điểm tới điểm lên và điểm trái và điểm bên phải và bên dưới điểm B. Nếu bạn muốn xoay quanh điểm A sao cho điểm B thẳng hàng với nó, việc tính toán góc quay theo radian sẽ như sau:

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

Tôi không xử lý hình ảnh của bạn như sau chỉ áp dụng nếu bạn đang sử dụng System.Drawing.Graphics:

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

Hy vọng điều đó sẽ hữu ích.

2

Bạn cần phải nhìn lên ma trận xoay hình học: See this site for an detailed explanation

Tuy nhiên, cho kết quả tốt nhất, bạn cần phải chuyển đổi từ đích đến nguồn và sau đó sử dụng việc chuyển đổi cho mỗi pixel điểm:

m = rotation matrix 

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

có, trong các phương pháp khung lưới để làm tất cả điều này: System.Drawing.Graphics.RotateTransformSystem.Drawing.Graphics.TranslateTransform. Bạn sẽ cần phải thiết lập một bản dịch để di chuyển điểm quay của hình ảnh về nguồn gốc, sau đó áp dụng vòng xoay và sau đó một bản dịch khác để đưa nó trở về vị trí ban đầu. Bạn sẽ cần phải thử nghiệm với các chức năng này để tìm ra cách chúng hoạt động - Tôi đang làm việc vào lúc này và không có thời gian để lấy một số mã cùng hoạt động. :-(

5

Không có mã, xin lỗi, nhưng một stratagy.

Bạn cần để có thể tạo ra các hình ảnh kết quả bằng cách lấy mẫu hình ảnh nguồn. Bạn biết góc quay, vì vậy bây giờ bạn cần phải tạo một hàm ánh xạ mà các bản đồ từ kết quả trở lại với bản gốc

mã này sẽ chỉ đơn giản là quét mỗi hàng của hình ảnh kết quả, và bản đồ pixel trở lại ảnh gốc Bạn có thể làm một cách đơn giản;..

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

Vì vậy, bây giờ chúng ta chỉ cần metho "getOriginalPixel" huyền diệu d, và đây là nơi mà các toán học đi vào.

Nếu chúng ta xoay hình 0 độ, thì lôgic, cốt truyện chỉ là X/Y của hình ảnh gốc. Nhưng đó không phải là niềm vui.

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

Tôi nghĩ rằng sẽ ánh xạ tới pixel nguồn. Bạn sẽ cần phải kiểm tra nếu nó nằm ngoài giới hạn và chỉ trả lại màu đen hoặc một cái gì đó :)

+0

Bạn nên trả về Color.Transparent nếu nó vượt quá giới hạn – MrFox

2

Đầu tiên tìm ra điểm trung tâm:

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

Sau đó sử dụng trigonomentry để giải quyết cho các góc. Tôi sẽ giả sử chúng tôi đã rebased nguồn gốc để điểm trung tâm của chúng tôi vì vậy bây giờ tôi có một mới x3 và y3 đến một trong những điểm.

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

Chúng tôi đang giải quyết cho biết góc TH

Sin(TH) = opposite/hypotenuse 

Vì vậy, để giải quyết cho TH chúng ta cần:

TH = Asin(y3/hypotenuse) 

Xoay bởi TH.

Xem Wikipedia for trigonometric functions reference

2

Thực hiện phép biến đổi 2D chung bao gồm việc giải quyết một cặp biện pháp phòng ngừa với 6 ẩn số.

'x = xA + YB + C

' y = xD + Ye + D

Với 3 điểm tương ứng, bạn sẽ có 6 knowns và hệ thống có thể được giải quyết. Bạn chỉ có 4 điểm trong trường hợp này, vì bạn không quan tâm đến việc cắt, nhưng bạn có thể tưởng tượng giới thiệu một điểm thứ 3 ở 90 độ cho đường thẳng được hình thành bởi hai điểm còn lại. Tạo một hình ảnh xoay sau đó (giả codedily) chỉ một cái gì đó như:

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

Nếu hiệu suất là quan trọng, đa phần trong các vòng lặp bên trong có thể được tối ưu hóa đi bằng cách ghi nhận rằng * chỉ thay đổi y B trong giao diện bên ngoài và rằng newx, newy thay đổi bởi hằng số A và D trong vòng lặp bên trong.

4

Các mã dưới đây trình

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