狠狠爱成人网_日韩一级在线_国产综合自拍_亚洲精品韩国_亚洲视频导航_麻豆成人在线播放_欧美jjzz_一区在线视频观看_美脚丝袜一区二区三区在线观看_欧美91视频

當(dāng)前位置:系統(tǒng)之家 > 技術(shù)開發(fā)教程 > 詳細(xì)頁面

碎片圖像無縫拼合技術(shù)的VC++完成

碎片圖像無縫拼合技術(shù)的VC++完成

更新時(shí)間:2024-04-09 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

信息產(chǎn)業(yè)部電子第二十二研究所青島分所 郎銳  

一、 引言  

在測繪、文博等行業(yè)經(jīng)常會(huì)遇到這樣一種情況:觀測對象比較大,為保證分辨率又不能將其全部照下,只能進(jìn)行局部照相,事后再將這些局部照相的重合部分去掉,拼合成一幅完整的圖像。以前多采用手工拼合,誤差較大,往往不能很好的實(shí)現(xiàn)無縫拼合,即使有少量的專業(yè)設(shè)備,成本也普遍較高。其實(shí)只需將照片通過掃描儀將其錄入到計(jì)算機(jī)中,通過程序處理,完全能很好的實(shí)現(xiàn)多幅圖像的無縫拼合,滿足實(shí)際需要,而且對于文博行業(yè)中常會(huì)遇到的破碎的、不規(guī)則對象如古舊字畫殘片等也能很好的進(jìn)行無縫拼合。本文就對針對該程序的實(shí)現(xiàn)原理及過程做了簡要的介紹。

二、 程序設(shè)計(jì)原理

首先我們從實(shí)際出發(fā),我們是通過進(jìn)行局部照相的手段來保存整體的全部信息,而要保證這些局部照片所含的信息之和能包括整體的全部信息就必然的使每兩幅鄰近的圖片有一部分交疊的部分,這樣才能保證在將整體對象劃分為若干局部照片而后再拼合成整體圖像的過程中不遺漏任何信息,即該劃分、拼合的整個(gè)過程是無損的。既然如此,我們只需能保證讓兩相鄰圖片的重疊部分能完全重合,那么我們也就能夠肯定在此狀態(tài)下的這兩幅圖像實(shí)現(xiàn)了無縫拼合。所以,問題就轉(zhuǎn)換為使相鄰圖片的重疊部分能完全重合,而判斷兩相同的圖像片段是否完全重疊可以用光柵掩碼來進(jìn)行直觀的判斷,比如我們可以采用"異或"的掩碼,當(dāng)相同位置上的兩幅圖片的像素相同時(shí)就為0即黑色,所以可以對兩圖片進(jìn)行移動(dòng),只要重疊部分全黑,則表明此時(shí)兩圖像的重疊部分已準(zhǔn)確的重合了,而此時(shí)也實(shí)現(xiàn)了圖像的無縫拼合。此后只需再采用"或"的光柵掩碼將合并后的圖像顯示出來,再通過拷屏等手段將其存盤即可。在實(shí)現(xiàn)拼合的全過程中主要涉及到圖像的拖放、圖像文件的讀取及顯示、光柵掩碼、拷屏以及內(nèi)存位圖的保存等多種技術(shù)。接下來就對這些技術(shù)的具體應(yīng)用進(jìn)行介紹。

三、 程序的具體實(shí)現(xiàn)

在進(jìn)行拼合之前,首先要將從掃描儀錄入的圖像從文件讀取到內(nèi)存中,并顯示出來。由于在拼合時(shí)采取的光柵操作掩碼是"異或",所以為保持圖像的原始面貌,可以在消息WM_ERASEBKGND 的響應(yīng)函數(shù)中用PatBlt函數(shù)將整個(gè)客戶區(qū)的初始背景設(shè)定為黑色:

……
pDC->PatBlt(0,0,rect.Width(),rect.Height(), BLACKNESS);
return TRUE;

讀取位圖文件可以用LoadImage函數(shù)來實(shí)現(xiàn),m_sPath1指定了文件的路徑,LR_LOADFROMFILE屬性指定從文件中讀取位圖,返回值為該位圖的句柄:

