数字图像处理实验——几何变换
图像几何变换实验
这是我在完成数字图像处理课程实验时的一些记录,其中实验目标和要求来自老师的实验讲义。第一个实验是完成图像的基本几何变换(包括平移、旋转、缩放)并将其显示出来,其中插值使用双线性插值。由于实验要求使用c++实现且不得调用相关的第三方库,因此选择了基于MFC实现,使用的平台是Visual Studio 2010。
SEU_Digital-Image-Processing-Lab/Lab1
1. 实验目标
本实验要求实现一个包含图像基本几何变换(包括平移、旋转、缩放)的实验程序。该程 序可以读取以 bmp 格式存放的灰度图像文件,提供简易的人机交互方式选择变换方式及输 入相关的参数,可以显示处理前及处理后的图像。
2. 具体要求:
(1) 程序使用 C++语言编写,集成开发环境可以选择 vs 或 Qt,几何变换的核心 代码(包括坐标映射、像素遍历、灰度插值等)不允许直接调用库函数实 现,不允许使用 opencv 等第三方库。
(2) 图像几何变换(包括插值)部分以类的形式封装(类及接口自由设计),与 人机交互功能分离。图像几何变换应该包含平移、旋转和缩放三种基本变换 的接口,并由接口函数导入变换的相关参数。其中,旋转的中心可以设定为 图像的几何中心或通过接口函数导入。原始图像以及结果图像的导入和导出 方式不限,可以自由设计。
(3) 人机交互方式可以自由设计,应该可以显示原始和结果图像(不限制显示方 式,例如可以直接在主界面上显示,或新建窗口显示,或同时显示处理前后 图像,或每一时刻只能显示一幅图像)。可以由用户选择加载以 BMP 格式保 存的灰度图像作为原始图像,不要求保存处理结果。
3. 实现方法
本实验基于MFC实现,使用的平台是visual studio 2010。窗口显示使用基于CWnd的类。图片使用CImage类。
继承CWnd实现一个窗口类
考虑到会对一个窗口做一些适合我们的修改,我们从CWnd类中继承出一个自己的类CImgWnd,其中包含一个成员:一个指向CImage对象的指针。
它的构造函数如下:
1 | CImgWnd::CImgWnd(CWnd *pParentWnd, RECT rect, CImage* img, LPCTSTR pname) |
在这个类中实现对于图像的显示
1 | void CImgWnd::OnPaint() |
view中的显示窗口的消息函数
其中mpSrcImgWnd是一个CImgWnd对象的指针,当这个指针为NULL时,新建一个CImgWnd对象,如果已经存在一个对象,则更新它。
1 | void CGeo_Lab1View::OnWndSrcwnd() |
图像读入及显示
使用CImage的Load函数来读入图像,在CImgWnd类的OnPaint函数中使用Draw函数来显示图像。而我们要写的几何变换实现的是对于一个CImage对象的内部的像素值的改变。具体可以看代码。
几何变换类
主要的函数为仿射变换和双线性插值。平移、旋转、缩放都是通过仿射变换实现的。由于缩放,旋转时导致的一些不能取到整数像素的情况,需要通过插值来实现。考虑到每次都判断坐标是否为整数过于繁琐,我们假设每次的坐标变化都是通过插值得到的。
数据成员及成员函数
1 | public: |
双线性插值
算法原理如下图,还是很好理解和实现的。

1 | BYTE GeometricTransform::BiInter(BYTE x00, BYTE x10, BYTE x01, BYTE x11, double r1, double r2) |
仿射变换
假设每个获得的像素值都是通过插值实现的。变换公式如下图,实现时需反解出x和y。

1 | void GeometricTransform::AffTransform(double a11, double a12, double a13, double a21, double a22, double a23) |
平移
1 | void GeometricTransform::Translation(double x, double y) |
缩放
1 | void GeometricTransform::Scaling(double sx, double sy) |
旋转
旋转中心为图像中心而非坐标原点,所以需要增加两个常数项,可以通过公式计算出。
1 | void GeometricTransform::Rotation(int Theta) |
小结
几何变换是图像处理的基本功能,由于只是课程小实验,我的程序还不是很完善,但完全实现了应有的功能,在网上目前也很难找到关于基于MFC的图像处理,尤其是不能调库的情况的资料,后续的实验内容我也会持续更新到博客上。