zoukankan      html  css  js  c++  java
  • 利用视差图合成新视点

     利用视差图合成新视点,视差图一般通过图像匹配获取,以middlebury上的一张图为例,左边为原图(左图像),右边为对应视差图(灰度图)。

        

    1. 正向映射:

    简单的利用左视点原图和视差图进行视点合成,取每一个像素点处的视差值,然后计算新图像中像素点位置,然后赋值。前向映射,单点赋值代码如下。配置完Opencv可以直接跑,如下图:

     

     1 #include <iostream>
     2 #include <string>
     3 #include <opencv.hpp>
     4 
     5 using namespace std;
     6 using namespace cv;
     7 
     8 void main()
     9 {
    10     string imgPath="data/source_images/teddy/";
    11     Mat srcImgL=imread(imgPath+"imgL.png");
    12     Mat dispL=imread(imgPath+"dispL.png",0);
    13     dispL=dispL/4;
    14 
    15     int imgHeight=srcImgL.rows;
    16     int imgWidth=srcImgL.cols;
    17     int channels=srcImgL.channels();
    18 
    19     Mat dstImgL=Mat::zeros(imgHeight,imgWidth, CV_8UC3);
    20 
    21     uchar* pImgDataL=(uchar*)srcImgL.data;
    22     uchar* pDispDataL=(uchar*)dispL.data;
    23     uchar* pDstDataL=(uchar*)dstImgL.data;
    24 
    25     VideoWriter writer("video.avi", CV_FOURCC('D','I','V','X'), 30, Size(imgWidth, imgHeight), 1);
    26     int cnt=0;
    27     int viewCnt=50;
    28     while (cnt !=4)
    29     {
    30         for (int k=0; k<viewCnt; k++)
    31         {
    32             dstImgL.setTo(0);
    33             float interp;
    34             if (cnt%2==0)    interp=(float)k/viewCnt;
    35             else  interp=float(viewCnt-k)/viewCnt;
    36             for (int j=0; j<imgHeight; j++)
    37             {
    38                 for (int i=0; i<imgWidth; i++)
    39                 {
    40                     uchar dispL=pDispDataL[j*imgWidth+i];
    41                     float offsetL=dispL* interp;
    42                     int idL=(int)(offsetL+0.5);  //计算视差值
    43 
    44                     if (idL+i>=imgWidth) continue;
    45                     //插值结果
    46                     int idxResult=(j*imgWidth+i)*channels;
    47                     int idx=(j*imgWidth+i+idL)*channels;
    48                     for (int chan=0; chan<channels; chan++)
    49                     {
    50                          pDstDataL[idxResult+chan]=pImgDataL[idx+chan];
    51                     }
    52                 }
    53             }
    54             namedWindow("show");
    55             imshow("show", dstImgL);
    56             waitKey(10); 
    57             writer<<dstImgL;
    58         }
    59         cnt++;
    60     }
    61     writer.release();
    62 }
    View Code

     边缘有锯齿,随后找时间加上反向映射以及双线性插值的版本。

    2. 反向映射

    先根据左视点视差图生成虚拟视点的视差图,然后反向映射得到每一个像素点在原图像中的浮点位置,利用线性插值获取最终颜色值。(虚拟视点位置视差图没有填充空洞版本),可见有很多裂纹。

     

      1 #include <iostream>
      2 #include <string>
      3 #include <opencv.hpp>
      4 
      5 using namespace std;
      6 using namespace cv;
      7 
      8 int index(int m, int n)
      9 {
     10     if (m>=0 && m<n)
     11         return m;
     12     else if (m<0)
     13         return 0;
     14     else if (m>=n)
     15         return n-1;
     16 }
     17 
     18 void obtainNewDispMap(const Mat &refDisp, Mat &dstDisp, float value)
     19 {
     20     int height=refDisp.rows;
     21     int width=refDisp.cols;
     22     uchar* pSrcDispData=(uchar*) refDisp.data;
     23     float* pDstDispData=(float*) dstDisp.data;
     24     for (int j=0; j<height; j++)
     25     {
     26         for (int i=0; i<width; i++)
     27         {
     28             int disp=(int)pSrcDispData[j*width+i];
     29             float newDisp=disp*(value);
     30             int inew=(int)(i-newDisp);
     31             inew=index(inew, width);
     32             pDstDispData[j*width+inew]=newDisp;
     33         } 
     34     }
     35 }
     36 
     37 void main(void)
     38 {
     39     string imgPath="data/source_images/teddy/";
     40     Mat srcImgL=imread(imgPath+"imgL.png");
     41     Mat dispL=imread(imgPath+"dispL.png",0);
     42     dispL=dispL/4;
     43 
     44     int imgHeight=srcImgL.rows;
     45     int imgWidth=srcImgL.cols;
     46 
     47     Mat dstImgL=Mat::zeros(imgHeight,imgWidth, CV_8UC3);
     48     Mat dstImg=Mat::zeros(imgHeight,imgWidth, CV_8UC3);
     49     Mat dstNewDispImg=Mat::zeros(imgHeight,imgWidth, CV_32FC1);
     50 
     51     uchar* pImgDataL=(uchar*)srcImgL.data;
     52     uchar* pDispDataL=(uchar*)dispL.data;
     53     uchar* pDstDataL=(uchar*)dstImgL.data;
     54 
     55     VideoWriter writer("video.avi", CV_FOURCC('D','I','V','X'), 30, Size(imgWidth, imgHeight), 1); 
     56     int cnt=0;
     57     int viewCnt=50;
     58     while (cnt!=4)
     59     {
     60         float interp;
     61         for (int k=0; k<viewCnt; k++)
     62         {
     63             dstNewDispImg.setTo(255);
     64             dstImgL.setTo(0);
     65             if (cnt%2==0)   interp=(float)k/viewCnt;
     66             else interp=(float)(viewCnt-k)/viewCnt;
     67 
     68             obtainNewDispMap(dispL, dstNewDispImg, interp);
     69 
     70             float* pNewDispData=(float*)dstNewDispImg.data;
     71             for (int j=0; j<imgHeight; j++)
     72             {
     73                 for (int i=0; i<imgWidth; i++)
     74                 {
     75                     float disp=pNewDispData[j*imgWidth+i];
     76                     float id=i+disp;
     77 
     78                     int id0=floor(id);
     79                     int id1=floor(id+1);
     80                 
     81                     float weight1=1-(id-id0);
     82                     float weight2=id-id0;
     83 
     84                     id0=index(id0, imgWidth);
     85                     id1=index(id1, imgWidth);
     86 
     87                     //插值结果
     88                     pDstDataL[j*imgWidth*3+i*3+0]=weight1*pImgDataL[j*imgWidth*3+id0*3+0]+weight2*pImgDataL[j*imgWidth*3+id1*3+0];
     89                     pDstDataL[j*imgWidth*3+i*3+1]=weight1*pImgDataL[j*imgWidth*3+id0*3+1]+weight2*pImgDataL[j*imgWidth*3+id1*3+1];
     90                     pDstDataL[j*imgWidth*3+i*3+2]=weight1*pImgDataL[j*imgWidth*3+id0*3+2]+weight2*pImgDataL[j*imgWidth*3+id1*3+2];
     91                 }
     92             }
     93             namedWindow("virImg");
     94             imshow("virImg", dstImgL);
     95             waitKey(10);
     96             writer<<dstImgL;
     97         }
     98         cnt++;
     99     }
    100    writer.release();
    101 }
    View Code

     3.反向映射+空洞填充+双线性插值

    上面生成虚拟视点位置的视差图时没有填充空洞,生成的虚拟视点会有很多裂纹存在。加上空洞填充能够有效消除裂纹。如下:

       

    填充空洞后生的虚拟视点图如下,可见空洞裂纹得到有效消除:

    --------------------------------- 业精于勤而荒于嬉 行成于思而毁于随 ---------------------------------
  • 相关阅读:
    用 C# 获取 IE 临时文件(转)
    vs2008打包程序需要.net3.5支持问题的解决方案
    关于使用ssh账号上外网
    元数据管理技术及发展应用现状
    一个拨号上网的批处理文件
    windows下启动和关闭oracle数据库的bat脚本
    Solaris下配置网络
    开启windows 2000 server上的远程桌面
    FileZilla客户端使用TIPs
    学习使用gvim
  • 原文地址:https://www.cnblogs.com/riddick/p/7355353.html
Copyright © 2011-2022 走看看