……
HBITMAP hbitmap;
hbitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),
m_sPath1,
IMAGE_BITMAP,0,0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);

之后我們就可以創(chuàng)建一個(gè)和當(dāng)前設(shè)備環(huán)境兼容的內(nèi)存設(shè)備環(huán)境hMemDC1,并將剛才讀取到內(nèi)存的位圖放置到該設(shè)備環(huán)境中:

hMemDC1=::CreateCompatibleDC(NULL);
SelectObject(hMemDC1,hbitmap);
::DeleteObject(hbitmap); //釋放掉用過的位圖句柄  
Invalidate();

至于位圖的顯示,由于需要頻繁的拖動(dòng)和其他處理,將其放置于OnDraw函數(shù)中較為合理,需要更新顯示時(shí)只需顯式地用Invalidate()函數(shù)刷新即可。OnDraw()中的顯示位圖部分最好用BitBlt函數(shù)來完成,該函數(shù)負(fù)責(zé)把hMemDC1中的位圖放置到pDC頁面中以完成內(nèi)存頁面的置換,其處理速度還是比較快的:

……
::BitBlt(pDC->m_hDC,m_nX1,m_nY1, m_nWidth1,m_nHeight1,hMemDC1,0,0,m_dwRop);
……

函數(shù)中的m_dwRop變量對光柵操作碼進(jìn)行設(shè)置,初始為SRCINVERT即光柵異或操作,當(dāng)拼合成功需要顯示合并后的效果時(shí)再將其設(shè)定為SRCPAINT光柵或操作。

我們可以通過對鼠標(biāo)消息響應(yīng)函數(shù)的編程來實(shí)現(xiàn)在客戶區(qū)內(nèi)的位圖拖放,按照Windows系統(tǒng)的習(xí)慣,首先在鼠標(biāo)左鍵的響應(yīng)函數(shù)中通過PtInRect()函數(shù)判斷鼠標(biāo)在左鍵按下時(shí)是否是落在位圖上,如果是就可以在鼠標(biāo)左鍵彈起之前將圖片隨鼠標(biāo)拖動(dòng)了,顯然這部分應(yīng)在WM_MOUSEMOVE消息的響應(yīng)函數(shù)內(nèi)編寫代碼:

……
if(m_bCanMove1==true) //在移動(dòng)之前鼠標(biāo)左鍵是在圖片上點(diǎn)擊的
{
int dx=m_nOldX1-m_nX1; //計(jì)算鼠標(biāo)距離圖片原點(diǎn)的距離
int dy=m_nOldY1-m_nY1;
m_nX1=point.x-dx; //計(jì)算新的圖片原點(diǎn)的坐標(biāo)(客戶區(qū)坐標(biāo))
m_nY1=point.y-dy;
Invalidate(); //更新視圖
}
m_nOldX1=point.x; //保存上一次的鼠標(biāo)位置
m_nOldY1=point.y;
……

到此為止,可以運(yùn)行程序?qū)Χ喾槠瑘D像進(jìn)行拼合了,用鼠標(biāo)拖動(dòng)一幅圖像在另一幅圖像邊緣移動(dòng),由于采用了"異或"的光柵掩碼,兩幅圖片交疊的地方顏色會(huì)發(fā)生改變,但只有完全重合時(shí)才會(huì)全黑,表明此時(shí)的拼合是無縫的,將掩碼換為"或"即可將拼合后的圖像顯示出來。但此時(shí)只是保留在內(nèi)存中,還要經(jīng)過進(jìn)一步的處理,才能將合并后的圖像存盤保留。

首先要對合并后的圖像所在的矩形框的位置、大小進(jìn)行判斷,可以用下面的類似代碼來完成(本例同時(shí)最多能有4幅圖像進(jìn)行拼合):

……
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=temp1;
……
temp1=m_nX1+m_nWidth1>m_nX2+m_nWidth2?m_nX1+m_nWidth1:m_nX2+m_nWidth2;
if(m_sPath3!="")
{
if(m_sPath4!="")
temp2=m_nX3+m_nWidth3>m_nX4+m_nWidth4?m_nX3+m_nWidth3:m_nX4+m_nWidth4;
else
temp2=m_nX3+m_nWidth3;
x1=temp1>temp2?temp1:temp2;
}
else
x1=temp1;

