2012年12月27日 星期四

影像處理 旋轉 正推法 (src->dst) 有洞 無切邊 (EmguCV 程式碼)

Image<bgr byte=""> RotateImageS2D(Image<bgr byte=""> srcImage, double angle)
{
int width = srcImage.Width;
int height = srcImage.Height;
double theta = angle * (Math.PI/180.0);
double vsin = Math.Sin(theta);
double vcos = Math.Cos(theta);
///////////////////////////////////////////////////////////////
// 求旋轉後圖片長寬
///////////////////////////////////////////////////////////////
// 四個頂點
int x1 = 0, y1 = 0;
int x2 = srcImage.Width - 1, y2 = 0;
int x3 = srcImage.Width - 1, y3 = srcImage.Height - 1;
int x4 = 0, y4 = srcImage.Height - 1;
// 旋轉後圖片四個頂點
int fx1 = (int)(vcos * x1 - vsin * y1);
int fx2 = (int)(vcos * x2 - vsin * y2);
int fx3 = (int)(vcos * x3 - vsin * y3);
int fx4 = (int)(vcos * x4 - vsin * y4);
int fy1 = (int)(vsin * x1 + vcos * y1);
int fy2 = (int)(vsin * x2 + vcos * y2);
int fy3 = (int)(vsin * x3 + vcos * y3);
int fy4 = (int)(vsin * x4 + vcos * y4);
// 求上下左右頂點
int fmaxX = Math.Max(fx1, Math.Max(fx2, Math.Max(fx3, fx4)));
int fminX = Math.Min(fx1, Math.Min(fx2, Math.Min(fx3, fx4)));
int fmaxY = Math.Max(fy1, Math.Max(fy2, Math.Max(fy3, fy4)));
int fminY = Math.Min(fy1, Math.Min(fy2, Math.Min(fy3, fy4)));
// 計算長寬
int fWidth = fmaxX - fminX;
int fHeight = fmaxY - fminY;
///////////////////////////////////////////////////////////////
// 畫出旋轉後的圖
///////////////////////////////////////////////////////////////
Image<bgr byte=""> dstImage = new Image<bgr byte="">(fWidth, fHeight);
// 旋轉前後中心點差距
int dW = width / 2 - fWidth / 2;
int dH = height / 2 - fHeight / 2;
for (int i = 0; i &lt; height; i++)
{
for (int j = 0; j &lt; width; j++)
{
// 純粹好看用
double x = (double)j;
double y = (double)i;
// 公式
int dX = (int)(vcos * x - vsin * y - vcos / 2 * width + vsin / 2 * height + width / 2 - dW);
int dY = (int)(vsin * x + vcos * y - vsin / 2 * width - vcos / 2 * height + height / 2 - dH);
// 判斷有無出界
if (dX &gt;= 0 &amp;&amp; dX &lt; fWidth &amp;&amp; dY &gt;= 0 &amp;&amp; dY &lt; fHeight)
{
dstImage[dY, dX] = srcImage[(int)y, (int)x];
}
}
}
return dstImage;
}