在过去的两天里,我一直在尝试将 360 度相机、单鱼眼图像转换为节点 js 中的 equirectangular 查看器。在 stackoverflow 中,同样的问题在伪代码中被询问和回答。我一直在尝试将伪代码转换为节点 js 并清除了一些错误。现在项目运行没有错误,但输出图像是空白的。
从那个伪,我不知道polar_w,polar_h和geo_w,geo_h,geo和极坐标值,所以,它给出了静态值来显示输出。这是我将伪代码转换为节点 js 的链接。
如何将球坐标转换为等角投影坐标?.
这是我尝试将球面图像转换为 equirectangular 查看器的代码:
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 | var Jimp = require('jimp'); // Photo resolution var img_w_px = 1280; var img_h_px = 720; var polar_w = 1280; var polar_h = 720; var geo_w = 1280; var geo_h = 720; var img_h_deg = 70; var img_w_deg = 30; // Camera field-of-view angles var img_ha_deg = 70; var img_va_deg = 40; // Camera rotation angles var hcam_deg = 230; var vcam_deg = 60; // Camera rotation angles in radians var hcam_rad = hcam_deg/180.0*Math.PI; var vcam_rad = vcam_rad/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)], [0, 1, 0], [-Math.sin(vcam_rad), 0, Math.cos(vcam_rad)] ]; // Rotation around z-axis for horizontal rotation of camera var rot_z = [ [Math.cos(hcam_rad), -Math.sin(hcam_rad), 0], [Math.sin(hcam_rad), Math.cos(hcam_rad), 0], [0, 0, 1] ]; Jimp.read('./public/images/4-18-2-42.jpg', (err, lenna) => { polar = new Jimp(img_w_px, img_h_px); geo = new Jimp(img_w_px, img_h_px); for(var i=0; i<img_h_px; ++i) { for(var j=0; j<img_w_px; ++j) { // var p = img.getPixelAt(i, j); var p = lenna.getPixelColor(i, j) // var p = getPixels(img, { x: i, y: j }) // Calculate relative position to center in degrees var p_theta = (j - img_w_px / 2.0) / img_w_px * img_w_deg / 180.0 * Math.PI; var p_phi = -(i - img_h_px / 2.0) / img_h_px * img_h_deg / 180.0 *Math. PI; // Transform into cartesian coordinates var p_x = Math.cos(p_phi) * Math.cos(p_theta); var p_y = Math.cos(p_phi) * Math.sin(p_theta); var p_z = Math.sin(p_phi); var p0 = {p_x, p_y, p_z}; // Apply rotation matrices (note, z-axis is the vertical one) // First vertically var p1 = rot_y[1][2][3] * p0; var p2 = rot_z[1][2][3] * p1; // Transform back into spherical coordinates var theta = Math.atan2(p2[1], p2[0]); var phi = Math.asin(p2[2]); // Retrieve longitude,latitude var longitude = theta / Math.PI * 180.0; var latitude = phi / Math.PI * 180.0; // Now we can use longitude,latitude coordinates in many different projections, such as: // Polar projection { var polar_x_px = (0.5*Math.PI + phi)*0.5 * Math.cos(theta) /Math.PI*180.0 * polar_w; var polar_y_px = (0.5*Math.PI + phi)*0.5 * Math.sin(theta) /Math.PI*180.0 * polar_h; polar.setPixelColor(p, polar_x_px, polar_y_px); } // Geographical (=equirectangular) projection { var geo_x_px = (longitude + 180) * geo_w; var geo_y_px = (latitude + 90) * geo_h; // geo.setPixel(geo_x_px, geo_y_px, p.getRGB()); geo.setPixelColor(p, geo_x_px, geo_y_px); } // ... } } geo.write('./public/images/4-18-2-42-00001.jpg'); polar.write('./public/images/4-18-2-42-00002.jpg'); }); } |
并尝试了另一种方法,将图像分成四个部分来检测汽车。使用 image-slice 模块将图像切成四部分,并使用 jimp 模块进行读写。但不幸的是,没有正确检测到汽车。
这是我用于切片图像的代码:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var imageToSlices = require('image-to-slices'); var lineXArray = [540, 540]; var lineYArray = [960, 960]; var source = './public/images/4-18-2-42.jpg'; // width: 300, height: 300 imageToSlices(source, lineXArray, lineYArray, { saveToDir: './public/images/', clipperOptions: { canvas: require('canvas') } }, function() { console.log('the source image has been sliced into 9 sections!'); }); }//sliceImage |
为了从图像中检测汽车,我使用了 opencv4nodejs。未正确检测到汽车。这是我用于检测汽车的代码:
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 | if(img==null){ img = cv.imread('./public/images/section-1.jpg'); }else { img=cv.imread(img); } const minConfidence = 0.06; 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); cv.imwrite('./public/images/section-'+Math.random()+'.jpg', img); var name="distanceFromCamera"; var focalLen= 1.6 ;//Focal length in mm var realObjHeight=254 ;//Real Height of Object in mm var cameraFrameHeight=960;//Height of Image in pxl var imgHeight=960;//Image Height in pxl var sensorHeight=10;//Sensor height in mm var R = 6378.1 //#Radius of the Earth var brng = 1.57 //#Bearing is 90 degrees converted to radians. var hc=(200/100);//Camera height in m predictions .forEach((data)=> { // imgHeight=img.rows;//Image Height in pxl // realObjHeight=data.rect.height; // data.rect[name]=((focalLen)*(realObjHeight)* (cameraFrameHeight))/((imgHeight)*(sensorHeight)); var dc=(((data.rect.width * focalLen) / img.cols)*2.54)*100; // meters console.log(Math.floor(parseInt(data.rect.width))); // var dc=((Math.floor(parseInt(data.rect.width)* 0.264583) * focalLen) / img.cols); // mm var lat1=13.0002855;//13.000356; var lon1=80.2046441;//80.204632; // Gate 13.0002855,80.2046441 // Brazil Polsec : -19.860566, -43.969436 // var d=Math.sqrt((dc*dc)+(hc*hc)); // d=(data.rect[name])/1000; data.rect[name]=d=dc/1000; lat1 =toRadians(lat1); lon1 = toRadians(lon1); brng =toRadians(90); // lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) + // Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng)); // lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1), // Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2)); var lat2 = Math.asin(Math.sin(lat1) * Math.cos(d/6371) + Math.cos(lat1) * Math.sin(d/6371) * Math.cos(brng)); var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(d/6371) * Math.cos(lat1), Math.cos(d/6371) - Math.sin(lat1) * Math.sin(lat2)); lat2 = toDegrees(lat2); lon2 = toDegrees(lon2); data.rect['latLong']=lat2+','+lon2; // console.log(brng); }); response.send(predictions); cv.imshowWait('img', img); }; |
这里是需要转换成等距矩形的鱼眼图。
非常感谢任何帮助....
您在问如何将 360 度鱼眼投影转换为 equirectangular 投影。
为了做到这一点,对于鱼眼图像上的每个像素,您需要知道在输出图像上放置的位置。
您的输入图像是 1920x1080,让我们假设您要将其输出到相同大小的 equirectangular 投影。
输入圆映射定义为:
2 3 | cy = 540; // center of circle on Y-axis radius = 540; // radius of circle |
如果输入图像中有一个像素位于
2 3 4 5 6 | 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; |
因此,我们将鱼眼图像中的
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 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'); }); }); |
请注意,您仍然需要将像素与相邻像素混合(与调整图像大小时的原因相同)。
此外,在您的情况下,您只有一半的球体(您看不到天空中的太阳)。所以你需要使用
还要注意,给定的实现可能根本没有效率,最好直接使用缓冲区。
无论如何,在没有混合的情况下,我得出了如下所示的结果:
因此,为了进行混合,您可以使用最简单的方法,即最近邻方法。在这种情况下,您应该反转上面示例中的公式。无需将输入图像中的像素移动到输出图像中的正确位置,您可以遍历输出图像中的每个像素并询问我们可以使用哪个输入像素。这将避免黑色像素,但仍可能显示伪影:
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 | 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/2; var blendmap = {}; new jimp(outputwidth, outputheight, 0x000000ff, function(err, outputimage) { for(var y=0;y<outputheight;++y) { for(var x=0;x<outputwidth;++x) { var theta_deg = 360 - x * 360.0 / outputwidth - 180; var phi_deg = 90 - y * 90.0 / outputheight; var r = Math.sin(phi_deg * Math.PI / 180) var dx = Math.cos(theta_deg * Math.PI / 180) * r; var dy = Math.sin(theta_deg * Math.PI / 180) * r; var inputx = Math.round(dx * radius + cx); var inputy = Math.round(dy * radius + cy); outputimage.setPixelColor(inputimage.getPixelColor(inputx, inputy), x, y); } } outputimage.write('output.png'); }); }); |
仅供参考,以便在笛卡尔坐标系和球坐标系之间进行转换。这些是公式(取自此处)。请注意,在您的情况下,

