如何匹配3D透视的真实照片和对象在CSS3 3D变换 [英] How to match 3D perspective of real photo and object in CSS3 3D transforms

查看:230
本文介绍了如何匹配3D透视的真实照片和对象在CSS3 3D变换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况:



在我的特定情况下,我有3D相框图片和2D照片。我想使用CSS3转换函数(旋转,缩放,倾斜)将2D照片与3D框架进行匹配。



问题: p>

我无法精确匹配这两个使用手动方法aka打印旋转值,看看它做什么。



理想解决方案#1



在线视觉工具存在,可让您拖动照片的边角)



p>非可视工具存在 - 与以前相同,但是你手动输入4点坐标(图像角点),它给你正确的CSS3变换值。



这个问题的真正解决方案



如果没有这样的工具(我的搜索没有找到),我想让某人尝试 >



我准备了JSFiddle演示,你可以自由地计算它:
演示



 

 < div class =container> < div class =frame> < img src =http://cdn.idesigned.cz/img/cc08acc7b9b08ab53bf935d720210f13.png/> < / div> < div class =photo> < div class =transform> < img src =https://static.pexels.com/photos/7976/pexels-photo.jpg/> < / div> < / div>< / div>  

解决方案

如果您可以使用3-d转换(例如 rotateZ ),那么您还可以提供 matrix3d 您可以从所需的点对应计算。



这里是一个小提琴: https://jsfiddle.net/szym/03s5mwjv/



我使用 numeric.js 来解决一组4个线性方程,以找到透视变换矩阵,将 src 转换为 dst 。这与 getPerspectiveTransform 在OpenCV 中。



计算的2-d透视变换是一个3x3矩阵,使用齐次坐标。 CSS matrix3d 是使用齐次坐标的4x4矩阵,因此我们需要为 z 添加一个标识行/轴。此外, matrix3d 以列为主的顺序指定。



一旦你得到 matrix3d 您可以将其粘贴到样式表中。但是请记住,假设(0,0)作为原点计算矩阵,因此您还需要设置 transformOrigin:0 0



  //计算将src指向dst.function的matrix3d computeTransform(src,dst){// src和dst应该有长度4每个var count = 4; var a = []; //(2 * count)x 8 matrix var b = []; //(2 * count)vector for(var i = 0; i <2 * count; ++ i){a.push([0,0,0,0,0,0,0,0]); b.push(0); } for(var i = 0; i  

  .container {position:relative; width:50%;}#frame,#photo {position:absolute; top:0; left:0; right:0; bottom:0;} #photo {visibility:hidden;} #frame img,#photo img {width:100%} #photo {opacity:0.7;}  

 < script src =https://cdnjs.cloudflare.com/ajax/libs/numeric/1.2.6/numeric。 min.js>< / script> < p id =result>点击所需的左上角,右上角,右下角,左下角< div class =container> < div id =frame> < img src =http://cdn.idesigned.cz/img/cc08acc7b9b08ab53bf935d720210f13.png/> < / div> < div id =photo> < div id =transform> < img id =imgsrc =http://placehold.it/350x150/> < / div> < / div> < / div>  


The situation:

In my particular case I have 3D photoframe image and a 2D photo. And I want the 2D photo to match the 3D frame using CSS3 transform functions (Rotate, Scale, Skew).

The problem:

I wasn't able to precisely match the two using manual method aka typing rotation value and watching what it does.

Ideal solution #1

Online visual tool exists that lets you drag corners of the photo (like photoshop does) and It gives you the correct CSS3 transform values.

Ideal solution #2

Non-visual tool exist - same as before but you manually enter 4 point coordinates (image corners) and it gives you the correct CSS3 transform values.

Real solution of this question

If there aren't such tools (my search found none) I would like somebody to try explain the math behind it so I could calculate it myself - If it is even possible?

I prepared JSFiddle demo for you fiddle around: Demo

/* Main issue here */

.transform {
  transform: rotateX(34deg) rotateZ(13deg) rotateY(-10deg) scaleY(1) scaleX(1) skewY(0deg) skewX(0deg) translateY(0px) translateX(20px);
  transform-origin: 50% 0% 0;
}
/* Supporting styles */

