MFC空间几何变换之图像平移镜像旋转缩放详解.docx
- 文档编号:3384091
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:44
- 大小:39.93KB
MFC空间几何变换之图像平移镜像旋转缩放详解.docx
《MFC空间几何变换之图像平移镜像旋转缩放详解.docx》由会员分享,可在线阅读,更多相关《MFC空间几何变换之图像平移镜像旋转缩放详解.docx(44页珍藏版)》请在冰豆网上搜索。
MFC空间几何变换之图像平移镜像旋转缩放详解
MFC空间几何变换之图像平移、镜像、旋转、缩放详解
一.图像平移
前一篇文章讲述了图像点运算(基于像素的图像变换),这篇文章讲述的是图像几何变换:
在不改变图像内容的情况下对图像像素进行空间几何变换的处理方式。
点运算对单幅图像做处理,不改变像素的空间位置;代数运算对多幅图像做处理,也不改变像素的空间位置;几何运算对单幅图像做处理,改变像素的空间位置,几何运算包括两个独立的算法:
空间变换算法和灰度级插值算法。
空间变换操作包括简单空间变换、多项式卷绕和几何校正、控制栅格插值和图像卷绕,这里主要讲述简单的空间变换,如图像平移、镜像、缩放和旋转。
主要是通过线性代数中的齐次坐标变换。
图像平移坐标变换如下:
运行效果如下图所示,其中BMP图片(0,0)像素点为左下角。
其代码核心算法:
1.在对话框中输入平移坐标(x,y)m_xPY=x,m_yPY=y
2.定义Place=dlg.m_yPY*m_nWidth*3表示当前m_yPY行需要填充为黑色
3.新建一个像素矩阵 ImageSize=newunsignedchar[m_nImage]
4.循环整个像素矩阵处理
for(inti=0;i if(i elseif(i>=Place&&countWidth ImageSize[i]=black; countWidth++; continue; } elseif(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,确定为默认按钮。 设置成下图对话框: 第三步: 在对话框资源模板空白区域双击鼠标—Createanewclass创建一个新类--命名为CImagePYDlg。 会自动生成它的.h和.cpp文件。 打开类向导(CtrlW),选择类名: CImagePYDlg添加成员变量如下图所示,同时在MessageMaps中生成ID_JHBH_PY实现函数。 第四步: 在CImageProcessingView.cpp中添加头文件#include"ImagePYDlg.h",并实现平移。 [cpp] viewplain 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("载入图片后才能空间平移! ",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 *ImageSize 46. /* 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 62. /* for(int j=0 ; 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; //记录每行的像素个数,满行时变回0 71. int number=0; //数字记录使用的像素行数,平移时使用 72. 73. for(int i=0 ; i 74. { 75. /*如果每行的像素填满时清为0*/ 76. if(countWidth==m_nWidth*3) { 77. countWidth=0; 78. } 79. 80. /*第一部分: 到平移后像素位置前面的所有像素点赋值为黑色*/ 81. if(i 82. ImageSize[i]=black; //赋值为黑色 83. continue; 84. } 85. 86. /*第二部分: 平移区域的左边部分赋值为黑色*/ 87. else if(i>=Place && countWidth 88. ImageSize[i]=black; //赋值为黑色 89. countWidth++; 90. continue; 91. } 92. 93. /****************************/ 94. /* 各部分如图所示: 95. /* 000000000000000000000000 96. /* 000000000000000000000000 97. /* 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. /* 000000000000000000000000 114. /* 000000000000000000000000 115. /* 点表示像素部分,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] viewplain copy 1.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整除,就需要在每行末尾不起0达到标准。 例如一行像素为97字节,我们就需要补3个字节吗,数值可以是0,但是我们在BMP格式的信息头里说明了其宽度,所以补齐后对我们没有影响,所以后面补若干个字节的0即可直到被4整除。 通过后面的图像缩放后,我从学做了一遍这个补齐的缩放。 代码如下,能够实现完美平移。 nice啊~ [cpp] viewplain 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_xPY>m_nWidth || dlg.m_yPY>m_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),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. //注意: 假如最后一行像素不足,我默认处理为完整的一行,不足补00H 38. //总之处理后的图像总是m*n且为4倍数,每行都完整存在 39. 40. /*更改文件头信息 定义临时文件头结构变量*/ 41.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 空间 几何 变换 图像 平移 旋转 缩放 详解