当前位置:文档之家› mfc空间几何变换之图像平移、镜像、旋转、缩放详解

mfc空间几何变换之图像平移、镜像、旋转、缩放详解

MFC空间几何变换之图像平移、镜像、旋转、缩放详解一. 图像平移前一篇文章讲述了图像点运算(基于像素的图像变换),这篇文章讲述的是图像几何变换:在不改变图像容的情况下对图像像素进行空间几何变换的处理方式。

点运算对单幅图像做处理,不改变像素的空间位置;代数运算对多幅图像做处理,也不改变像素的空间位置;几何运算对单幅图像做处理,改变像素的空间位置,几何运算包括两个独立的算法:空间变换算法和灰度级插值算法。

空间变换操作包括简单空间变换、多项式卷绕和几何校正、控制栅格插值和图像卷绕,这里主要讲述简单的空间变换,如图像平移、镜像、缩放和旋转。

主要是通过线性代数中的齐次坐标变换。

图像平移坐标变换如下:运行效果如下图所示,其中BMP图片(0,0)像素点为左下角。

其代码核心算法:1.在对话框中输入平移坐标(x,y) m_xPY=x,m_yPY=y2.定义Place=dlg.m_yPY*m_nWidth*3 表示当前m_yPY行需要填充为黑色3.新建一个像素矩阵ImageSize=new unsigned char[m_nImage]4.循环整个像素矩阵处理for(int i=0 ; i<m_nImage ; i++ ){if(i<Place) {ImageSize[i]=black;continue;}//黑色填充底部从小往上绘图else if(i>=Place && countWidth<dlg.m_xPY*3) {//黑色填充左部分ImageSize[i]=black;countWidth++; continue;}else if(i>=Place && countWidth>=dlg.m_xPY*3) {//图像像素平移区域ImageSize[i]=m_pImage[m_pImagePlace];//原(0,0)像素赋值过去m_pImagePlace++;countWidth++;if(countWidth==m_nWidth*3) {//一行填满m_pImagePlace走到(0,1)number++;m_pImagePlace=number*m_nWidth*3;}}}5.写文件绘图fwrite(ImageSize,m_nImage,1,fpw)第一步:在ResourceView资源视图中,添加Menu子菜单如下:(注意ID号)第二步:设置平移对话框。

将试图切换到ResourceView界面--选中Dialog,右键鼠标新建一个Dialog,并新建一个名为IDD_DIALOG_PY。

编辑框(X)IDC_EDIT_PYX 和(Y)IDC_EDIT_PYY,确定为默认按钮。

设置成下图对话框:第三步:在对话框资源模板空白区域双击鼠标—Create a new class创建一个新类--命名为CImagePYDlg。

会自动生成它的.h和.cpp文件。

打开类向导(Ctrl W),选择类名:CImagePYDlg添加成员变量如下图所示,同时在Message Maps中生成ID_JHBH_PY实现函数。

第四步:在CImageProcessingView.cpp中添加头文件#include "ImagePYDlg.h",并实现平移。

[cpp]view plain copy1./********************************************************/2./*图像空间几何变换:图像平移ID_JHBH_PY(几何变换-平移)3./*使用平移对话框:CImagePYDlg dlg4./*算法:f(x,y)=f(x+x0,y+y0)图像所有点平移,空的补黑'0'5./*注意该图像平移方法只是从左上角(0,0)处开始平移6./*其他方向原理相同自己去实现7./********************************************************/8.9.void CImageProcessingView::OnJhbhPy()10.{11.if(numPicture==0){12.AfxMessageBox("载入图片后才能空间平移!",MB_OK,0);13.return;14.}15.//定义采样对话框也是用来空间变换平移的坐标16.CImagePYDlg dlg;17.if(dlg.DoModal()==IDOK)//显示对话框18.{19.//采样坐标最初为图片的自身像素20.if(dlg.m_xPY>m_nWidth||dlg.m_yPY>m_nHeight){21.AfxMessageBox("图片平移不能为超过原图长宽!",MB_OK,0);22.return;23.}24.AfxMessageBox("图片空间变换-平移!",MB_OK,0);25.26.//打开临时的图片读写文件27.FILE*fpo=fopen(BmpName,"rb");28.FILE*fpw=fopen(BmpNameLin,"wb+");29.fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);30.fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);31.fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);32.fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);33.fread(m_pImage,m_nImage,1,fpo);34.35./************************************************************/36./*图片空间变换-平移37./*坐标(dlg.m_xPY,dlg.m_yPY)表示图像平移的坐标38./*先用Plave计算出平移后的起始坐标,其他的坐标赋值为'0'黑色39./*然后依次平移坐标,空的赋为黑色,否则填充40./************************************************************/41.42./******************************************************************/43./*严重错误1:数组变量赋值相等44./*在View.h中定义变量BYTE*m_pImage读入图片数据后的指针45./*建立临时变量数组,让它平移变换unsigned char*ImageSize46./*ImageSize=m_pImage(错误)47./*会导致ImageSize赋值变换时m_pImage也产生了变换,所以输出全为黑色48./*因为它俩指向了相同的数组地址49./*解决方法:使用下面C++的new方法动态分配或for循环i=m_nImage赋值50./******************************************************************/51.52./*临时变量存储的像素与m_pImage相同,便于处理图像*/53.unsigned char*ImageSize;54.ImageSize=new unsigned char[m_nImage];//new和delete有效的进行动态存的分配和释放55.56.int Place;//建立临时坐标记录起始坐标(0,0)平移过来的位置57.int m_pImagePlace;//原始图像平移为(0,0)图像把它平移到Place位置58.unsigned char black;//填充黑色='0'59.60./************************************************************/61./*for(int i=0;i<m_nHeight;i++)62./*for(int j=0;j<m_nWidth;j++)63./*不能使用的上面的因为可能图像的最后一行没有完整的一行像素64./*这样会出现exe报错,使用m_nImage读写所有像素比较正确65./************************************************************/66.67.Place=dlg.m_yPY*m_nWidth*3;//前m_yPY行都要填充为黑色68.black=0;//颜色为黑色69.m_pImagePlace=0;//图像处事位置为(0,0),把该点像素平移过去70.int countWidth=0;//记录每行的像素个数,满行时变回071.int number=0;//数字记录使用的像素行数,平移时使用72.73.for(int i=0;i<m_nImage;i++)74.{75./*如果每行的像素填满时清为0*/76.if(countWidth==m_nWidth*3){77.countWidth=0;78.}79.80./*第一部分:到平移后像素位置前面的所有像素点赋值为黑色*/81.if(i<Place){82.ImageSize[i]=black;//赋值为黑色83.continue;84.}85.86./*第二部分:平移区域的左边部分赋值为黑色*/87.else if(i>=Place&&countWidth<dlg.m_xPY*3){//RGB乘388.ImageSize[i]=black;//赋值为黑色89.countWidth++;90.continue;91.}92.93./****************************/94./*各部分如图所示:95./*00000000000000000000000096./*00000000000000000000000097./*0000000.................98./*0000000.................99./*0000000.................100./*0000000.................101./*点表示像素部分,0为黑色102./****************************/103.104./*重点错误提示:由于bmp图像显示是从左下角开始存储(0,0)点所以输出图像为*/ 105./*bmp图像是从左下角到右上角排列的*/106.107./****************************/108./*各部分如图所示:109./*0000000.................110./*0000000.................111./*0000000.................112./*0000000.................113./*000000000000000000000000114./*000000000000000000000000115./*点表示像素部分,0为黑色116./****************************/117.118./*第三部分:图像像素平移区域*/119.else if(i>=Place&&countWidth>=dlg.m_xPY*3)120.{121.ImageSize[i]=m_pImage[m_pImagePlace];122.m_pImagePlace++;123.countWidth++;124.if(countWidth==m_nWidth*3)125.{126.number++;127.m_pImagePlace=number*m_nWidth*3;128.}129.}130.}131.132.fwrite(ImageSize,m_nImage,1,fpw);133.fclose(fpo);134.fclose(fpw);135.numPicture=2;136.level=200;//200表示几何变换137.Invalidate();138.}139.}同时在ShowBitmap中添加level标记重新绘制图片,代码如下:[cpp]view plain copy1.else//图像几何变换2.if(level=200)3.{4.m_hBitmapChange=(HBITMAP)LoadImage(NULL,BmpNameLin,IMAGE_BITMAP,0,0,5.LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);6.}运行时需要注意一点:BMP图像在处理过程中可能会出现一些斜线,而平移(40,60)位移量时可能出现如下。

相关主题