1、求职设计求职设计 江振忠(2005年4月20日)一 .软件工程 1. 要求写出软件的分析说明与设计说明2. 建立对象模型3. 结构设计4. 类说明5. 其他说明二 数学建模1. 问题分析2. 建立模型3. 解决问题4. 误差分析三 算法实现图1300mm4mm4mm300mm题目:设计一个图形在一个容器中的排序问题,要求定义15个不同的单连通域的不一样的图形,在一个300mm*300mm的容器中排序,使的剩下的面积最大。并且图形之间的间距为4mm。建立模型,编程求解答。求S的最大值软件实现要求: 可以在其他机子上运行,可以读取其机子上的图形运行程序,并且能输出结果!并且要求可以图形方向变换,以
2、求最最好的排序!碎片图像无缝拼合技术的VC+实现一、 引言 在测绘、文博等行业经常会遇到这样一种情况:观测对象比较大,为保证分辨率又不能将其全部照下,只能进行局部照相,事后再将这些局部照相的重合部分去掉,拼合成一幅完整的图像。以前多采用手工拼合,误差较大,往往不能很好的实现无缝拼合,即使有少量的专业设备,成本也普遍较高。其实只需将照片通过扫描仪将其录入到计算机中,通过程序处理,完全能很好的实现多幅图像的无缝拼合,满足实际需要,而且对于文博行业中常会遇到的破碎的、不规则对象如古旧字画残片等也能很好的进行无缝拼合。本文就对针对该程序的实现原理及过程做了简要的介绍。 二、 程序设计原理 首先我们从实
3、际出发,我们是通过进行局部照相的手段来保存整体的全部信息,而要保证这些局部照片所含的信息之和能包括整体的全部信息就必然的使每两幅邻近的图片有一部分交叠的部分,这样才能保证在将整体对象划分为若干局部照片而后再拼合成整体图像的过程中不遗漏任何信息,即该划分、拼合的整个过程是无损的。既然如此,我们只需能保证让两相邻图片的重叠部分能完全重合,那么我们也就能够肯定在此状态下的这两幅图像实现了无缝拼合。所以,问题就转换为使相邻图片的重叠部分能完全重合,而判断两相同的图像片段是否完全重叠可以用光栅掩码来进行直观的判断,比如我们可以采用异或的掩码,当相同位置上的两幅图片的像素相同时就为0即黑色,所以可以对两图
4、片进行移动,只要重叠部分全黑,则表明此时两图像的重叠部分已准确的重合了,而此时也实现了图像的无缝拼合。此后只需再采用或的光栅掩码将合并后的图像显示出来,再通过拷屏等手段将其存盘即可。在实现拼合的全过程中主要涉及到图像的拖放、图像文件的读取及显示、光栅掩码、拷屏以及内存位图的保存等多种技术。接下来就对这些技术的具体应用进行介绍。 三、 程序的具体实现 在进行拼合之前,首先要将从扫描仪录入的图像从文件读取到内存中,并显示出来。由于在拼合时采取的光栅操作掩码是异或,所以为保持图像的原始面貌,可以在消息WM_ERASEBKGND 的响应函数中用PatBlt函数将整个客户区的初始背景设定为黑色: pDC
5、-PatBlt(0,0,rect.Width(),rect.Height(), BLACKNESS); return TRUE; 读取位图文件可以用LoadImage函数来实现,m_sPath1指定了文件的路径,LR_LOADFROMFILE属性指定从文件中读取位图,返回值为该位图的句柄: HBITMAP hbitmap; hbitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(), m_sPath1, IMAGE_BITMAP,0,0, LR_LOADFROMFILE|LR_CREATEDIBSECTION); 之后我们就可以创建一个和当前设备环境兼容
6、的内存设备环境hMemDC1,并将刚才读取到内存的位图放置到该设备环境中: hMemDC1=:CreateCompatibleDC(NULL); SelectObject(hMemDC1,hbitmap); :DeleteObject(hbitmap); /释放掉用过的位图句柄 Invalidate(); 至于位图的显示,由于需要频繁的拖动和其他处理,将其放置于OnDraw函数中较为合理,需要更新显示时只需显式地用Invalidate()函数刷新即可。OnDraw()中的显示位图部分最好用BitBlt函数来完成,该函数负责把hMemDC1中的位图放置到pDC页面中以完成内存页面的置换,其处理速
7、度还是比较快的: :BitBlt(pDC-m_hDC,m_nX1,m_nY1, m_nWidth1,m_nHeight1,hMemDC1,0,0,m_dwRop); 函数中的m_dwRop变量对光栅操作码进行设置,初始为SRCINVERT即光栅异或操作,当拼合成功需要显示合并后的效果时再将其设定为SRCPAINT光栅或操作。 我们可以通过对鼠标消息响应函数的编程来实现在客户区内的位图拖放,按照Windows系统的习惯,首先在鼠标左键的响应函数中通过PtInRect()函数判断鼠标在左键按下时是否是落在位图上,如果是就可以在鼠标左键弹起之前将图片随鼠标拖动了,显然这部分应在WM_MOUSEMOV
8、E消息的响应函数内编写代码: if(m_bCanMove1=true) /在移动之前鼠标左键是在图片上点击的 int dx=m_nOldX1-m_nX1; /计算鼠标距离图片原点的距离 int dy=m_nOldY1-m_nY1; m_nX1=point.x-dx; /计算新的图片原点的坐标(客户区坐标) m_nY1=point.y-dy; Invalidate(); /更新视图 m_nOldX1=point.x; /保存上一次的鼠标位置 m_nOldY1=point.y; 到此为止,可以运行程序对多幅碎片图像进行拼合了,用鼠标拖动一幅图像在另一幅图像边缘移动,由于采用了异或的光栅掩码,两幅图
9、片交叠的地方颜色会发生改变,但只有完全重合时才会全黑,表明此时的拼合是无缝的,将掩码换为或即可将拼合后的图像显示出来。但此时只是保留在内存中,还要经过进一步的处理,才能将合并后的图像存盘保留。 首先要对合并后的图像所在的矩形框的位置、大小进行判断,可以用下面的类似代码来完成(本例同时最多能有4幅图像进行拼合): int temp1,temp2,x0,y0,x1,y1; temp1=m_nX1 if(m_sPath3!=)/如果有3幅图片参与拼合 if(m_sPath4!=)/如果有4幅图片参与拼合 temp2=m_nX3 else temp2=m_nX3; x0=temp1 else x0=t
10、emp1; temp1=m_nX1+m_nWidth1m_nX2+m_nWidth2?m_nX1+m_nWidth1:m_nX2+m_nWidth2; if(m_sPath3!=) if(m_sPath4!=) temp2=m_nX3+m_nWidth3m_nX4+m_nWidth4?m_nX3+m_nWidth3:m_nX4+m_nWidth4; else temp2=m_nX3+m_nWidth3; x1=temp1temp2?temp1:temp2; else x1=temp1; 可以用类似的代码计算出y0和y1。在进行屏幕截图之前必须将由x0,y0,x1,y1构成的矩形由客户坐标转换成
11、屏幕坐标,可以用ClientToScreen()函数来实现。下面是将屏幕指定区域以位图形式拷贝到内存中去的函数的主要实现代码: HBITMAP CImageView:CopyScreenToBitmap(LPRECT lpRect) / 确保选定区域不为空矩形 if(IsRectEmpty(lpRect) return NULL; /为屏幕创建设备描述表 hScrDC = CreateDC(DISPLAY, NULL, NULL, NULL); /为屏幕设备描述表创建兼容的内存设备描述表 hMemDC = CreateCompatibleDC(hScrDC); / 创建一个与屏幕设备描述表兼容
12、的位图 hBitmap = CreateCompatibleBitmap(hScrDC, lpRect-Width(),lpRect-Height(); / 把新位图选到内存设备描述表中 hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); / 把屏幕设备描述表拷贝到内存设备描述表中 BitBlt(hMemDC, 0, 0, lpRect-Width(),lpRect-Height, hScrDC, lpRect-left lpRect-top, SRCCOPY); /得到屏幕位图的句柄 hBitmap =(HBITMAP)SelectObj
13、ect(hMemDC, hOldBitmap); /清除 DeleteDC(hScrDC); DeleteDC(hMemDC); / 返回位图句柄 return hBitmap; 当把拼合后的区域拷贝到内存,并获取到该内存位图的句柄后可以将其通过剪贴板传送到其他图形处理软件中进行进一布的处理,也可以按照位图的格式直接将其保存成文件,为方便计,本例采用了后者。其实现过程主要是根据刚才获取到的内存位图句柄按格式填充BMP文件的信息头以及像素阵列,下面就结合实现的关键代码进行介绍: 首先获取设备描述表句柄,并用函数GetDeviceCaps()获取到当前显示分辨率下每个像素所占字节数,并据此计算出调
14、色板的大小: hDC = CreateDC(DISPLAY,NULL,NULL,NULL); iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); DeleteDC(hDC); if (iBits = 1) wBitCount = 1; else if (iBits= 4) wBitCount = 4; else if (iBits= 8) wBitCount = 8; else if (iBits = 24) wBitCount = 24; /计算调色板大小 然后就可以设置位图信息头结构了,其中bi 是BITM
15、APINFOHEADER 结构的实例对象: if (wBitCount = 8) dwPaletteSize = (1SetFieldType(CDaoFieldExchange:outputColumn); DFX_Binary(pFX, _T(Images), m_Images);/以二进制方式在Images字段和m_Images变量间交换数据 file:/AFX_FIELD_MAP 有了该类,就可以定义相应的对象来与数据库中的图像字段交换数据,下面定义的函数GetImageData()说明了如何根据读取的OLE字段数据生成待显示的图像,需要注意的是该函数中使用的CBitmap类的变量Bi
16、tmap是预定义的一个全局变量: BOOL CImageDlg: GetImageData(CByteArray & DBArray) CByteArray Array; Array.Copy( DBArray); int HeaderLen = 78 + sizeof(BITMAPFILEHEADER); file:/确定图像头信息的起始位置 Array.RemoveAt( 0, HeaderLen ); / 移动到图像头信息的起始位置 BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)Array.GetData() ; BITMAPINFO &bmInfo = *(LPBITMAPINFO)Array.GetData() ; file:/得到图像数据的头信息 int nColors=bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 1 8 ) lpDIBBits=(LPVOID)(LPDWORD)(bmInfo.bmiColors+bmInfo.bmiHeader.biClrUsed)+ (bmInfo.bmiHead
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1