当前位置: 首页 > 面试题库 >

如何通过openCV模拟鱼眼镜头效果?

高英彦
2023-03-14
问题内容

我正在寻找创建鱼眼镜头效果的方法,查看了openCV的文档,看起来它包含针对像鱼眼这样的径向变形的“相机校准”功能。是否可以通过openCV模拟鱼眼失真?

如果与openGL相比,openCV可以做到,哪一个会产生更好的结果?谢谢。


问题答案:

我使用opencv创建了此应用。这是您所指的效果吗?我基本上编码了维基百科“ Distortion(optics)”上显示的公式,如果需要,我可以显示代码

更新:好的,因此以下是使用opencv用c ++编写的实际代码(未记录,因此随时要求解释):该程序将输入以下参数作为输入:输入图片| | 输出图像| | 控制失真量的K(通常尝试0.001附近的值) | | 变形中心的x坐标| | 变形中心的y坐标|

因此,程序的关键是double for循环,该循环在结果图像上逐个像素迭代,并使用径向失真公式在输入图像中寻找匹配的像素(这通常是图像变形的方法-可能是直观地对付从输出到输入的反投影)。有一些细微之处与输出图像的比例有关(在此程序中,生成的图像与输入的大小相同),除非您想了解更多细节,否则我不会涉及。

    #include <cv.h>
    #include <highgui.h>
    #include <math.h>
    #include <unistd.h>
    #include <getopt.h>
    #include <iostream>


    void sampleImage(const IplImage* arr, float idx0, float idx1, CvScalar& res)
    {
      if(idx0<0 || idx1<0 || idx0>(cvGetSize(arr).height-1) || idx1>(cvGetSize(arr).width-1)){
        res.val[0]=0;
        res.val[1]=0;
        res.val[2]=0;
        res.val[3]=0;
        return;
      }
      float idx0_fl=floor(idx0);
      float idx0_cl=ceil(idx0);
      float idx1_fl=floor(idx1);
      float idx1_cl=ceil(idx1);

      CvScalar s1=cvGet2D(arr,(int)idx0_fl,(int)idx1_fl);
      CvScalar s2=cvGet2D(arr,(int)idx0_fl,(int)idx1_cl);
      CvScalar s3=cvGet2D(arr,(int)idx0_cl,(int)idx1_cl);
      CvScalar s4=cvGet2D(arr,(int)idx0_cl,(int)idx1_fl);
      float x = idx0 - idx0_fl;
      float y = idx1 - idx1_fl;
      res.val[0]= s1.val[0]*(1-x)*(1-y) + s2.val[0]*(1-x)*y + s3.val[0]*x*y + s4.val[0]*x*(1-y);
      res.val[1]= s1.val[1]*(1-x)*(1-y) + s2.val[1]*(1-x)*y + s3.val[1]*x*y + s4.val[1]*x*(1-y);
      res.val[2]= s1.val[2]*(1-x)*(1-y) + s2.val[2]*(1-x)*y + s3.val[2]*x*y + s4.val[2]*x*(1-y);
      res.val[3]= s1.val[3]*(1-x)*(1-y) + s2.val[3]*(1-x)*y + s3.val[3]*x*y + s4.val[3]*x*(1-y);
    }

    float xscale;
    float yscale;
    float xshift;
    float yshift;

    float getRadialX(float x,float y,float cx,float cy,float k){
      x = (x*xscale+xshift);
      y = (y*yscale+yshift);
      float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy)));
      return res;
    }

    float getRadialY(float x,float y,float cx,float cy,float k){
      x = (x*xscale+xshift);
      y = (y*yscale+yshift);
      float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy)));
      return res;
    }

    float thresh = 1;
    float calc_shift(float x1,float x2,float cx,float k){
      float x3 = x1+(x2-x1)*0.5;
      float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx)));
      float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx)));

      //  std::cerr<<"x1: "<<x1<<" - "<<res1<<" x3: "<<x3<<" - "<<res3<<std::endl;

      if(res1>-thresh and res1 < thresh)
        return x1;
      if(res3<0){
        return calc_shift(x3,x2,cx,k);
      }
      else{
        return calc_shift(x1,x3,cx,k);
      }
    }

    int main(int argc, char** argv)
    {
      IplImage* src = cvLoadImage( argv[1], 1 );
      IplImage* dst = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
      IplImage* dst2 = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
      float K=atof(argv[3]);
      float centerX=atoi(argv[4]);
      float centerY=atoi(argv[5]);
      int width = cvGetSize(src).width;
      int height = cvGetSize(src).height;

      xshift = calc_shift(0,centerX-1,centerX,K);
      float newcenterX = width-centerX;
      float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,K);

      yshift = calc_shift(0,centerY-1,centerY,K);
      float newcenterY = height-centerY;
      float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,K);
      //  scale = (centerX-xshift)/centerX;
      xscale = (width-xshift-xshift_2)/width;
      yscale = (height-yshift-yshift_2)/height;

      std::cerr<<xshift<<" "<<yshift<<" "<<xscale<<" "<<yscale<<std::endl;
      std::cerr<<cvGetSize(src).height<<std::endl;
      std::cerr<<cvGetSize(src).width<<std::endl;

      for(int j=0;j<cvGetSize(dst).height;j++){
        for(int i=0;i<cvGetSize(dst).width;i++){
          CvScalar s;
          float x = getRadialX((float)i,(float)j,centerX,centerY,K);
          float y = getRadialY((float)i,(float)j,centerX,centerY,K);
          sampleImage(src,y,x,s);
          cvSet2D(dst,j,i,s);

        }
      }
    #if 0
      cvNamedWindow( "Source1", 1 );
      cvShowImage( "Source1", dst);
      cvWaitKey(0);
    #endif

      cvSaveImage(argv[2],dst,0);

    #if 0
      for(int j=0;j<cvGetSize(src).height;j++){
        for(int i=0;i<cvGetSize(src).width;i++){
          CvScalar s;
          sampleImage(src,j+0.25,i+0.25,s);
          cvSet2D(dst,j,i,s);
        }
      }

      cvNamedWindow( "Source1", 1 );
      cvShowImage( "Source1", src);
      cvWaitKey(0);

    #endif  

}



 类似资料:
  • 我正在尝试用D3创建一个时间线。js。我将在时间轴上绘制事件,我希望在悬停时间轴时具有鱼眼效果。 我的时间表如下:http://codepen.io/fabianmossberg/pen/gaRwXG 参考:第三张图表http://bost.ocks.org/mike/fisheye/但仅限于X轴。 我还希望鱼眼效果在退出timline时变得平滑,就像在上一样http://www.nytimes.

  • 问题内容: 我在通过jQuery伪造锚点单击时遇到问题:为什么我的thickbox第一次单击输入按钮时出现,但第二次或第三次却没有出现? 这是我的代码: 当我直接单击链接时,它总是起作用,但是如果我尝试通过输入按钮激活thickbox,则它不会起作用。这是在FF。对于Chrome,它似乎每次都能正常工作。有什么提示吗? 尽量避免内联这样的jQuery调用。将脚本标签放在页面顶部以绑定到事件: 编辑

  • 我已经成功地为一个示例数据集实现了codeflower视图。用于实现这一目标的代码是: 我现在希望添加鱼眼扭曲到这个可视化,不知道如何去做。我已经研究了鱼眼的留档,但当我使用codeflower.js我不确定如何访问svg元素了。任何帮助都很感激。谢谢你。

  • 可以使用Spring Security制作一个非常简单的JWT示例。 我想说明如何使用角色,而不必设置所有的Spring Security性。 基本上我想使用带有包含角色的jwt令牌的postman。我不想设置用户登录。可能吗?

  • 我在Ubuntu16.0.4上安装了一个新的Opencv,我编写了一个程序来获取相机流并存储一些帧。它“没有”问题。但不能通过Systemd工作。systemd单元处于活动状态(不要失败),但目标文件夹中没有帧存储。 我一步一步地寻找问题,我发现代码挂在打开摄像头流上。那就是:帽子。打开(“MyIpCameraAddress”) 我试着通过bash脚本而不是脚本来运行代码。但问题依然存在 说明=a

  • 问题内容: 我能够通过VLC命令行接收/查看UDP h264数据包(即VLC –network-caching 0 –demux h264 udp:// …) 我正计划通过OpenCV算法处理那些帧。但是,我似乎找不到找到将VLC帧发送到我的Python OpenCV脚本的方法。 是否可以在单独的脚本中通过Numpy传递要处理的VLC流输出? 之前,我曾尝试使用其VideoCapture函数直接将