如何将2darrays旋转LESS超过90°,达到最佳近似值?

假设我有一个以0°旋转存储的数组:

0 0 1 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 

如果我通过,我希望它以良好的近似值返回,例如30°作为参数,它将类似于:

 0 0 0 1 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 

45°会

 1 0 0 0 1 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 

我知道90°旋转的解决方案。 但我不认为这会对我有帮助吗?

我没有任何示例代码,因为我目前甚至不知道从哪里开始查找。 如果有任何关键词我可以google指向我的方向我可以适应这一点,这也将是伟大的。

Spectre在C#中的代码解决方案:

  class Rotation { public Rotation() { A = new int[xs,ys]{ {0,0,0,9,0,0,0}, {0,0,0,9,0,0,0}, {0,0,0,9,0,0,0}, {9,9,9,9,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, }; B = new int[xs, ys]; deg = (float)(Math.PI / 180.0); } public const int xs = 7; // matrix size public const int ys = 7; const int x0 = 3; // rotation center cell const int y0 = 3; readonly float deg; public int[,] A; public int[,] B; //--------------------------------------------------------------------------- public void rotcv(float ang) { rotcw(Rotation.x0, Rotation.y0, ang); } private void rotcw(int x0, int y0, float ang) // rotate A -> B by angle ang around (x0,y0) CW if ang>0 { int x, y, ix0, iy0, ix1, iy1, q; double xx, yy, fx, fy, c, s; // circle kernel c = Math.Cos(-ang); s = Math.Sin(-ang); // rotate for (y = 0; y < ys; y++) for (x = 0; x = xs) ix1 = ix0; fy += y0; iy0 = (int)Math.Floor (fy); fy -= iy0; iy1 = iy0 + 1; if (iy1 >= ys) iy1 = iy0; // bilinear interpolation A[fx][fy] -> B[x][y] if ((ix0 >= 0) && (ix0 = 0) && (iy0 < ys)) { xx = (A[ix0,iy0]) + ((A[ix1,iy0] - A[ix0,iy0]) * fx); yy = (A[ix0,iy0]) + ((A[ix1,iy0] - A[ix0,iy0]) * fx); xx = xx + ((yy - xx) * fy); q =(int) xx; } else q = 0; B[x,y] = q; } } } 

测试:

  static void Main(string[] args) { Rotation rot = new Rotation(); for (int x = 0; x < Rotation.xs; x++) { for (int y = 0; y < Rotation.xs; y++) { Console.Write(rot.A[x,y] + " "); } Console.WriteLine(); } Console.WriteLine(); float rotAngle = 0; while (true) { rotAngle += (float)(Math.PI/180f)*90; rot.rotcv(rotAngle); for (int x = 0; x < Rotation.xs; x++) { for (int y = 0; y < Rotation.xs; y++) { Console.Write(rot.B[x, y] + " "); } Console.WriteLine(); } Console.WriteLine(); Console.ReadLine(); } } 

好的,这是承诺的。 第一个C ++代码:

 //--------------------------------------------------------------------------- #include  //--------------------------------------------------------------------------- const int xs=7; // matrix size const int ys=7; const int x0=3; // rotation center cell const int y0=3; const float deg=M_PI/180.0; int A[xs][ys]= { {0,0,0,9,0,0,0}, {0,0,0,9,0,0,0}, {0,0,0,9,0,0,0}, {9,9,9,9,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, }; int B[xs][ys]; //--------------------------------------------------------------------------- void rotcw(int x0,int y0,float ang) // rotate A -> B by angle ang around (x0,y0) CW if ang>0 { int x,y,ix0,iy0,ix1,iy1,q; float xx,yy,fx,fy,c,s; // circle kernel c=cos(-ang); s=sin(-ang); // rotate for (y=0;y=xs) ix1=ix0; fy+=y0; iy0=floor(fy); fy-=iy0; iy1=iy0+1; if (iy1>=ys) iy1=iy0; // bilinear interpolation A[ix0+fx][iy0+fy] -> B[x][y] if ((ix0>=0)&&(ix0=0)&&(iy0 

这里7x7预览15度步骤:

预习

可能需要稍微调整中心一半的细胞或某物(中心根据我的喜好流血太多)

矩阵A是源, B是目标......

你也可以添加阈值...像:

 if (q>=5) q=9; else q=0; 

想象一下,你的矩阵是一个2D世界,其原点(0,0)是中间的像素。 然后,例如,左上角点的坐标为(-2,2)。 如果将此向量乘以2D旋转矩阵,您将获得旋转世界中的新坐标。 在这里你可以随意近似(圆形,地板,ciel ……)。

这是旋转矩阵定义:

  | cos a -sin a| | sin a cos a | 

其中a是你的旋转角度。 以下是你如何成倍增加:

https://wikimedia.org/api/rest_v1/media/math/render/svg/50622f9a4a7ba2961f5df5f7e0882983cf2f1d2f

在该图像中,(x,y)是原始坐标(例如,左上角像素的(-2,2)),(x’,y’)是新的(近似的)坐标。

在Photoshop,GIMP,…和Imagemagick中,它已经多次用于图像处理。

您可以使用库(例如带有numpy的Python)将矩阵转换为位图图像,ImageMagick将其旋转x度并将旋转图像的结果读回矩阵。 您必须决定如何处理角点,如果要将* n网格旋转到* n网格,它们将被截断。

它可以在几行中完成,您不必重新发明轮子,如果旋转点没有完全落入单元格中,您将获得旋转点周围的灰度值。

迷你图片: 在此处输入图像描述 在此处输入图像描述

使用Python读取结果:

 import matplotlib.image as img image = img.imread('matrix.png') print image[:,:,0] # Only reads grayscale information. # Original [[ 0. 0. 1. 0. 0.] [ 0. 0. 1. 0. 0.] [ 1. 1. 1. 0. 0.] [ 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0.]] # Rotated by 30° [[ 0.07450981 0. 0.08235294 0.8509804 0. ] [ 0.68627453 0.82745099 0.53725493 0.78039217 0. ] [ 0. 0.50980395 0.97647059 0.22745098 0. ] [ 0. 0. 0.05882353 0. 0. ] [ 0. 0. 0. 0. 0. ]] 

对于Java解决方案, AffineTransform可以为您提供帮助。 这是一个例子。