可以用類似的代碼計(jì)算出y0和y1。在進(jìn)行屏幕截圖之前必須將由x0,y0,x1,y1構(gòu)成的矩形由客戶坐標(biāo)轉(zhuǎn)換成屏幕坐標(biāo),可以用ClientToScreen()函數(shù)來實(shí)現(xiàn)。下面是將屏幕指定區(qū)域以位圖形式拷貝到內(nèi)存中去的函數(shù)的主要實(shí)現(xiàn)代碼:

HBITMAP CImageView::CopyScreenToBitmap(LPRECT lpRect)
{
……
// 確保選定區(qū)域不為空矩形  
if(IsRectEmpty(lpRect))  
return NULL;
//為屏幕創(chuàng)建設(shè)備描述表  
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
//為屏幕設(shè)備描述表創(chuàng)建兼容的內(nèi)存設(shè)備描述表  
hMemDC = CreateCompatibleDC(hScrDC);  
……
// 創(chuàng)建一個(gè)與屏幕設(shè)備描述表兼容的位圖
hBitmap = CreateCompatibleBitmap(hScrDC, lpRect->Width(),lpRect->Height());
// 把新位圖選到內(nèi)存設(shè)備描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);  
// 把屏幕設(shè)備描述表拷貝到內(nèi)存設(shè)備描述表中
BitBlt(hMemDC, 0, 0, lpRect->Width(),lpRect->Height,  
hScrDC, lpRect->left lpRect->top, SRCCOPY);  
//得到屏幕位圖的句柄
hBitmap =(HBITMAP)SelectObject(hMemDC, hOldBitmap);  
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
……
// 返回位圖句柄  
return hBitmap;
}

當(dāng)把拼合后的區(qū)域拷貝到內(nèi)存,并獲取到該內(nèi)存位圖的句柄后可以將其通過剪貼板傳送到其他圖形處理軟件中進(jìn)行進(jìn)一布的處理,也可以按照位圖的格式直接將其保存成文件,為方便計(jì),本例采用了后者。其實(shí)現(xiàn)過程主要是根據(jù)剛才獲取到的內(nèi)存位圖句柄按格式填充BMP文件的信息頭以及像素陣列,下面就結(jié)合實(shí)現(xiàn)的關(guān)鍵代碼進(jìn)行介紹:

首先獲取設(shè)備描述表句柄,并用函數(shù)GetDeviceCaps()獲取到當(dāng)前顯示分辨率下每個(gè)像素所占字節(jié)數(shù),并據(jù)此計(jì)算出調(diào)色板的大小:

……
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; //計(jì)算調(diào)色板大小
……
然后就可以設(shè)置位圖信息頭結(jié)構(gòu)了,其中bi 是BITMAPINFOHEADER 結(jié)構(gòu)的實(shí)例對象:
……
if (wBitCount <= 8)
dwPaletteSize = (1<
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;  
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;  
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
用GlobalAlloc()函數(shù)根據(jù)計(jì)算的結(jié)果為位圖內(nèi)容分配內(nèi)存,并返回分配得到的內(nèi)存句柄hDib,
并用GetStockObject()來設(shè)置缺省狀態(tài)下的調(diào)色板:
……
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)*4*Bitmap.bmHeight;  
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);  
*lpbi = bi; // 處理調(diào)色板  
hPal = GetStockObject(DEFAULT_PALETTE);  
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal =SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);  
}
// 獲取該調(diào)色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
(BITMAPINFO*)lpbi, DIB_RGB_COLORS);
//恢復(fù)調(diào)色板  
if (hOldPal)
{
SelectPalette(hDC,(HPALETTE)hOldPal, TRUE);  
RealizePalette(hDC);
::ReleaseDC(NULL,hDC);  
}
……

最后的工作就是創(chuàng)建位圖文件了,需要把設(shè)置好的位圖文件頭和像素點(diǎn)陣信息依次保存到文件中,其中bmfHdr 是BITMAPFILEHEADER位圖文件頭結(jié)構(gòu)的實(shí)例對象,需要按照BMP位圖的存盤格式對其進(jìn)行設(shè)置:

