Converting 360 degree view to equirectangular in node js?
在过去的两天里,我一直在尝试将 360 度相机、单鱼眼图像转换为节点 js 中的 equirectangular 查看器。在 stackoverflow 中,同样的问题在伪代码中被询问和回答。我一直在尝试将伪代码转换为节点 js 并清除了一些错误。现在项目运行没有错误,但输出图像是空白的。
从那个伪,我不知道polar_w,polar_h和geo_w,geo_h,geo和极坐标值,所以,它给出了静态值来显示输出。这是我将伪代码转换为节点 js 的链接。
如何将球坐标转换为等角投影坐标?.
这是我尝试将球面图像转换为 equirectangular 查看器的代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
exports.sphereImage=(request, response)=>{
var Jimp = require(‘jimp’); // Photo resolution var img_w_px = 1280; var polar_w = 1280; var img_h_deg = 70; // Camera field-of-view angles var img_ha_deg = 70; // Camera rotation angles var hcam_deg = 230; // Camera rotation angles in radians var hcam_rad = hcam_deg/180.0*Math.PI; // Rotation around y-axis for vertical rotation of camera var rot_y = [ [Math.cos(vcam_rad), 0, Math.sin(vcam_rad)], ]; // Rotation around z-axis for horizontal rotation of camera var rot_z = [ [Math.cos(hcam_rad), –Math.sin(hcam_rad), 0], ]; Jimp.read(‘./public/images/4-18-2-42.jpg’, (err, lenna) => {
polar = new Jimp(img_w_px, img_h_px); for(var i=0; i<img_h_px; ++i) var p = lenna.getPixelColor(i, j) // Calculate relative position to center in degrees // Transform into cartesian coordinates // Apply rotation matrices (note, z-axis is the vertical one) // Transform back into spherical coordinates // Retrieve longitude,latitude // Now we can use longitude,latitude coordinates in many different geo.write(‘./public/images/4-18-2-42-00001.jpg’); }); } |
并尝试了另一种方法,将图像分成四个部分来检测汽车。使用 image-slice 模块将图像切成四部分,并使用 jimp 模块进行读写。但不幸的是,没有正确检测到汽车。
这是我用于切片图像的代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
exports.sliceImage=(request, response)=>{
var imageToSlices = require(‘image-to-slices’); imageToSlices(source, lineXArray, lineYArray, { }//sliceImage |
为了从图像中检测汽车,我使用了 opencv4nodejs。未正确检测到汽车。这是我用于检测汽车的代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
function runDetectCarExample(img=null){
if(img==null){ img = cv.imread(‘./public/images/section-1.jpg’); const predictions = classifyImg(img).filter(res => res.confidence > minConfidence && res.className==‘car’); const drawClassDetections = makeDrawClassDetections(predictions); const getRandomColor = () => new cv.Vec(Math.random() * 255, Math.random() * 255, 255); drawClassDetections(img, ‘car’, getRandomColor); // imgHeight=img.rows;//Image Height in pxl var dc=(((data.rect.width * focalLen) / img.cols)*2.54)*100; // meters
var lat1=13.0002855;//13.000356; // lon2 = lon1 +
var lat2 = Math.asin(Math.sin(lat1) * Math.cos(d/6371) + var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(d/6371) * Math.cos(lat1), lat2 = toDegrees(lat2); });
response.send(predictions); |
这里是需要转换成等距矩形的鱼眼图。
非常感谢任何帮助….
- 有很多代码供我们在这里切入以查找问题,尤其是当您还没有明确说明问题的真正含义时。我认为你需要做的是减少它,专注于你的问题的核心,并使用像 Mocha 这样的单元测试框架编写测试,清楚地定义一系列输入值的预期行为。
- 你应该清理你的问题,并坚持你所问的抽象核心。您需要的是鱼眼投影映射到等角投影。在复制之前,最好先了解一下这到底是什么
您在问如何将 360 度鱼眼投影转换为 equirectangular 投影。
为了做到这一点,对于鱼眼图像上的每个像素,您需要知道在输出图像上放置的位置。
您的输入图像是 1920×1080,让我们假设您要将其输出到相同大小的 equirectangular 投影。
输入圆映射定义为:
|
1
2 3 |
cx = 960; // center of circle on X-axis
cy = 540; // center of circle on Y-axis radius = 540; // radius of circle |
如果输入图像中有一个像素位于 (x,y) 处,那么我们可以使用以下方法计算球坐标:
|
1
2 3 4 5 6 |
dx = (x – cx) * 1.0 / radius;
dy = (y – cy) * 1.0 / radius; theta_deg = atan2(dy, dx) / MATH_PI * 180; phi_deg = acos(sqrt(dx*dx + dy*dy)) / MATH_PI * 180; outputx = (theta_deg + 180) / 360.0 * outputwidth_px; outputy = (phi_deg + 90) / 180.0 * outputheight_px; |
因此,我们将鱼眼图像中的 (x,y) 转换为 equirectangular 图像中的 (outputx,outputy)。为了不让实现成为可怕的”读者练习”,这里是一些使用 OP 使用的 Jimp 库的示例 Javascript 代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
var jimp = require(‘jimp’);
var inputfile = ‘input.png’; jimp.read(inputfile, function(err, inputimage) { var cx = 960; var cy = 540; var radius = 540; var inputwidth = 1920; var inputheight = 1080; var outputwidth = 1920; var outputheight = 1080; new jimp(outputwidth, outputheight, 0x000000ff, function(err, outputimage) { for(var y=0;y<inputheight;++y) { for(var x=0;x<inputwidth;++x) { var color = inputimage.getPixelColor(x, y); var dx = (x – cx) * 1.0 / radius; var dy = (y – cy) * 1.0 / radius; var theta_deg = Math.atan2(dy, dx) / Math.PI * 180; var phi_deg = Math.acos(Math.sqrt(dx*dx + dy*dy)) / Math.PI * 180; var outputx = Math.round((theta_deg + 180) / 360.0 * outputwidth); var outputy = Math.round((phi_deg + 90) / 180.0 * outputheight); outputimage.setPixelColor(color, outputx, outputy); } } outputimage.write(‘output.png’); }); }); |
请注意,您仍然需要将像素与相邻像素混合(与调整图像大小时的原因相同)。
此外,在您的情况下,您只有一半的球体(您看不到天空中的太阳)。所以你需要使用 var outputy = Math.round(phi_deg / 90.0 * outputheight)。为了保持正确的纵横比,您可能需要将高度更改为 540.
还要注意,给定的实现可能根本没有效率,最好直接使用缓冲区。
无论如何,在没有混合的情况下,我得出了如下所示的结果:

来源:https://www.codenong.com/51869432/
