MFC空间几何变换之图像平移镜像旋转缩放详解.docx

上传人:牧羊曲112 文档编号:3161424 上传时间:2023-03-11 格式:DOCX 页数:32 大小:49.11KB
返回 下载 相关 举报
MFC空间几何变换之图像平移镜像旋转缩放详解.docx_第1页
第1页 / 共32页
MFC空间几何变换之图像平移镜像旋转缩放详解.docx_第2页
第2页 / 共32页
MFC空间几何变换之图像平移镜像旋转缩放详解.docx_第3页
第3页 / 共32页
MFC空间几何变换之图像平移镜像旋转缩放详解.docx_第4页
第4页 / 共32页
MFC空间几何变换之图像平移镜像旋转缩放详解.docx_第5页
第5页 / 共32页
亲,该文档总共32页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《MFC空间几何变换之图像平移镜像旋转缩放详解.docx》由会员分享,可在线阅读,更多相关《MFC空间几何变换之图像平移镜像旋转缩放详解.docx(32页珍藏版)》请在三一办公上搜索。

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界面-选中Dia

4、log,右键鼠标新建一个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 ImagePYD

5、lg.h,并实现平移。 cpp view plain copy 1. /*/ 2. /* 图像空间几何变换:图像平移 ID_JHBH_PY(几何变换-平移) 3. /* 使用平移对话框:CImagePYDlg dlg 4. /* 算法: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(载入图片后

6、才能空间平移!,MB_OK,0); 13. return; 14. 15. /定义采样对话框也是用来空间变换平移的坐标 16. CImagePYDlg dlg; 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. /打开临时的

7、图片 读写文件 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_nIm

8、age,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 *ImageSize 46. /* ImageSize=

9、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 charm_nImage; /new和delete有效的进行动态内存的分配和释放 55. 56. int Place; /建立临时

10、坐标 记录起始坐标(0,0)平移过来的位置 57. int m_pImagePlace; /原始图像平移为(0,0) 图像把它平移到Place位置 58. unsigned char black; /填充黑色=0 59. 60. /*/ 61. /* for(int i=0 ; im_nHeight ; i+ ) 62. /* for(int j=0 ; jm_nWidth ; j+ ) 63. /* 不能使用的上面的因为可能图像的最后一行没有完整的一行像素 64. /* 这样会出现exe报错,使用m_nImage读写所有像素比较正确 65. /*/ 66. 67. Place=dlg.m_y

