图像的几何变换
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1实验目的、要求
实验目的:
(1)掌握图像在空间域进行基本变换的原理与相关方法。
(2)能使用VC++实现图像平移变换、镜像变换、旋转变换、缩放变换的功能。
实验要求:
A部分:
(1)使用VC++设计程序:实现图像平移变换,图像缩放、图像裁剪、图像对角线镜像。
(2)使用VC++设计程序:对一幅高度与宽度均相等的图像,实现逆时针90度旋转。B部分:
(1)包括A部分全部要求。
(2)使用VC++设计程序:对任意一幅图像(高度与宽度可以不相等),实现任意角度的旋转。
(3)研究放大图像时使用的插值算法,使用VC++实现常见的三种图像插值算法:最近邻插值,双线性插值,立方卷积插值。通过实验验证其效果。
2实验原理
图像的平移:通过直角坐标系的平移变换公式:
x ‘ = x +dx
y’ = y + dy
注:(x,y)为源图像的坐标,(x’, y’)为新图像的坐标,dx对应x的偏移量,dy对应y的偏移量。即:平移之后新图像上坐标为(x’, y’)的像素点的颜色值,应该等于原图像上坐标为(x, y)的像素点的颜色值,以下类似。
图像的镜像:镜像分为水平镜像和垂直镜像
垂直镜像计算公式如下(图像大小为宽度为M,高度为N):
x’ = x
y’ = N – 1 – y
水平镜像计算公式为:
x’ = M – 1 – x
y’ = y
对角线镜像(对角线为左上角至右下角)计算公式:
x’ = M – 1 – x
y’ = N – 1 – y
图像的旋转:图像的旋转计算公式如下:
X’ = X *COS Q – Y *SIN Q
Y’ = X *SIN Q + Y*COS Q
注:(x,y)为源图像的坐标,(x’, y’)为新图像的坐标。
图像缩放:设原图像大小为宽度M、高度N,调整后宽度为k1×M、高度为k2×N,则:
Img.New(x,y) = Img.Old(x/k1, y/k2)
图像插值:当放大图像时,像素也相应地增加,增加的过程就是插值程序自动选择信息较好的像素作为增加的像素,而并非只使用临近的像素,所以在放大图像时,图像看上去会比较平滑、干净。常用插值算法包括:
最近邻插值:近邻取样插值的缩放算法,直接取Color0颜色作为缩放后点的颜色
双线性插值:需要考虑(Sx,Sy)坐标点周围4个颜色值Color0\Color1\Color2\Color3,把(Sx,Sy)到A\B\C\D坐标点的距离作为系数来把4个颜色混合出缩放后点的颜色立方卷积插值:考虑映射点周围16个点(4x4)的颜色来计算最终的混合颜色
3主要设备、器材
硬件环境:AMD A8-4500M 1.90G/4G RAM
软件环境:操作系统:WIN7
开发工具:Micrsoft Visual C++ 6.0
4实验步骤及原始数据记录
关键代码说明:
图像平移:
void CImageProcessingView::OnGeoTranslation()
{
// 实验图像平移
MessageBox("请在这里添加图像平移的代码");
// 可以参考图像裁剪的代码:CImageProcessingView::OnGeoCut()
// 获得当前文档对象
CImageProcessingDoc* pDoc = GetDocument();
// 判断图像是否已被加载
if( pDoc->m_pDibInit->IsEmpty() )
{
MessageBox("图像未加载");
return;
}
int width = pDoc->m_pDibInit->GetImageWidth();
int height = pDoc->m_pDibInit->GetImageHeight();
int bitCount = pDoc->m_pDibInit->GetImageBitCount();
// 将m_pDibInit 拷贝至m_pDibTest
pDoc->m_pDibTest->CloneDib(pDoc->m_pDibInit);
// 设置pDoc->m_pDibTest 为全白图像
int i, j;
RGBQUAD rgbQuad1;
rgbQuad1.rgbBlue = 255;
rgbQuad1.rgbGreen = 255;
rgbQuad1.rgbRed = 255;
rgbQuad1.rgbReserved = 0;
for(i=0; i { for(j=0; j { pDoc->m_pDibTest->SetPixel(i,j,&rgbQuad1); } } // 实验删除BEGIN int shiftX = 30; int shiftY = 50; for(i=0; i { for(j=0; j { rgbQuad1 = pDoc->m_pDibInit->GetPixel(i,j); pDoc->m_pDibTest->SetPixel(i+shiftX, j+shiftY, &rgbQuad1); } } // 实验删除END // 交换m_pDibInit 与m_pDibTest 指针 CDib* pTmp = pDoc->m_pDibInit; pDoc->m_pDibInit = pDoc->m_pDibTest; pDoc->m_pDibTest = pTmp; // 设置脏标记 pDoc->SetModifiedFlag(TRUE); // 更新视图 pDoc->UpdateAllViews(NULL); } 图像缩放: void CImageProcessingView::OnGeoResizing() { // 实验图像缩放 MessageBox("请在这里添加图像缩放的代码"); // 可以参考图像裁剪的代码:CImageProcessingView::OnGeoCut() // 获得当前文档对象 CImageProcessingDoc* pDoc = GetDocument(); // 判断图像是否已被加载 if( pDoc->m_pDibInit->IsEmpty() ) { MessageBox("图像未加载"); return; } int width = pDoc->m_pDibInit->GetImageWidth(); int height = pDoc->m_pDibInit->GetImageHeight(); int bitCount = pDoc->m_pDibInit->GetImageBitCount();