图像的扭曲是按照一定的映射将像素点从原来的位置移动到新的位置,这种映射可以用复变函数表示
在极坐标下,设原来的坐标为(r,α),变换后的新坐标为(R,β):
R = r * r * degree
β = α
其中 degree 是可变参数。该映射使得图像向外扩张。下面是c#中的代码
/// <summary>
/// 膨胀
/// </summary>
/// <param name="bmp">要处理的图片</param>
/// <param name="degree">扭曲的幅度</param>
/// <returns>处理后的图片</returns>
public Bitmap Distortion(Bitmap bmp, int degree)
{
Bitmap retBmp = bmp.Clone() as Bitmap;
int width = bmp.Width;
int height = bmp.Height;
// 原点的x和y坐标
int midX = width / 2;
int midY = height / 2;
// 极坐标角度
double theta;
// 极坐标半径
double radius;
int offsetX, offsetY;
int xx, yy;
for (int y = 0; y < height; y++)
{
// 当前处理的像素点与原点的纵向偏离量
offsetY = y - midY;
for (int x = 0; x < width; x++)
{
// 当前处理的像素点与原点的横向偏离量
offsetX = x - midX;
// 计算新坐标的在极坐标下表示的角度和半径
theta = Math.Atan2(offsetY, offsetX);
radius = Math.Sqrt(offsetX * offsetX + offsetY * offsetY);
// 反推出对应的原坐标的半径
radius = Math.Sqrt(radius) * degree;
// 原坐标的直角坐标系中的位置(xx,yy)
xx = (int)(radius * Math.Cos(theta)) + midX;
yy = (int)(radius * Math.Sin(theta)) + midY;
// 边界约束,如果超出边界只好用边界的像素代替
if (xx < 0) xx = 0;
if (xx >= width) xx = width - 1;
if (yy < 0) yy = 0;
if (yy >= height) yy = height - 1;
// 将原坐标像素点移动到新坐标
retBmp.SetPixel(x, y, bmp.GetPixel(xx, yy));
}
}
return retBmp;
}
挤压:
R = sqrt(r) * degree
β = α
该映射使得图像向内收缩
只要把代码中 38 ~ 41 行的去掉,改成:radius = (offsetX * offsetX + offsetY * offsetY) / degree;
以上主要参考《图像编程精髓——从开发自己的Photoshop开始》,书中使用指针操作,以及移位运算、三角函数的级数展开等方法提高了运算效率
来源:oschina
链接:https://my.oschina.net/u/189801/blog/54401