图像的扭曲是按照一定的映射将像素点从原来的位置移动到新的位置,这种映射可以用复变函数表示

516d1eac5b1b7e6201567f28673d90af.png

膨胀:

在极坐标下,设原来的坐标为(r,α),变换后的新坐标为(R,β):

R = r * r * degree

β = α

其中 degree 是可变参数。该映射使得图像向外扩张。下面是c#中的代码

///

/// 膨胀

///

/// 要处理的图片

/// 扭曲的幅度

/// 处理后的图片

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开始》,书中使用指针操作,以及移位运算、三角函数的级数展开等方法提高了运算效率

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