1、MFC空间几何变换之图像平移镜像旋转缩放详解MFC空间几何变换之图像平移、镜像、旋转、缩放详解一. 图像平移 前一篇文章讲述了图像点运算(基于像素的图像变换),这篇文章讲述的是图像几何变换:在不改变图像内容的情况下对图像像素进行空间几何变换的处理方式。 点运算对单幅图像做处理,不改变像素的空间位置;代数运算对多幅图像做处理,也不改变像素的空间位置;几何运算对单幅图像做处理,改变像素的空间位置,几何运算包括两个独立的算法:空间变换算法和灰度级插值算法。 空间变换操作包括简单空间变换、多项式卷绕和几何校正、控制栅格插值和图像卷绕,这里主要讲述简单的空间变换,如图像平移、镜像、缩放和旋转。主要是通过
2、线性代数中的齐次坐标变换。 图像平移坐标变换如下: 运行效果如下图所示,其中BMP图片(0,0)像素点为左下角。 其代码核心算法: 1.在对话框中输入平移坐标(x,y) m_xPY=x,m_yPY=y 2.定义Place=dlg.m_yPY*m_nWidth*3 表示当前m_yPY行需要填充为黑色 3.新建一个像素矩阵ImageSize=new unsigned charm_nImage 4.循环整个像素矩阵处理 for(int i=0 ; im_nImage ; i+ ) if(i=Place & countWidth=Place & countWidth=dlg.m_xPY*3) /图像像
3、素平移区域 ImageSizei=m_pImagem_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,右
4、键鼠标新建一个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,
5、并实现平移。cppview plaincopy1. /*/2. /*图像空间几何变换:图像平移ID_JHBH_PY(几何变换-平移)3. /*使用平移对话框:CImagePYDlgdlg4. /*算法:f(x,y)=f(x+x0,y+y0)图像所有点平移,空的补黑05. /*注意该图像平移方法只是从左上角(0,0)处开始平移6. /*其他方向原理相同自己去实现7. /*/8. 9. voidCImageProcessingView:OnJhbhPy()10. 11. if(numPicture=0)12. AfxMessageBox(载入图片后才能空间平移!,MB_OK,0);13. retu
6、rn;14. 15. /定义采样对话框也是用来空间变换平移的坐标16. CImagePYDlgdlg;17. if(dlg.DoModal()=IDOK)/显示对话框18. 19. /采样坐标最初为图片的自身像素20. if(dlg.m_xPYm_nWidth|dlg.m_yPYm_nHeight)21. AfxMessageBox(图片平移不能为超过原图长宽!,MB_OK,0);22. return;23. 24. AfxMessageBox(图片空间变换-平移!,MB_OK,0);25. 26. /打开临时的图片读写文件27. FILE*fpo=fopen(BmpName,rb);28.
7、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
8、,dlg.m_yPY)表示图像平移的坐标38. /*先用Plave计算出平移后的起始坐标,其他的坐标赋值为0黑色39. /*然后依次平移坐标,空的赋为黑色,否则填充40. /*/41. 42. /*/43. /*严重错误1:数组变量赋值相等44. /*在View.h中定义变量BYTE*m_pImage读入图片数据后的指针45. /*建立临时变量数组,让它平移变换unsignedchar*ImageSize46. /*ImageSize=m_pImage(错误)47. /*会导致ImageSize赋值变换时m_pImage也产生了变换,所以输出全为黑色48. /*因为它俩指向了相同的数组地址49
9、. /*解决方法:使用下面C+的new方法动态分配或for循环i=m_nImage赋值50. /*/51. 52. /*临时变量存储的像素与m_pImage相同,便于处理图像*/53. unsignedchar*ImageSize;54. ImageSize=newunsignedcharm_nImage;/new和delete有效的进行动态内存的分配和释放55. 56. intPlace;/建立临时坐标记录起始坐标(0,0)平移过来的位置57. intm_pImagePlace;/原始图像平移为(0,0)图像把它平移到Place位置58. unsignedcharblack;/填充黑色=05
10、9. 60. /*/61. /*for(inti=0;im_nHeight;i+)62. /*for(intj=0;jm_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. intcountWidth=0;/记录每行的像素个数,满行时变回071.
11、 intnumber=0;/数字记录使用的像素行数,平移时使用72. 73. for(inti=0;im_nImage;i+)74. 75. /*如果每行的像素填满时清为0*/76. if(countWidth=m_nWidth*3)77. countWidth=0;78. 79. 80. /*第一部分:到平移后像素位置前面的所有像素点赋值为黑色*/81. if(i=Place&countWidth=Place&countWidth=dlg.m_xPY*3)120. 121. ImageSizei=m_pImagem_pImagePlace;122. m_pImagePlace+;123. c
12、ountWidth+;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标记重新绘制图片,代码如下:cppvie
13、w plaincopy1. 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)位移量时可能出现如下。他是因为BMP格式有个非常重要的规定,要求每一扫描的字节数据必须能被4整除,也就是Dword对齐(长度4字节),如果图像的一行字节数不能被4整除,就需
14、要在每行末尾不起0达到标准。 例如一行像素为97字节,我们就需要补3个字节吗,数值可以是0,但是我们在BMP格式的信息头里说明了其宽度,所以补齐后对我们没有影响,所以后面补若干个字节的0即可直到被4整除。 通过后面的图像缩放后,我从学做了一遍这个补齐的缩放。代码如下,能够实现完美平移。nice啊cppview plaincopy1. voidCImageProcessingView:OnJhbhPy()2. 3. if(numPicture=0)4. AfxMessageBox(载入图片后才能空间平移!,MB_OK,0);5. return;6. 7. /定义采样对话框也是用来空间变换平移的坐
15、标8. CImagePYDlgdlg;9. if(dlg.DoModal()=IDOK)/显示对话框10. 11. /采样坐标最初为图片的自身像素12. if(dlg.m_xPYm_nWidth|dlg.m_yPYm_nHeight)13. AfxMessageBox(图片平移不能为超过原图长宽!,MB_OK,0);14. return;15. 16. AfxMessageBox(图片空间变换-平移!,MB_OK,0);17. 18. /打开临时的图片读写文件19. FILE*fpo=fopen(BmpName,rb);20. FILE*fpw=fopen(BmpNameLin,wb+);21
16、. fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);22. fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);23. 24. intnum;/记录每行多余的图像素数个数25. intsfSize;/补齐后的图像大小26. /重点:图像的每行像素都必须是4的倍数:1*1的图像为rgb00H27. if(m_nWidth*3%4!=0)28. 29. num=(4-m_nWidth*3%4);30. sfSize=(m_nWidth*3+num)*m_nHeight;/每行多number个31. 32. else33. 34. num=0;35. sfSize=m_nWidth*m_nHeight*3;36. 37. /注意:假如最后一行像素不足,我默认处理为完整的一行,不足补00H38. /总之处理后的图像总是m*n且为4倍数,每行都完整存在39. 40. /*更改文件头信息定义临时文件头结构变量*/41.
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1