主 题: 关于全景图像的无缝拼接
作 者: zerodata ()
等 级:
信 誉 值: 98
所属论坛: VC/MFC 图形处理/算法
问题点数: 0
回复次数: 9
发表时间: 2003-07-25 09:43:34Z
请那位做过全景图像拼接的大虾指点,
我在做全景图像的拼接,是通行将重合部分分割成小块,再进行灰度的比较,以此来找到一条缝合曲线,但是无法做到无缝拼接,
各位,有这方面的经验的请谈谈如何来实现.
回复人: harry202(harry) ( ) 信誉:104 2003-07-25 09:50:23Z 得分:0
哪里有类似软件下载?
Top
回复人: zerodata() ( ) 信誉:98 2003-07-25 09:55:31Z 得分:0
有一个做的非常好的软件:pixmaker,
Top
回复人: yellowwolf(你们把名给全起了所以我注册色狼) ( ) 信誉:66 2003-07-25 11:49:04Z 得分:0
什么论坛,我发出去了,他说我没有登陆,白写了那么多。
http://expert.csdn.net/Expert/topic/1988/1988156.xml?temp=.2311975
参考一下。
Top
回复人: GZCompiler(编译器) ( ) 信誉:120 2003-07-25 11:58:22Z 得分:0
图片在接触点的亮度首先要尽量一致。
重合部分如果有位移偏差,作一下拉伸变形。
Top
回复人: zerodata() ( ) 信誉:98 2003-07-25 12:36:26Z 得分:0
接触点的亮度已经调整好了,可以使两幅在不同的曝光度下的图片能柔和的过渡,
现在的问题是如何来找到一系列的接触点
例如,拍摄两幅室内的照片,重合区中有一横梁,由于横梁拍摄的角度不同,横梁在重合区中不一定是平行或者恰好吻合的,很有可能是相交,那么这个交点,怎么来找呢?
另:重合部分的偏差进行拉伸变形速度较慢,不太可行
Top
回复人: zerodata() ( ) 信誉:98 2003-07-25 12:41:35Z 得分:0
to : yellowwolf(你们把名给全起了所以我注册色狼)
看了你在另一贴子中的论述,对你的匹配算法不是太明白,能发一份你的code给我吗?
[email protected]
Top
回复人: yellowwolf(你们把名给全起了所以我注册色狼) ( ) 信誉:66 2003-07-25 16:20:03Z 得分:0
BOOL CDIB::SetComparDIB(BMP* bmp1, BMP* bmp2)
{
unsigned int TempArea = 0;
MAXarea = 0;
int rightbmp_h= bmp2->bmp_Width / 3;
// 从右图的第一像素开始与左图的每一象素比较
for ( register int leftbmp_w =bmp1->bmp_Width; leftbmp_w >=0 ; leftbmp_w--)
{
for (register unsigned int leftbmp_h = 0; leftbmp_h < bmp1->bmp_Height; leftbmp_h++)
{
bmp2->Pix_X = 0;
bmp2->Pix_Y = rightbmp_h;
bmp1->Pix_X = leftbmp_w;
bmp1->Pix_Y = leftbmp_h;
if (IsSamePix(bmp1,bmp2,bmp1->Pix_X,bmp1->Pix_Y,bmp2->Pix_X,bmp2->Pix_Y))
if (IsSameCol(bmp1,bmp2,bmp1->Pix_X,bmp1->Pix_Y,bmp2->Pix_X,bmp2->Pix_Y))
IsSameRect(bmp1,bmp2);
}
}
if ( MAXarea != 0)
{
MergeDIB(bmp1, bmp2);
return TRUE;
}
MessageBox (NULL, "没有找到合并点,不给于合并", NULL, MB_OK);
return FALSE;
}
long CDIB::GetPixOffset (unsigned int X, unsigned int Y, BMP* bmp)
{
if ( (X >= 0 && X< bmp->bmp_Width) && (Y >= 0 && Y < bmp->bmp_Height))
return ( Y * bmp->bmp_line_w + X * (bmp->bmp_BitCount / 8));
return 0;
}
BOOL CDIB::IsSamePix(BMP* bmp1, BMP* bmp2,int x1,int y1, int x2,int y2)
{
BYTE *p, *q;
p = bmp1->lpDIB + GetPixOffset(x1, y1, bmp1);
q = bmp2->lpDIB + GetPixOffset(x2, y2, bmp2);
for (register int i = 0; i< bmp1->bmp_BitCount / 8; i++)
if ( abs(p[i] - q[i]) > 25 ) return FALSE;
//if ( p[i] != q[i]) return FALSE;
return TRUE;
}
BOOL CDIB::IsSameCol(BMP *bmp1, BMP *bmp2,int x1,int y1,int x2,int y2)
{
unsigned int below_h1 = bmp1->bmp_Height - y1; // 左图当点象素到图底部的长
unsigned int below_h2 = bmp2->bmp_Height - y2; // 右图当点象素到图底部的长
unsigned int h = (below_h1 > below_h2) ? below_h2 : below_h1; // 得到两图中到图底部最短的长
for ( register unsigned int i = 0; i
{
// 得到下一象素继续比较
if (!IsSamePix (bmp1, bmp2,x1,y1,x2,y2))
return FALSE;
y1 += 1;
y2 += 1;
}
return TRUE;
}
BOOL CDIB::IsSameRect(BMP *bmp1, BMP *bmp2)
{
unsigned int x1,y1,x2,y2;
unsigned int w1 = bmp1->bmp_Width - bmp1->Pix_X ;
unsigned int w2 = bmp2->bmp_Width - bmp2->Pix_X;
unsigned int w = (w1 > w2) ? w2 : w1;
x1 = bmp1->Pix_X; y1 = bmp1->Pix_Y;
x2 = bmp2->Pix_X; y2 = bmp2->Pix_Y;
for ( register unsigned int i = 0; i < w; i++ )
{
if ( !IsSameCol(bmp1,bmp2,x1,y1,x2,y2) )
return FALSE;
x1 ++;
x2 ++;
}
unsigned int h = (bmp1->bmp_Height - bmp1->Pix_Y) < (bmp2->bmp_Height - bmp2->Pix_Y) ? (bmp1->bmp_Height - bmp1->Pix_Y) : (bmp2->bmp_Height - bmp2->Pix_Y);
if(i*h >MAXarea)
{
MAXarea = i*h;
overlap_info.left_starX = bmp1->Pix_X;
overlap_info.left_starY = bmp1->Pix_Y;
overlap_info.left_endX = i + bmp1->Pix_X;
overlap_info.left_endY = h + bmp1->Pix_Y;
overlap_info.right_starX = bmp2->Pix_X;
overlap_info.right_starY = bmp2->Pix_Y;
overlap_info.right_endX = i + bmp2->Pix_X;
overlap_info.right_endY = h + bmp2->Pix_Y;
}
return TRUE;
}
void CDIB::MergeDIB(BMP* bmp1, BMP* bmp2)
{
BYTE* unitbuff;
unsigned int unit_w = bmp2->bmp_Width + overlap_info.left_starX; // 合并文件后的宽
unsigned int unit_h = overlap_info.left_endY - overlap_info.left_starY; // 合并文件后的高
int byte_w = unit_w * (bmp1->bmp_BitCount/8); // 得到行真实数据
if(byte_w%4) byte_w = byte_w + (4 - byte_w%4); // 得到一行的数据属占的字节数
int imagedata = byte_w * unit_h; // 得到整个文件数据的属占的字节数
if (!(unitbuff = new BYTE[imagedata]))
{
MessageBox(NULL, "合并文件申请内存时失败", "内存申请", MB_OK);
return;
}
BYTE *p1, *p2, *p3;
p1 = bmp1->lpDIB + overlap_info.left_starY * bmp1->bmp_line_w;
p2 = bmp2->lpDIB + overlap_info.right_starY * bmp2->bmp_line_w;
p3 = unitbuff;
for ( unsigned int i=0; i < unit_h; i++)
{
memcpy (p3, p1, overlap_info.left_starX * (bmp1->bmp_BitCount / 8));
p3 += overlap_info.left_starX * (bmp1->bmp_BitCount / 8);
p1 += bmp1->bmp_line_w;
memcpy (p3, p2, bmp2->bmp_Width * (bmp2->bmp_BitCount / 8));
p3 += bmp2->bmp_Width * (bmp2->bmp_BitCount / 8);
p2 += bmp2->bmp_line_w;
if ( (unsigned int)(p3 - unitbuff) % 4 != 0)
p3 += 4 - (unsigned int)((p3 - unitbuff) % 4);
}
Tempbmp.bmp_BitCount = bmp1->bmp_BitCount;
Tempbmp.bmp_Height = unit_h;
Tempbmp.bmp_Width = unit_w;
if (Tempbmp.lpDIB != NULL)
Tempbmp.lpDIB =NULL;
Tempbmp.lpDIB = new BYTE[imagedata];
if ( !Tempbmp.lpDIB )
{
MessageBox(NULL, "申请内存时失败", "内存申请", MB_OK);
return;
}
if ( bmp1->bmp_BitCount == 8 )
{
if ( !Tempbmp.lpPalette != NULL)
Tempbmp.lpPalette = NULL;
// 存取颜色表
Tempbmp.lpPalette = new BYTE[sizeof(RGBQUAD) * PALETTESIZE(8)];
memcpy(Tempbmp.lpPalette, bmp1->lpPalette, sizeof(RGBQUAD) * PALETTESIZE(8));
}
if ( bmp1->bmp_BitCount == 24 )
Tempbmp.lpPalette = NULL;
// 数据恢复文件中数据的顺序
for ( i = 0; i < unit_h; i++ )
memcpy ( Tempbmp.lpDIB + byte_w * i, unitbuff + byte_w * (unit_h - i - 1), byte_w);
// 数据写入文件
CFile pf("b.bmp", CFile::modeCreate|CFile::modeWrite);
if ( pf == NULL )
{
MessageBox (NULL, "Create Merge file failed!", "Create file", MB_OK);
return;
}
BITMAPFILEHEADER bm;
bm.bfType = 0x4D42;
bm.bfSize = imagedata;
bm.bfReserved1 = 0;
bm.bfReserved2 = 0;
bm.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
if (bmp1->bmp_BitCount != 24)
bm.bfOffBits += PALETTESIZE(bmp1->bmp_BitCount)*sizeof(RGBQUAD);
pf.Write(&bm,sizeof(BITMAPFILEHEADER));
BITMAPINFOHEADER bmi;
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biWidth = unit_w ;
bmi.biHeight = unit_h;
bmi.biPlanes=1;
bmi.biBitCount= bmp1->bmp_BitCount;
bmi.biCompression=BI_RGB;
bmi.biSizeImage=0;
bmi.biXPelsPerMeter=0;
bmi.biYPelsPerMeter=0;
bmi.biClrUsed=0;
bmi.biClrImportant=0;
pf.Write(&bmi,sizeof(BITMAPINFOHEADER));
if (bmp1->bmp_BitCount != 24)
pf.Write(bmp1->lpPalette, PALETTESIZE(bmp1->bmp_BitCount)*sizeof(RGBQUAD));
pf.Write(Tempbmp.lpDIB,byte_w * unit_h);
delete[] unitbuff;
MessageBox(NULL,"两图合并后的文件写入成功!","合并文件信息",0);
return ;
}
比点-》比列-》比块
我现在做的跟你做的差不多,也是拍了几次的图拼合的,亮度不一样,用些好模,有点难。
上面的代码你看一下,可能看这种图没有很大的帮助。
QQ里有没有加了我,一起交流一下,我晚上常在。
Top
回复人: zerodata() ( ) 信誉:98 2003-07-25 17:48:34Z 得分:0
to : yellowwolf(你们把名给全起了所以我注册色狼)
我已经加你了,晚上聊聊
我的qq: 52217141
Top
回复人: yellowwolf(你们把名给全起了所以我注册色狼) ( ) 信誉:66 2003-07-25 19:34:52Z 得分:0
我在拼有色差图。把代码改了一点
rightbmp_h= bmp2->bmp_Height / 3; // 取右图中中间某点
// 从右图高的1/3开始与左图的每一象素比较
for ( register int leftbmp_w =bmp1->bmp_Width; leftbmp_w >=0 ; leftbmp_w--)
if ( abs(p[i] - q[i]) > 25 ) return FALSE; // 注这句
if ( p[i] != q[i]) return FALSE; // 用这句
不好意思了。今晚有点事,不好意思,明天我在。
该问题已经结贴