We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
3D立体画是裸眼3D的一种,最初是由一些极具创意的画家在街道或平地上创作的,后来又有了在纸上的绘制的作品。我的第一幅3D立体画是高二上画的:
然后上大学后许久没有画过了。
近期武汉新型冠状病毒肺炎疫情严重,只能呆在家,闲来无事想写一个能直接生成3D立体画的程序。
思路很简单,我们的目的是在相机的图像中将需要显示的物体放置在纸面上,还是放出这个世界坐标和图像坐标的关系:
首先定义一个相机:
// 模拟相机类 var Camera = function() { var arr = [[1000, 0, 400], [0, 1000, 300], [0, 0, 1]]; this.intrinsic = new Matrix(arr); // 相机内参 var arr1 = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]]; this.extrinsic = new Matrix(arr1); //相机外参 var arr2 = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; this.rotate = new Matrix(arr2); // 相机旋转矩阵 this.camera_angle = 0; this.camera_distance = 100; this.camera_height = 100; this.camera_move = 0; }
然后我还创建了一个矩阵相乘类:
// 简单的矩阵库,只支持矩阵乘法 var Matrix = function(matrix) { this.matrix = matrix; this.rows = this.matrix.length; // 行数y this.cols = this.matrix[0].length; // 列数x } // 矩阵相乘 Matrix.prototype.dot = function(matrix) { var self_matrix = this; var cols = matrix.cols; var rows = this.rows; var result = new Array(rows); for(var i = 0; i < rows; i++) { result[i] = new Array(cols); } for(var i = 0; i < cols; i++) { for(var j = 0; j < rows; j++) { var sum = 0; for(var k = 0; k < self_matrix.cols; k++) { sum += self_matrix.matrix[j][k] * matrix.matrix[k][i]; } result[j][i] = sum; } } var new_matrix = new Matrix(result); return new_matrix; }
最关键的是接下来这个paper类,我模拟了一个A4纸,A4四个角点的世界坐标是已知给定的,根据相机内参和外参计算出其在图像中的坐标,就可以显示A4纸了。
// 纸张以中心旋转 Paper.prototype.rotate = function() { var arr = [[Math.cos(this.paper_angle), -Math.sin(this.paper_angle)], [Math.sin(this.paper_angle), Math.cos(this.paper_angle)]]; var rotate = new Matrix(arr); var corners = [ [[-105], [-148.5]], [[105], [-148.5]], [[105], [148.5]], [[-105], [148.5]] ]; for(var i = 0; i < corners.length; i++) { var point = new Matrix(corners[i]); var result = rotate.dot(point); this.corners[i][0] = result.matrix[0][0] + 105; this.corners[i][1] = result.matrix[1][0] + 148.5; } } // 在canvas上显示纸张 Paper.prototype.show = function(context1) { this.rotate(); var arr = [[1, 0, 0, -this.height/2 + self.camera.camera_move], [0, 1, 0, self.camera.camera_height], [0, 0, 1, self.camera.camera_distance]]; self.camera.extrinsic.set(arr); var arr1 = [[1, 0, 0], [0, Math.cos(self.camera.camera_angle), -Math.sin(self.camera.camera_angle)], [0, Math.sin(self.camera.camera_angle), Math.cos(self.camera.camera_angle)]]; self.camera.rotate.set(arr1); self.camera.extrinsic = self.camera.rotate.dot(self.camera.extrinsic); context1.beginPath(); var point = new Matrix([[this.corners[3][0]], [0], [this.corners[3][1]], [1]]); var result = self.camera.intrinsic.dot(self.camera.extrinsic).dot(point); context1.moveTo(result.matrix[0][0] / result.matrix[2][0], result.matrix[1][0] / result.matrix[2][0]); // 从左下角逆时针 for(var i = 0; i < this.corners.length; i++) { point = new Matrix([[this.corners[i][0]], [0], [this.corners[i][1]], [1]]); result = self.camera.intrinsic.dot(self.camera.extrinsic).dot(point); context1.lineTo(result.matrix[0][0] / result.matrix[2][0], result.matrix[1][0] / result.matrix[2][0]); } context1.strokeStyle = 'red'; context1.lineWidth = 1; context1.stroke(); }
最后是生成图像的代码,逻辑很简单,遍历A4中的每个像素点,投影到图像坐标系,获取到对应的像素值。
Generate.prototype.show = function(context1, context2) { var context1 = self.canvas1.getContext('2d'); var context2 = self.canvas2.getContext('2d'); context2.clearRect(0, 0, self.canvas2.width, self.canvas2.height); var imageData = context2.getImageData(0, 0, self.canvas2.width, self.canvas2.height); var img_data = imageData.data; for(var i = 0; i < self.paper.width; i++) { for(var j = 0; j < self.paper.height; j++) { var point = [j, i]; point = self.paper.rotate_point(point); var temp_point = new Matrix([[point[0]], [0], [point[1]], [1]]); var result = self.camera.intrinsic.dot(self.camera.extrinsic).dot(temp_point); var pixel = context1.getImageData(result.matrix[0][0] / result.matrix[2][0], result.matrix[1][0] / result.matrix[2][0], 1, 1); var data = pixel.data; img_data[4 * (i + j * self.paper.width)] = data[0]; img_data[4 * (i + j * self.paper.width) + 1] = data[1]; img_data[4 * (i + j * self.paper.width) + 2] = data[2]; img_data[4 * (i + j * self.paper.width) + 3] = data[3]; } } context2.putImageData(imageData, 0, 0); }
最后,我把代码上传到了github上:https://github.com/imuncle/3Ddraw
在线体验:https://imuncle.github.io/3Ddraw/
The text was updated successfully, but these errors were encountered:
强啊!以后就不需要手画了,直接打印出来
Sorry, something went wrong.
老板牛批
No branches or pull requests
3D立体画是裸眼3D的一种,最初是由一些极具创意的画家在街道或平地上创作的,后来又有了在纸上的绘制的作品。我的第一幅3D立体画是高二上画的:
然后上大学后许久没有画过了。
近期武汉新型冠状病毒肺炎疫情严重,只能呆在家,闲来无事想写一个能直接生成3D立体画的程序。
思路很简单,我们的目的是在相机的图像中将需要显示的物体放置在纸面上,还是放出这个世界坐标和图像坐标的关系:
首先定义一个相机:
然后我还创建了一个矩阵相乘类:
最关键的是接下来这个paper类,我模拟了一个A4纸,A4四个角点的世界坐标是已知给定的,根据相机内参和外参计算出其在图像中的坐标,就可以显示A4纸了。
最后是生成图像的代码,逻辑很简单,遍历A4中的每个像素点,投影到图像坐标系,获取到对应的像素值。
最后,我把代码上传到了github上:https://github.com/imuncle/3Ddraw
在线体验:https://imuncle.github.io/3Ddraw/
The text was updated successfully, but these errors were encountered: