图像预处理第5步:倾斜度调整
//图像预处理第5步:倾斜度调整 void CChildView::OnImgprcAdjustSlope() { SlopeAdjust(m_hDIB); //在屏幕上显示位图 CDC* pDC=GetDC(); DisplayDIB(pDC,m_hDIB); }
/********************************************************* * 函数名称: * SlopeAdjust() * * 参数: * HDIB hDIB -原图像的句柄 * * 返回值: * 无 * * 功能: * 通过对图像左右半边平均高度的统计来进行倾斜的调整 * * 说明: * 只能对2值图像进行处理 * ****************************************************************/ void SlopeAdjust(HDIB hDIB) { // 指向DIB的指针 LPSTR lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)hDIB); // 指向DIB象素指针 LPSTR lpDIBBits; // 找到DIB图像象素起始位置 lpDIBBits = ::FindDIBBits(lpDIB); // 指向源图像的指针 unsigned char* lpSrc; // 循环变量 LONG i; LONG j; // 图像每行的字节数 LONG lLineBytes; //图像的长度 LONG lWidth; //图像的宽度 LONG lHeight; //获取图像的长度 lWidth=::DIBWidth ((char*)lpDIB); //获取图像的宽度 lHeight=::DIBHeight ((char*)lpDIB); // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); //图像左半边的平均高度 double leftaver=0.0; //图像右半边的平均高度 double rightaver=0.0; //图像的倾斜度 double slope; //统计循环变量 LONG counts=0; //扫描左半边的图像,求黑色象素的平均高度 //行 for (i=0;i<lHeight;i++) { //列 for (j=0;j<lWidth/2;j++) { //指向第i行第j个象素的指针 lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j; //如果为黑点 if (*lpSrc == 0) { //对其高度进行统计叠加 counts +=lWidth/2 -j; leftaver += i*(lWidth/2 -j); } } } //计算平均高度 leftaver /= counts; //将统计循环变量重新赋值 counts =0; //扫描右半边的图像,求黑色象素的平均高度 //行 for (i =0;i<lHeight;i++) { //列 for (j=lWidth/2;j<lWidth;j++) { //指向第i行第j个象素的指针 lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j; //如果为黑点 if (*lpSrc == 0) { //进行统计叠加 counts +=lWidth -j; rightaver += i*(lWidth -j); } } } //计算右半边的平均高度 rightaver /= counts; //计算斜率 slope = (leftaver - rightaver) / (lWidth/2); //指向新的图像象素起始位置的指针 LPSTR lpNewDIBBits; //指向新图像的指针 LPSTR lpDst; //新图像的句柄 HLOCAL nNewDIBBits=LocalAlloc(LHND,lLineBytes*lHeight); //锁定内存 lpNewDIBBits=(char*)LocalLock(nNewDIBBits); //指向新图像象素的指针 lpDst=(char*)lpNewDIBBits; //为新图像赋初始值 memset(lpDst,(BYTE)255,lLineBytes*lHeight); //象素点的灰度值 int gray; //位置映射值 int i_src; //根据斜率,把当前新图像的点映射到源图像的点 //行 for (i=0;i<lHeight;i++) { //列 for (j=0;j<lWidth;j++) { //计算映射位置 i_src=int(i - (j-lWidth/2)*slope); //如果点在图像外,象素置白色 if (i_src <0 || i_src >=lHeight ) gray = 255; else { //否则到源图像中找点,取得象素值 //指向第i_src行第j个象素的指针 lpSrc=(unsigned char *)lpDIBBits + lLineBytes * i_src + j; gray = *lpSrc; } //把新图像的点用得到的象素值填充 //指向第i行第j个象素的指针 lpDst = (char *)lpNewDIBBits + lLineBytes * i + j; *lpDst=gray; } } // 将新的图像的内容拷贝到旧的图像中 memcpy(lpDIBBits,lpNewDIBBits,lLineBytes*lHeight); // 解除锁定 ::GlobalUnlock ((HGLOBAL)hDIB); }
运行效果:
调整前
调整后
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!