关于全景图像的无缝拼接

原创 2004年08月31日 01:06:00
主  题:  关于全景图像的无缝拼接
作  者:  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给我吗?
wyy@Ezonics.com.cn
 
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 <h; 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;  // 用这句
不好意思了。今晚有点事,不好意思,明天我在。
该问题已经结贴 

Opencv Sift和Surf特征实现图像无缝拼接生成全景图像

Sift和Surf算法实现两幅图像拼接的过程是一样的,主要分为4大部分: 1. 特征点提取和描述 2. 特征点配对,找到两幅图像中匹配点的位置 3. 通过配对点,生成变换矩阵,并对图像1应用变换矩阵生...
  • dcrmg
  • dcrmg
  • 2016年09月23日 00:11
  • 15102

基于SIFT特征的全景图像拼接

主要分为以下几个步骤: (1) 读入两张图片并分别提取SIFT特征 (2) 利用k-d tree和BBF算法进行特征匹配查找 (3) 利用RANSAC算法筛选匹配点并计算变换矩阵 (3) 图像融合 ...
  • masikkk
  • masikkk
  • 2013年07月04日 21:43
  • 29933

opencv全景拼接源码解读与修改。

Stitcher::Status status = stitcher.stitch(imgs, pano);这一句是最上层的调用,它调用了以下函数:1,Status status = estimate...
  • fk1174
  • fk1174
  • 2017年03月11日 13:25
  • 1965

Opencv Sift和Surf特征实现图像无缝拼接生成全景图像

转载于:http://m.blog.csdn.net/article/details?id=52629856 Sift和Surf算法实现两幅图像拼接的过程是一样的,主要分为4大部分: ...
  • b20202200
  • b20202200
  • 2017年01月04日 11:33
  • 558

全景图像拼接基于SIFT特征-Qt工程

  • 2017年11月15日 19:33
  • 292KB
  • 下载

利用OpenCV中的Stitcher类实现全景图像拼接

  • 2013年06月27日 20:29
  • 2.29MB
  • 下载

鱼眼图像全景拼接系统

  • 2017年11月07日 16:10
  • 12.41MB
  • 下载

基于Surf的Opencv全景图像拼接《Panoramic Image mosaic based on SURF algorithm using OpenCV》

  • 2016年04月23日 10:25
  • 1.04MB
  • 下载

全景图像自动拼接

  • 2015年10月02日 16:57
  • 256KB
  • 下载

全景图像拼接

  • 2013年07月05日 11:13
  • 7.22MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于全景图像的无缝拼接
举报原因:
原因补充:

(最多只允许输入30个字)