.container {
  position: relative;
  width: 500px;
  height: 500px;
}
.frame,
.photo {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.photo {
  top: 50px;
  left: 95px;
  right: 65px;
  bottom: 270px;
}
.frame img,
.photo img {
  width: 100%
}
.frame {
  z-index: 2;
}

<div class="container">

  <div class="frame">
    <img src="http://cdn.idesigned.cz/img/cc08acc7b9b08ab53bf935d720210f13.png" />
  </div>

  <div class="photo">
    <div class="transform">
      <img src="https://static.pexels.com/photos/7976/pexels-photo.jpg" />
    </div>
  </div>

</div>

解决方案

If you can use 3-d transforms (such as rotateZ), then you can also provide matrix3d which you can compute from desired point correspondences.

Here's a fiddle: https://jsfiddle.net/szym/03s5mwjv/

I'm using numeric.js to solve a set of 4 linear equations to find the perspective transform matrix that transforms src onto dst. This is essentially the same math as in getPerspectiveTransform in OpenCV.

The computed 2-d perspective transform is a 3x3 matrix using homogeneous coordinates. The CSS matrix3d is a 4x4 matrix using homogeneous coordinates, so we need to add an identity row/column for the z axis. Furthermore, matrix3d is specified in column-major order.

Once you get the matrix3d you can just paste it into your stylesheet. But keep in mind that the matrix is computed assuming (0, 0) as origin, so you also need to set transformOrigin: 0 0.

// Computes the matrix3d that maps src points to dst.
function computeTransform(src, dst) {
  // src and dst should have length 4 each
  var count = 4;
  var a = []; // (2*count) x 8 matrix
  var b = []; // (2*count) vector

  for (var i = 0; i < 2 * count; ++i) {
    a.push([0, 0, 0, 0, 0, 0, 0, 0]);
    b.push(0);
  }

  for (var i = 0; i < count; ++i) {
    var j = i + count;
    a[i][0] = a[j][3] = src[i][0];
    a[i][1] = a[j][4] = src[i][1];
    a[i][2] = a[j][5] = 1;
    a[i][3] = a[i][4] = a[i][5] =
      a[j][0] = a[j][1] = a[j][2] = 0;
    a[i][6] = -src[i][0] * dst[i][0];
    a[i][7] = -src[i][1] * dst[i][0];
    a[j][6] = -src[i][0] * dst[i][1];
    a[j][7] = -src[i][1] * dst[i][1];
    b[i] = dst[i][0];
    b[j] = dst[i][1];
  }

  var x = numeric.solve(a, b);
  // matrix3d is homogeneous coords in column major!
  // the z coordinate is unused
  var m = [
    x[0], x[3],   0, x[6],
    x[1], x[4],   0, x[7],
       0,    0,   1,    0,
    x[2], x[5],   0,    1
  ];
  var transform = "matrix3d(";
  for (var i = 0; i < m.length - 1; ++i) {
    transform += m[i] + ", ";
  }
  transform += m[15] + ")";
  return transform;
}

// Collect the four corners by user clicking in the corners
var dst = [];
document.getElementById('frame').addEventListener('mousedown', function(evt) {
  // Make sure the coordinates are within the target element.
  var box = evt.target.getBoundingClientRect();
  var point = [evt.clientX - box.left, evt.clientY - box.top];
  dst.push(point);

  if (dst.length == 4) {
    // Once we have all corners, compute the transform.
    var img = document.getElementById('img');
    var w = img.width,
        h = img.height;
    var transform = computeTransform(
      [
        [0, 0],
        [w, 0],
        [w, h],
        [0, h]
      ],
      dst
    );
    document.getElementById('photo').style.visibility = 'visible';
    document.getElementById('transform').style.transformOrigin = '0 0';
    document.getElementById('transform').style.transform = transform;
    document.getElementById('result').innerHTML = transform;
  }
});

.container {
  position: relative;
  width: 50%;
}
  
#frame,
#photo {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
  
#photo {
  visibility: hidden;
}
  
#frame img,
#photo img {
  width: 100%
}
  
#photo {
  opacity: 0.7;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/numeric/1.2.6/numeric.min.js"></script>
  <p id="result">Click the desired top-left, top-right, bottom-right, bottom-left corners
  <div class="container">
    <div id="frame">
      <img src="http://cdn.idesigned.cz/img/cc08acc7b9b08ab53bf935d720210f13.png" />
    </div>

    <div id="photo">
      <div id="transform">
        <img id="img" src="http://placehold.it/350x150" />
      </div>
    </div>

  </div>

这篇关于如何匹配3D透视的真实照片和对象在CSS3 3D变换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