……
fh = CreateFile(lpFileName,  
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,  
NULL);
// 設(shè)置位圖文件頭
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ dwPaletteSize + dwBmBitsSize;  
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;  
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +  
(DWORD)sizeof(BITMAPINFOHEADER)+ dwPaletteSize;  
//寫入位圖文件頭
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);  
// 寫入位圖文件其余內(nèi)容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize,&dwWritten, NULL);
……

小結(jié):本程序通過一個(gè)實(shí)例講述了處理圖片無縫拼合的一種實(shí)用方法,在測繪、勘察、文博等行業(yè)均有較大的應(yīng)用潛力。在理解了程序的設(shè)計(jì)思路和編程思想的前提下,結(jié)合具體的實(shí)際需求,通過對本文具體代碼的改動(dòng)可以設(shè)計(jì)出更適合本單位實(shí)際情況的類似軟件。另外,本文所講述的截取并保存屏幕技術(shù)在類似程序的編制上也可以提供一定的參考。本程序在Windows 98下,由Microsoft Visual C++ 6.0編譯通過。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統(tǒng)下載排行

狠狠爱成人网_日韩一级在线_国产综合自拍_亚洲精品韩国_亚洲视频导航_麻豆成人在线播放_欧美jjzz_一区在线视频观看_美脚丝袜一区二区三区在线观看_欧美91视频
国产东北露脸精品视频| 91精品国产品国语在线不卡| 国产精品免费一区二区三区观看| 伊人狠狠色j香婷婷综合| 亚洲影音一区| 欧美日韩国产精品成人| 国产亚洲欧美色| 亚洲精品国产a久久久久久| 美女精品一区二区| 99亚偷拍自图区亚洲| 日韩亚洲国产精品| 欧美日韩亚州综合| 国产精品麻豆99久久久久久| 日韩精品一级中文字幕精品视频免费观看| 日本三级韩国三级欧美三级| 亚洲三级视频| 一本久道中文字幕精品亚洲嫩| 欧美一区二区三区视频免费 | 国产精品欧美久久| 欧美精品aⅴ在线视频| 国产精品久久毛片a| 国产精品2024| 在线中文字幕一区| 中文字幕一区二区三区不卡| 激情综合色播激情啊| 99re6热在线精品视频播放速度| 欧美一区日韩一区| 日本va欧美va瓶| 一区二区三区偷拍| 国产午夜久久久久| 国产不卡视频一区| 欧美午夜精品一区二区三区| 亚洲欧美日韩国产另类专区| 99re成人精品视频| 日韩一区二区电影| 国产美女在线精品| 欧美三级电影网站| 奇米在线7777在线精品| 国产精品久久久久久久久久直播| 久久久久国产精品麻豆| 国产白丝网站精品污在线入口| 91国偷自产一区二区三区观看| 亚洲小说欧美激情另类| 国产精品久久久亚洲一区| 亚洲视频一二区| 亚洲高清免费| 午夜伦欧美伦电影理论片| 国产精品夜夜夜一区二区三区尤| 亚洲欧美激情小说另类| 日韩亚洲在线| 天天影视网天天综合色在线播放| 久久精品一本| 国内精品视频666| 久久尤物电影视频在线观看| 午夜精品一区二区在线观看| 1区2区3区欧美| 久久久天天操| 成人午夜免费av| 亚洲视频精选在线| 欧美专区18| 9久草视频在线视频精品| 亚洲人成亚洲人成在线观看图片| 午夜久久99| 久久国产精品免费| 亚洲成人手机在线| 自拍偷在线精品自拍偷无码专区| 久久久久欧美| 日韩电影免费一区| 精品福利一二区| 亚洲欧美日韩专区| 国产成人av电影免费在线观看| 一区在线播放视频| 91国产视频在线观看| 97se亚洲国产综合自在线观| 亚洲一区二区精品久久av| 3d动漫精品啪啪一区二区竹菊| 欧美一区二区| 国产久卡久卡久卡久卡视频精品| 国产精品成人午夜| 久久亚洲一区二区三区四区| 亚洲欧美国产不卡| 亚洲图片在线观看| 国产91精品一区二区麻豆网站| 午夜视频在线观看一区二区| 久久精品日产第一区二区三区高清版| 在线区一区二视频| 亚洲欧美清纯在线制服| 午夜激情一区| 不卡的电视剧免费网站有什么| 亚洲成av人片一区二区| 亚洲视频狠狠干| 国产精品欧美综合在线| 欧美r级在线观看| 91精品福利在线一区二区三区| 一本一本大道香蕉久在线精品 | 91久久精品日日躁夜夜躁欧美| 欧美日韩 国产精品| 91小视频在线观看| 99精品国产视频| www.亚洲免费av| 99国产精品国产精品久久| 国产99久久精品| 福利一区二区在线| 91欧美一区二区| 亚洲国产日韩综合一区| 亚洲三级国产| 在线精品亚洲一区二区不卡| 在线观看不卡一区| 日韩一区二区三区在线视频| 精品女同一区二区| 久久久久久久久久久久久女国产乱 | 亚洲国产精品久久久男人的天堂| 亚洲精品久久久久久国产精华液| 一区二区三区中文字幕电影| 国内精品在线播放| 国产成人av一区二区三区在线| 丁香婷婷综合激情五月色| 国产在线精品二区| 久久最新视频| 国产人久久人人人人爽| 日产国产高清一区二区三区| 国产宾馆实践打屁股91| 亚洲婷婷免费| 91精品国产综合久久久蜜臀图片 | 午夜欧美视频在线观看| 国产精品亚洲午夜一区二区三区| 女女同性精品视频| 91国产视频在线观看| 中文久久乱码一区二区| 久久精品国产免费看久久精品| 欧美成人在线免费观看| 欧美三级电影网站| 亚洲摸摸操操av| 成人h动漫精品一区二区| 色香色香欲天天天影视综合网| 精品福利一区二区三区| 蜜臀av一区二区在线免费观看| 欧美日韩国产探花| 91精品免费在线观看| 香蕉成人啪国产精品视频综合网| 欧美精品首页| 日韩精品中午字幕| 精品亚洲成av人在线观看| 99国产精品| 18涩涩午夜精品.www| av中文字幕不卡| 日韩免费电影一区| 粉嫩在线一区二区三区视频| 久久影院电视剧免费观看| 久久亚洲精选| 日本欧美一区二区三区乱码| 国产精品免费看| 一区二区三区免费网站| 黑人一区二区三区四区五区| 国产亚洲欧美在线| 色综合中文综合网| 久久久国产精华| 牛夜精品久久久久久久99黑人| 精品人在线二区三区| kk眼镜猥琐国模调教系列一区二区| 欧美精品在线一区二区三区| 国产做a爰片久久毛片| 日韩欧美国产系列| 91免费国产视频网站| 国产精品美女久久久久久久| 日韩亚洲一区在线播放| 亚洲成人黄色小说| 精品婷婷伊人一区三区三| 福利电影一区二区| 国产精品麻豆欧美日韩ww| 日韩视频在线观看国产| 秋霞电影一区二区| 国产色产综合产在线视频| 99视频一区| 国产成人午夜精品影院观看视频| 久久婷婷一区二区三区| 西西裸体人体做爰大胆久久久| 老司机精品视频在线| 国产婷婷色一区二区三区| 性色av一区二区怡红| 欧美激情精品久久久六区热门| 亚洲国产精品久久艾草纯爱| 欧美成人女星排名| 久久成人一区| 欧美日韩国产一区精品一区| 麻豆专区一区二区三区四区五区| 国产视频一区在线观看| 色老综合老女人久久久| 欧美日韩一区二区三区在线视频 | 成人免费视频视频| 午夜精品一区二区三区电影天堂 | 中文字幕国产精品一区二区| 久久久一二三| 麻豆久久精品| 精品动漫av| 欧美激情日韩| 91麻豆免费观看| 成人国产亚洲欧美成人综合网 | 制服丝袜亚洲色图| 在线观看日韩毛片|