////////////////////////////////////////////////////////////////
//参数说明:
// HWND hWnd:窗口句柄
//程序说明:图像的旋转
BOOL Rotation(HWND hWnd)
{
//定义对话框处理程序
DLGPROC dlgInputBox = NULL;
//设定偏移、内存、每行字节数
DWORD OffBits,SrcBufSize,DstBufSize,DstLineBytes;
//文件信息头指针
LPBITMAPINFOHEADER lpImgData;
//数据区指针
LPSTR lpPtr;
HLOCAL hTempImgData;
//中间转换用的文件信息头指针
LPBITMAPINFOHEADER lpTempImgData;
//转换用的数据去指针
LPSTR lpTempPtr;
//定义了旋转系数
float SrcX1,SrcY1,SrcX2,SrcY2,SrcX3,SrcY3,SrcX4,SrcY4;
float DstX1,DstY1,DstX2,DstY2,DstX3,DstY3,DstX4,DstY4;
//新旧文件的宽高
DWORD Wold,Hold,Wnew,Hnew;
//定义一个HDC
HDC hDc;
HFILE hf;
//用来计算象素的位置
DWORD x0,y0,x1,y1;
//两个三角变量
float cosa,sina;
float num1,num2;
//两个文件头结构
BITMAPFILEHEADER DstBf;
BITMAPINFOHEADER DstBi;
//实例化对话框
dlgInputBox = (DLGPROC) MakeProcInstance ( (FARPROC)InputBox, ghInst );
DialogBox (ghInst, "INPUTBOX", hWnd, dlgInputBox);
FreeProcInstance ( (FARPROC) dlgInputBox );
//产生旋转角度
RotateAngle=(float)RADIAN(RotateAngle);
//得到旋转的三角数值
cosa=(float)cos((double)RotateAngle);
sina=(float)sin((double)RotateAngle);
//源图像宽高
Wold=bi.biWidth;
Hold=bi.biHeight;
//计算源图像旋转后要显示的区域
SrcX1=(float)(-0.5*Wold);
SrcY1=(float)(0.5*Hold);
SrcX2=(float)(0.5*Wold);
SrcY2=(float)(0.5*Hold);
SrcX3=(float)(-0.5*Wold);
SrcY3=(float)(-0.5*Hold);
SrcX4=(float)(0.5*Wold);
SrcY4=(float)(-0.5*Hold);
//新图像对应数值
DstX1=cosa*SrcX1+sina*SrcY1;
DstY1=-sina*SrcX1+cosa*SrcY1;
DstX2=cosa*SrcX2+sina*SrcY2;
DstY2=-sina*SrcX2+cosa*SrcY2;
DstX3=cosa*SrcX3+sina*SrcY3;
DstY3=-sina*SrcX3+cosa*SrcY3;
DstX4=cosa*SrcX4+sina*SrcY4;
DstY4=-sina*SrcX4+cosa*SrcY4;
//新图像的宽高
Wnew = (DWORD)(max(fabs(DstX4-DstX1), fabs(DstX3-DstX2))+0.5);
Hnew = (DWORD)(max(fabs(DstY4-DstY1), fabs(DstY3-DstY2))+0.5);
num1=(float)( -0.5*Wnew*cosa-0.5*Hnew*sina+0.5*Wold);
num2=(float)(0.5*Wnew*sina-0.5*Hnew*cosa+0.5*Hold);
//得到数据到文件头的偏移
OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);
//源图像所需内存
SrcBufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
ImgWidth=Wnew;
ImgHeight=Hnew;
//目标图像每行字节数
DstLineBytes=(DWORD)WIDTHBYTES(Wnew*bi.biBitCount);
//目标图像所需内存
DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+(DWORD)DstLineBytes*Hnew);
//查看内存分配
if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL)
{
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
//锁定内存区域指针指向数据区
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);
//转换成字节型指针
lpPtr=(char *)lpImgData;
lpTempPtr=(char *)lpTempImgData;
//初始化内存
memset(lpTempPtr,(BYTE)255,DstBufSize);
memcpy(lpTempPtr,lpPtr,OffBits);
//得到新的文件头和文件信息头
memcpy((char *)&DstBf,(char *)&bf,sizeof(BITMAPFILEHEADER));
memcpy((char *)&DstBi,(char *)&bi,sizeof(BITMAPINFOHEADER));
DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER);
DstBi.biWidth=Wnew;
DstBi.biHeight=Hnew;
//用新文件信息覆盖文件信息头内容
memcpy(lpTempPtr,(char *)&DstBi,sizeof(BITMAPINFOHEADER));
//旋转操作
for(y1=0;y1<Hnew;y1++)
for(x1=0;x1<Wnew;x1++){
//得到横坐标和纵坐标在员图中的位置
x0= (DWORD)(x1*cosa+y1*sina+num1);
y0= (DWORD)(-1.0f*x1*sina+y1*cosa+num2);
//临界判断
if( (x0>=0) && (x0<Wold) && (y0>=0) && (y0<Hold))
{
//得到数据区位置
lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y0*LineBytes)+x0;
lpTempPtr=(char *)lpTempImgData+(DstBufSize-DstLineBytes-y1*DstLineBytes)+x1;
//赋值
*lpTempPtr=*lpPtr;
}
}
//得到窗口的DC
hDc=GetDC(hWnd);
if(hBitmap!=NULL)
DeleteObject(hBitmap);
//创建位图
hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,
(LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);
//保存位图文件
hf=_lcreat("c:\\rotation.bmp",0);
_lwrite(hf,(LPSTR)&DstBf,sizeof(BITMAPFILEHEADER));
_lwrite(hf,(LPSTR)lpTempImgData,DstBufSize);
_lclose(hf);
//释放资源
ReleaseDC(hWnd,hDc);
LocalUnlock(hTempImgData);
LocalFree(hTempImgData);
GlobalUnlock(hImgData);
return TRUE;
}
Visual C++数字图像常用算法
需积分: 0 37 浏览量
更新于2007-11-19
收藏 21KB RAR 举报
在计算机视觉领域,Visual C++是一种广泛用于实现数字图像处理算法的编程语言,因为它提供了强大的性能和灵活性。本文将深入探讨在Visual C++中实现的一些关键数字图像处理算法,包括Hough变换、拉普拉斯高斯边缘检测、维纳滤波处理以及阈值变换。
1. **Hough变换**:
Hough变换是识别图像中直线的一种方法。它通过在参数空间中创建累加器来找到图像中的直线。在Visual C++中,我们首先对图像进行边缘检测,然后在Hough空间中为每个边缘像素创建一条直线参数集。累加器在所有可能的参数上累加,最终找到峰值,这些峰值对应于图像中的实际直线。这个算法在交通标志识别、文字检测等领域非常有用。
2. **拉普拉斯高斯边缘检测**:
拉普拉斯算子是一种二阶导数算子,可以用于检测图像的边缘。然而,由于其对噪声敏感,通常与高斯滤波器结合使用,形成拉普拉斯高斯边缘检测。高斯滤波器先平滑图像,减少噪声,然后应用拉普拉斯算子来检测边缘。这种方法在保持边缘细节的同时提高了边缘检测的准确性。在Visual C++中,可以使用OpenCV库来实现这一过程。
3. **维纳滤波处理**:
维纳滤波是一种用于图像去噪的统计方法,特别适用于去除加性高斯噪声。它基于图像的先验知识(如自相关性和互相关性)来恢复原始信号。在Visual C++,我们可以使用二维维纳滤波器对图像进行处理,以最小化重构误差,同时保持图像的细节和结构。OpenCV库也提供了实现维纳滤波的函数。
4. **阈值变换**:
阈值变换是图像分割的基础,它将图像像素值分为两类,例如背景和前景。在Visual C++中,我们可以根据像素值设定一个或多个阈值,将像素值低于阈值的部分设为一种颜色(通常是黑色),高于阈值的部分设为另一种颜色(通常是白色)。常见的阈值选择方法有全局阈值、Otsu's二值化和自适应阈值。这种方法广泛应用于文本识别、目标检测和医学图像分析。
以上这些算法在实际应用中常常组合使用,以达到更复杂的图像处理目的。例如,先使用高斯滤波器平滑图像,再用Hough变换检测直线,或者结合拉普拉斯高斯边缘检测和阈值变换进行图像分割。在Visual C++中,这些操作可以通过直接调用OpenCV等库的函数实现,大大简化了开发流程。了解并熟练掌握这些算法对于提升图像处理项目的效果至关重要。
xiao_xiang
- 粉丝: 0
- 资源: 1
最新资源
- 硅酸钠块行业分析:2023年全球市场规模大约为349百万美元.docx
- 光学扩散膜行业分析:2023年全球市场规模大约为352百万美元.docx
- 合成生物学技术行业分析:全球收入达到1279.6百万美元.docx
- 海上能源无人潜水器市场分析:2023年全球市场规模为854百万美元.docx
- 呼气分子诊断行业分析:2023年全球市场规模大约为234百万美元.docx
- 环氧豆油丙烯酸酯行业分析:2023年全球市场规模大约为871百万美元.docx
- 滑雪头盔式耳机行业分析:2023年全球市场规模大约为51.5百万美元.docx
- 幻想(虚拟)体育行业分析:北美和欧洲占全球约70%的市场份额.docx
- 会话营销软件行业分析:全球收入约为564.9百万美元.docx
- 火灾警报设备行业分析:全球市场收入约为19130百万美元.docx
- 基础unity,控制物体的简单移动,值得学习一下
- 活动行业分析:全球收入约为342100百万美元.docx
- 机械键盘行业分析:2023年全球市场规模大约为1245百万美元.docx
- 即时物流行业分析:2023年全球市场规模大约为23770百万美元.docx
- 奖励管理软件行业研究:全球收入约为692.5百万美元.docx
- 洁净室环境在线监测软件行业分析:北美占有约25%的全球市场份额.docx