这是生成的输出图像:

由于我不再在您的问题中看到您的原始输入图像,为了让任何人测试此答案中的代码,您可以使用以下图像:

运行代码:
2 3 4 5 6 7 8 | cd /tmp/test npm install --permanent jimp cat <<EOF >/tmp/test/main.js ... paste the javascript code from above ... EOF curl https://i.stack.imgur.com/0zWt6.png > input.png node main.js |
注意:为了进一步改进混合,您应该删除
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[
我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。
有没有一种简单的方法可以将给定的整数格式化为具有固定长度和前导零的字符串?#convertnumberstostringsoffixedlength3[1,12,123,1234].map{|e|???}=>["001","012","123","234"]我找到了解决方案,但也许还有更聪明的方法。format('%03d',e)[-3..-1] 最佳答案 如何使用%1000而不是进行字符串操作来获取最后三位数字?[1,12,123,1234].map{|e|format('%03d',e%1000)}更新:根据theTinMan的
我是ruby的新手,我正在尝试制作一个程序来自动格式化给定的字符串和数组。我试图弄清楚的一种自动格式化功能是一种用于数组的功能。假设我有一个如下例所示的数组myArray=["a","b","c"]我想把它变成一个列化的字符串,这样putsmyString就会给出`1)a``2)b``3)c`我该怎么做呢?我能找到的最接近的东西是使用.each这不是我想要的,我不能让每一行都有一个单独的条目。这一切都必须是一个带有换行符的字符串。任何帮助将不胜感激,提前致谢 最佳答案 您可以使用.map与.with_index:myArray=