前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >径向透镜畸变:鱼眼摄像头照片的矫正,纯前端js矫正鱼眼摄像头

径向透镜畸变:鱼眼摄像头照片的矫正,纯前端js矫正鱼眼摄像头

作者头像
拿我格子衫来
发布2024-09-05 08:09:22
980
发布2024-09-05 08:09:22
举报
文章被收录于专栏:TopFE

最近体验了一下lightburn的摄像头辅助定位, 在使用摄像头进行定位时,你需要先校准相机镜头,然后在校准相机对齐,由于我们上位机后续也需要类似的功能,所以就需要先抽时间预研一下,以便后续开张工作。

先说一下校准相机镜头,这一步做的目的是将相机拍的照片进行处理,如果相机拍的比较斜,或者那种鱼眼相机,拍的照片是中间被放大,四周被压缩。 类似下面的。

在这一步我们需要将其处理成正常的二维平面。 恢复成下面这样子。

这就是这一步的目的,将变形的图片处理成正常的,以便后续建立坐标系,其他流程的处理。

废话不多说,直接上硬菜。 要解决上文所述的,图片失真的情况,我找到了一个库 这就是 fisheye.js https://github.com/ericleong/fisheye.js

官方体验地址 https://ericleong.me/fisheye.js/

该库支持 普通图片的的径向透镜畸变,还支持gif的畸变。此外还支持不同通道,不同值的设置。

在该库内部使用WebGL 来实现畸变和恢复。使用着色器程序来处理纹理和是失真的参数。

使用方法

代码语言:javascript
复制
var canvas = document.getElementById('canvas');
var fisheye = new Fisheye(canvas);

var img;

var red = document.getElementById('red');
var green = document.getElementById('green');
var blue = document.getElementById('blue');

var update = function () {
  fisheye.setViewport(canvas.width, canvas.height);
  fisheye.setDistortion(red.value, green.value, blue.value);
  fisheye.clear();
  fisheye.draw(img);
};

向构造函数传入一个canvas节点,设置视图的尺寸和三个通道的失真参数就可以看到失真的效果。非常的简单。

由于我们的场景是,摄像机安装在机器的一个固定位置,位置固定,画面尺寸固定, 所有只要得到失真的系数,就能将照片还原正常。

失真参数是一个数字,或者三个数字,表示三个通道。0表示没有失真。

下面是案例源码

代码语言:javascript
复制
<!DOCTYPE HTML>
<html>

<head>
  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>fisheye.js</title>

  <style>
    html,
    body {
      margin: 0;
      padding: 0;
    }

    a {
      text-decoration: none;
    }

    body>h1 {
      text-align: center;
    }

    h1 {
      padding-left: 1em;
      padding-right: 1em;
    }

    h1,
    h2 {
      font-family: sans-serif;
      font-weight: lighter;
      font-style: normal;
    }

    h3 {
      font-family: sans-serif;
      font-style: bold;
      font-variant: small-caps;
    }

    #sandbox {
      display: flex;
      justify-content: space-around;

      display: -webkit-flex;
      -webkit-justify-content: space-around;

      width: 100%;
    }

    #controls {
      box-sizing: border-box;
      flex-basis: 20vw;
      -webkit-flex-basis: 20vw;

      padding: 0 1em 0 1em;
    }

    #controls input {
      width: 100%;
    }

    #picker-container {
      position: relative;

      width: 100%;
      height: 3em;

      font-size: 1.25em;
      font-family: sans-serif;

      margin-top: 1em;
    }

    #picker-container::before {
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;

      padding: 1em;

      content: 'pick another image';

      text-align: center;
    }

    #picker-container>input {
      width: 100%;
      height: 100%;

      cursor: pointer;

      opacity: 0 !important;
    }

    @media (max-width: 768px) {

      canvas {
        height: 100vw;
      }

      #sandbox {
        flex-direction: column;
        -webkit-flex-direction: column;
      }

      #controls {
        width: 100vw;
        padding: 0 10% 10% 10%;

        flex-basis: auto;
        -webkit-flex-basis: auto;
      }
    }
  </style>

  <script src="fisheye/omggif.js"></script>
  <script src="fisheye/glif.js"></script>
  <script src="fisheye/viewer.js"></script>
  <script src="fisheye/droppick.js"></script>
  <script src="fisheye/grab.js"></script>
  <script src="fisheye/fisheye.js"></script>