11、PY*m_nWidth*3; /前m_yPY行都要填充为黑色 68. black=0; /颜色为黑色 69. m_pImagePlace=0; /图像处事位置为(0,0),把该点像素平移过去 70. int countWidth=0; /记录每行的像素个数,满行时变回0 71. int number=0; /数字记录使用的像素行数,平移时使用 72. 73. for(int i=0 ; im_nImage ; i+ ) 74. 75. /*如果每行的像素填满时清为0*/ 76. if(countWidth=m_nWidth*3) 77. countWidth=0; 78. 79. 80. /*

12、第一部分:到平移后像素位置前面的所有像素点赋值为黑色*/ 81. if(i=Place & countWidth=Place & countWidth=dlg.m_xPY*3) 120. 121. ImageSizei=m_pImagem_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(ImageSiz

13、e,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 copy 1. 2. 3. 4. 5. 6. else /图像几何变换 if(level=200) m_hBitmapChange = (HBITMAP) LoadImage(NULL,BmpNameLin,IMAGE_BITMAP,0,

14、0, LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION); 运行时需要注意一点:BMP图像在处理过程中可能会出现一些斜线,而平移(40,60)位移量时可能出现如下。他是因为BMP格式有个非常重要的规定,要求每一扫描的字节数据必须能被4整除,也就是Dword对齐(长度4字节),如果图像的一行字节数不能被4整除,就需要在每行末尾不起0达到标准。 例如一行像素为97字节,我们就需要补3个字节吗,数值可以是0,但是我们在BMP格式的信息头里说明了其宽度,所以补齐后对我们没有影响,所以后面补若干个字节的0即可直到被4整除。 通过后面的图像缩放后,我从学

15、做了一遍这个补齐的缩放。代码如下,能够实现完美平移。nice啊 cpp view plain copy 1. void CImageProcessingView:OnJhbhPy 2. 3. if(numPicture=0) 4. AfxMessageBox(载入图片后才能空间平移!,MB_OK,0); 5. return; 6. 7. /定义采样对话框也是用来空间变换平移的坐标 8. CImagePYDlg dlg; 9. if( dlg.DoModal=IDOK ) /显示对话框 10. 11. /采样坐标最初为图片的自身像素 12. if( dlg.m_xPYm_nWidth | dlg

16、.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. fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo); 22. fread(&bih,sizeof(BITMAPINFOHEADER),

17、1,fpo); 23. 24. int num; /记录每行多余的图像素数个数 25. int sfSize; /补齐后的图像大小 26. /重点:图像的每行像素都必须是4的倍数:1*1的图像为 r g b 00H 27. 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. else 33. 34. num=0; 35. sfSize=m_nWidth*m_nHeight*3; 36. 37. /注意:假如最后一行像素不足,我默认

18、处理为完整的一行,不足补00H 38. /总之处理后的图像总是m*n且为4倍数,每行都完整存在 39. 40. /*更改文件头信息 定义临时文件头结构变量*/ 41. BITMAPFILEHEADER bfhsf; 42. BITMAPINFOHEADER bihsf; 43. bfhsf=bfh; 44. bihsf=bih; 45. bfhsf.bfSize=sfSize+54; 46. fwrite(&bfhsf,sizeof(BITMAPFILEHEADER),1,fpw); 47. fwrite(&bihsf,sizeof(BITMAPINFOHEADER),1,fpw); 48.

19、fread(m_pImage,m_nImage,1,fpo); 49. 50. CString str; 51. str.Format(补齐=%d,num); 52. AfxMessageBox(str); 53. 54. /*临时变量存储的像素与sfSize相同 new和delete有效的进行动态内存的分配和释放*/ 55. unsigned char *ImageSize; 56. ImageSize=new unsigned charsfSize; 57. 58. int Place; /建立临时坐标 记录起始坐标(0,0)平移过来的位置 59. int m_pImagePlace; /

20、原始图像平移为(0,0) 图像把它平移到Place位置 60. unsigned char black=0; /填充黑色=0 61. unsigned char other=0; /补码00H=0 62. 63. Place=dlg.m_yPY*(m_nWidth*3+num); /前m_yPY行都要填充为黑色 64. m_pImagePlace=0; /图像处事位置为(0,0),把该点像素平移过去 65. int countWidth=0; /记录每行的像素个数,满行时变回0 66. int number=0; /数字记录使用的像素行数,平移时使用 67. 68. for(int i=0 ;

21、 isfSize ; i+ ) 69. 70. /*第一部分:到平移后像素位置前面的所有像素点赋值为黑色*/ 71. if(i=Place & countWidth=Place & countWidth=dlg.m_xPY*3) 87. 88. ImageSizei=m_pImagem_pImagePlace; 89. m_pImagePlace+; 90. countWidth+; 91. if(countWidth=m_nWidth*3) 92. 93. if(num=0) 94. 95. countWidth=0; 96. number+; 97. m_pImagePlace=numbe

22、r*m_nWidth*3; 98. 99. else /num为补0 100. 101. for(int j=0;jnum;j+) 102. 103. i+; 104. ImageSizei=other; 105. 106. countWidth=0; 107. number+; 108. m_pImagePlace=number*(m_nWidth*3+num); /重点:添加Num 109. 110. 111. 112. 113. 114. fwrite(ImageSize,sfSize,1,fpw); 115. fclose(fpo); 116. fclose(fpw); 117. nu

23、mPicture = 2; 118. level=200; /200表示几何变换 119. Invalidate; 120. 121. 运行效果如下图所示,完美平移,其他算法遇到斜线问题类似补齐即可。 二. 图像镜像 1.水平镜像翻转 其变换矩阵如下: X=width-X0-1 (width为图像宽度) Y=Y0 打开类向导,在CImageProcessingView中添加IDs为ID_JHBH_FZ,生成函数,代码如下: cpp view plain copy 1. /* 几何变换 图像翻转:自己对这个功能比较感兴趣,做个图像反转 */ 2. void CImageProcessingVie

24、w:OnJhbhFz 3. 4. if(numPicture=0) 5. AfxMessageBox(载入图片后才能空间反转!,MB_OK,0); 6. return; 7. 8. AfxMessageBox(图片空间变换-反转图像!,MB_OK,0); 9. 10. /打开临时的图片 11. FILE *fpo = fopen(BmpName,rb); 12. FILE *fpw = fopen(BmpNameLin,wb+); 13. fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo); 14. fread(&bih,sizeof(BITMAPINFOHE

25、ADER),1,fpo); 15. fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw); 16. fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw); 17. fread(m_pImage,m_nImage,1,fpo); 18. 19. /*new和delete有效的进行动态内存的分配和释放*/ 20. unsigned char *ImageSize; 21. ImageSize=new unsigned charm_nImage; 22. int countWidth=0; /记录每行的像素个数,满行时变回0 23.

26、 int Place; /记录图像每行的位置,便于图像反转 24. int number=0; /数字记录使用的像素行数 25. Place=m_nWidth*3-1; 26. 27. /翻转矩阵: y=y0 x=width-x0-1 28. for(int i=0 ; im_nImage ; i+ ) 29. 30. if(countWidth=m_nWidth*3) 31. 32. countWidth=0; 33. 34. ImageSizei=m_pImagePlace; /(0,0)赋值(0,width*3-1)像素 35. Place-; 36. countWidth+; 37. if(countWidth=m_nWidth*3) 38. 39. number+; 40. Place=number*m_nWidth*3-1; 41. 42. 43. 44. fwrite(ImageSize,m_nIma

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号