</head>
</head>

<body>
  <!-- <h1>radial lens distortion with <a href="https://github.com/ericleong/fisheye.js">fisheye.js</a></h1> -->
  <h1>径向透镜畸变:鱼眼摄像头照片的矫正</h1>
  <div id="sandbox">
    <canvas id="canvas" width="640" height="640"></canvas>
    <div id="controls">
      <h2>distortion</h2>
      <div><input id="all" type="range" min="-10" max="10" value="5" step="0.1" /></div>
      <h2>color channels</h2>
      <div>
        <h3>red</h3><input id="red" type="range" min="-10" max="10" value="5" step="0.1" />
      </div>
      <div>
        <h3>green</h3><input id="green" type="range" min="-10" max="10" value="5" step="0.1" />
      </div>
      <div>
        <h3>blue</h3><input id="blue" type="range" min="-10" max="10" value="5" step="0.1" />
      </div>
      <div id="picker-container"><input id="picker" type="file" accept="image/*" /></div>
    </div>
  </div>

  <script type="text/javascript">
    var canvas = document.getElementById('canvas');
    var fisheye = new Fisheye(canvas);

    var img;

    var red = document.getElementById('red');
    var green = document.getElementById('green');
    var blue = document.getElementById('blue');

    var update = function () {
      fisheye.setViewport(canvas.width, canvas.height);
      fisheye.setDistortion(red.value, green.value, blue.value);
      fisheye.clear();
      fisheye.draw(img);
    };

    var ie11 = !(window.ActiveXObject) && "ActiveXObject" in window;
    var eventType = ie11 ? 'change' : 'input';

    red.addEventListener(eventType, update);
    green.addEventListener(eventType, update);
    blue.addEventListener(eventType, update);

    var all = document.getElementById('all');
    all.addEventListener(eventType, function () {
      console.log(all.value, 'value')
      red.value = all.value;
      green.value = all.value;
      blue.value = all.value;

      update();
    });

    img = new Image();
    img.addEventListener('load', update, false);
    // img.src = 'fisheye/rainbow-glass.jpg';
    img.src = 'fisheye/grib.png';

    var gifTimeout;

    // drag and drop
    droppick(document.getElementById('sandbox'), document.getElementById('picker'), function (items) {
      grab(items, function (item) {
        debugger
        clearTimeout(gifTimeout);

        function setSize(width, height) {
          if (width > 0.8 * window.innerWidth) {
            if (window.matchMedia('(max-width: 768px)').matches) {
              canvas.width = Math.round(window.innerWidth * window.devicePixelRatio);
              canvas.height = Math.round(canvas.width * (height / width));

              canvas.style.width = '100vw'
              canvas.style.height = 100 * (height / width) + 'vw';
            } else {
              canvas.width = Math.round(0.8 * window.innerWidth * window.devicePixelRatio);
              canvas.height = Math.round(canvas.width * (height / width));

              canvas.style.width = '80vw'
              canvas.style.height = 80 * (height / width) + 'vw';
            }
          } else {
            canvas.width = width;
            canvas.height = height;

            canvas.style.width = canvas.width + 'px';
            canvas.style.height = canvas.height + 'px';
          }
        }

        if (item instanceof ArrayBuffer) {
          img = document.createElement('canvas');

          var view = viewer(img, item, function (timeoutId) {
            gifTimeout = timeoutId;

            setSize(img.width, img.height);
            update();
          });

          gifTimeout = view();
        } else if (item instanceof HTMLImageElement) {

          img = item;

          setSize(item.naturalWidth, item.naturalHeight);
          update();
        }
      })
    });
  </script>
</body>

</html>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档