如何在高空照片中高效找到地平线?

2024-02-09

我试图检测从高空拍摄的图像中的地平线,以确定相机的方向。我也试图让它运行得更快 - 理想情况下,我希望能够在 Raspberry Pi 上实时处理帧(即每秒几帧)。到目前为止我所采取的方法是基于这样一个事实:在高海拔地区,天空非常暗,如下所示:

我尝试过从整个图像中采集样本,并将它们分成浅色和深色样本,并在它们之间画一条线。然而,由于大气层的模糊性,这会将地平线置于其实际位置之上:

这是我的代码(用 Javascript 编写,以便于进行网络演示):

function mag(arr) {
    return Math.sqrt(arr[0]*arr[0]+arr[1]*arr[1]+arr[2]*arr[2])
}
// return (a, b) that minimize
// sum_i r_i * (a*x_i+b - y_i)^2
function linear_regression( xy ) {
    var i,
        x, y,
        sumx=0, sumy=0, sumx2=0, sumy2=0, sumxy=0, sumr=0,
        a, b;
    for(i=0;i<xy.length;i++) {
        x = xy[i][0]; y = xy[i][2];
        r = 1
        sumr += r;
        sumx += r*x;
        sumx2 += r*(x*x);
        sumy += r*y;
        sumy2 += r*(y*y);
        sumxy += r*(x*y);
    }
    b = (sumy*sumx2 - sumx*sumxy)/(sumr*sumx2-sumx*sumx);
    a = (sumr*sumxy - sumx*sumy)/(sumr*sumx2-sumx*sumx);
    return [a, b];
}


var vals = []
for (var i=0; i<resolution; i++) {
            vals.push([])
            for (var j=0; j<resolution; j++) {
                    x = (canvas.width/(resolution+1))*(i+0.5)
                    y = (canvas.height/(resolution+1))*(j+0.5)
                    var pixelData = cr.getImageData(x, y, 1, 1).data;
                    vals[vals.length-1].push([x,y,pixelData])
                    cr.fillStyle="rgb("+pixelData[0]+","+pixelData[1]+","+pixelData[2]+")"
                    cr.strokeStyle="rgb(255,255,255)"
                    cr.beginPath()
                    cr.arc(x,y,10,0,2*Math.PI)
                   cr.fill()
                    cr.stroke()
            }
    }
    var line1 = []
    var line2 = []
    for (var i in vals) {
            i = parseInt(i)
            for (var j in vals[i]) {
                    j = parseInt(j)
                    if (mag(vals[i][j][3])<minmag) {
                            if ((i<(vals.length-2) ? mag(vals[i+1][j][4])>minmag : false)
                             || (i>0 ? mag(vals[i-1][j][5])>minmag : false)
                             || (j<(vals[i].length-2) ? mag(vals[i][j+1][6])>minmag : false)
                             || (j>0 ? mag(vals[i][j-1][7])>minmag : false)) {
                                    cr.strokeStyle="rgb(255,0,0)"
                                    cr.beginPath()
                                    cr.arc(vals[i][j][0],vals[i][j][8],10,0,2*Math.PI)
                                    cr.stroke()
                                    line1.push(vals[i][j])
                            }
                    }
                    else if (mag(vals[i][j][9])>minmag) {
                            if ((i<(vals.length-2) ? mag(vals[i+1][j][10])<minmag : false)
                             || (i>0 ? mag(vals[i-1][j][11])<minmag : false)
                             || (j<(vals[i].length-2) ? mag(vals[i][j+1][12])<minmag : false)
                             || (j>0 ? mag(vals[i][j-1][13])<minmag : false)) {
                                    cr.strokeStyle="rgb(0,0,255)"
                                    cr.beginPath()
                                    cr.arc(vals[i][j][0],vals[i][j][14],10,0,2*Math.PI)
                                    cr.stroke()
                                    line2.push(vals[i][j])
                            }
                    }
            }
        }
        eq1 = linear_regression(line1)
        cr.strokeStyle = "rgb(255,0,0)"
        cr.beginPath()
        cr.moveTo(0,eq1[1])
        cr.lineTo(canvas.width,canvas.width*eq1[0]+eq1[1])
        cr.stroke()
        eq2 = linear_regression(line2)
        cr.strokeStyle = "rgb(0,0,255)"
        cr.beginPath()
        cr.moveTo(0,eq2[1])
        cr.lineTo(canvas.width,canvas.width*eq2[0]+eq2[1])
        cr.stroke()
        eq3 = [(eq1[0]+eq2[0])/2,(eq1[1]+eq2[1])/2]
        cr.strokeStyle = "rgb(0,255,0)"
        cr.beginPath()
        cr.moveTo(0,eq3[1])
        cr.lineTo(canvas.width,canvas.width*eq3[0]+eq3[1])
        cr.stroke()

结果(绿线是检测到的地平线,红色和蓝色是估计的边界外):

我该如何改进这个?还有更有效的方法吗?最终的程序可能会用 Python 编写,如果速度太慢,也可能用 C 编写。


考虑一些基本的通道混合和阈值处理,然后按照 @Spektre 的建议进行垂直采样。 [根据 @Spektre 的评论,更改为 2*R-B 而不是 R+G-B]

以下是通道混合的一些选项:

  1. Original
  2. 扁平单声道混音 R+G+B
  3. 红色通道
  4. 2*R - B
  5. 右+G-B

看起来#4是最清晰的地平线(感谢@Spektre让我更仔细地检查这一点),以[红2:绿0:蓝-1]的比例混合颜色,你会得到这个单色图像:

设置蓝色负值意味着地平线上的蓝色薄雾用于消除那里的模糊性。事实证明,这比仅使用红色和/或绿色更有效(尝试使用 GIMP 中的通道混合器)。

然后,如果您愿意,我们可以通过阈值化(尽管您可以在采样后执行此操作)进一步澄清,此处为 25% 灰度:

使用 Spektre 的垂直采样图像的方法,只需向下扫描,直到看到值超过 25%。使用 3 条线,您应该获得 3 个 x,y 对,从而重建曲线,知道它是抛物线。

为了提高鲁棒性,请采集 3 个以上的样本并丢弃异常值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在高空照片中高效找到地平线? 的相关文章

  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 如何从浏览器向服务器发送“页面将关闭”消息?

    我想向每个 html 文档添加一个脚本 JavaScript 该脚本向服务器发送两条消息 页面确实打开了 页面将关闭 此消息包含页面打开的时间 打开消息应在文档加载时 或加载完成时 发送 这是简单的部分 The close message
  • 使用javascript动态更新css内容

    需要将 css 更新为动态值 我不确定最好的方法是什么 div style zoom 1 div 缩放级别将根据窗口大小调整触发 应用程序将相应缩放 我将此应用程序加载到 cordova 中并让它在 iPAD 中运行 然后我意识到需要使用
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • $resource.query 返回分割字符串(字符数组)而不是字符串

    我正在使用像下面这样的 Angular resource angular module app factory data function resource var Con resource api data update method P
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • VSCode:调试配置中的 Python 路径无效

    对 Python 和 VSCode 以及 stackoverflow 非常陌生 直到最近 我已经使用了大约 3 个月 一切都很好 当尝试在调试器中运行任何基本的 Python 程序时 弹出窗口The Python path in your
  • 如何从没有结尾的管道中读取 python 中的 stdin

    当管道来自 打开 时 不知道正确的名称 我无法从 python 中的标准输入或管道读取数据 文件 我有作为例子管道测试 py import sys import time k 0 try for line in sys stdin k k
  • glpk.LPX 向后兼容性?

    较新版本的glpk没有LPXapi 旧包需要它 我如何使用旧包 例如COBRA http opencobra sourceforge net openCOBRA Welcome html 与较新版本的glpk 注意COBRA适用于 MATL
  • 使用 Enzyme 测试 `React.createRef` api

    我想测试下面的类 它使用React createRef api 不过 快速搜索并没有发现任何这样做的例子 有人成功过吗 我该如何嘲笑裁判 理想情况下我想使用shallow class Main extends React Component
  • 有没有办法使用 ko.observableArray 作为地图?

    有没有办法使用ko observableArray http knockoutjs com documentation observableArrays html像地图 字典一样 例如 var arr ko observableArray
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 如何使用google colab在jupyter笔记本中显示GIF?

    我正在使用 google colab 想嵌入一个 gif 有谁知道如何做到这一点 我正在使用下面的代码 它并没有在笔记本中为 gif 制作动画 我希望笔记本是交互式的 这样人们就可以看到代码的动画效果 而无需运行它 我发现很多方法在 Goo
  • 在 iOS 7 Safari 中,如何区分通过边缘滑动与后退/前进按钮的 popstate 事件?

    在 iOS 7 Safari 中 现在有两种后退 前进导航方式 使用底部的传统后退 前进按钮箭头或从屏幕边缘滑动 我正在使用动画在 ajax 应用程序中的页面之间进行转换 但如果用户通过边缘滑动进行导航 我不想触发该转换 因为这本身就是一个
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • 在 Python 类中动态定义实例字段

    我是 Python 新手 主要从事 Java 编程 我目前正在思考Python中的类是如何实例化的 我明白那个 init 就像Java中的构造函数 然而 有时 python 类没有 init 方法 在这种情况下我假设有一个默认构造函数 就像
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • 您可以在 Python 类型注释中指定方差吗?

    你能发现下面代码中的错误吗 米皮不能 from typing import Dict Any def add items d Dict str Any gt None d foo 5 d Dict str str add items d f
  • 如何通过索引访问 JSON 对象中的字段

    我知道这不是最好的方法 但我别无选择 我必须通过索引访问 JSONObject 中的项目 访问对象的标准方法是只写this objectName or this objectName 我还找到了一种获取 json 对象内所有字段的方法 fo
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐

  • C++中传递成员函数指针

    我正在尝试传递一个函数指针 类型为QScriptEngine FunctionSignature QScriptValue QScriptContext QScriptEngine 到另一个函数 但我需要传递的函数是类的成员函数 我这样使用
  • 网络x绘制_网络x_边缘capstyle

    有谁知道在通过 例如 绘制networkx边缘时是否可以对线条属性进行细粒度控制draw networkx edges 我想控制线路solid capstyle and solid joinstyle 它们是 matplotlib Line
  • 选择 Atom 中所有找到的 RegEx 结果

    我正在尝试选择正则表达式查找找到的所有结果 以便我可以全部修改它们 不要用文本替换它们 例如 将它们全部大写Cmd K gt Cmd U 我知道我could通过重复来一项一项地做Cmd G Cmd K Cmd U 但对于大文件来说 这根本不
  • Laravel 4 绕过路由的维护模式

    我已将我的应用程序放下以进行维护php artisan down命令 我的自定义维护页面作为电子邮件输入 用于接受来自用户的电子邮件并存储在我的数据库中 以便在站点备份并再次运行时通知用户 但是当我使用 POST 提交表单时 我被重定向到维
  • mViewPager.getCurrentItem() 不返回第一个和最后一个寻呼机的正确位置

    我正在尝试获取视图寻呼机的页码 我遇到了很多Stackoverflow Q A 他们都说要使用 currentposition mViewPager getCurrentItem 但此方法不适用于第一页和最后一页 如何解决这个问题 提前致谢
  • 运行 Hadoop 作业时不是有效的 Jar

    我想运行 WordCount 示例 在eclipse中运行正确 在输出文件夹中存在输出文件 我制作了WordCount的jar文件并想通过命令运行它 hadoop jar WordCount jar Projects input Proje
  • 使用index.js在React中导入多个图像资源

    我一直在使用一种收集组件文件以供导出的模式index js文件放置在目录中 例如 index js file in components directory export Splash from Splash export Portfoli
  • 使用 Spring Boot 重命名 Liquibase 变更日志表

    我在用着Liquibase v 3 5 3 和 一起Spring 启动 v 1 5 3 我想使用 spring boot 属性文件更改 liquibase 变更日志表名称 我发现做到这一点的唯一方法是设置liquibase database
  • 找到具有相同权重的最大边数的生成树

    问题就在这里 给出一个带权无向连通图G 权重是恒定的 任务是提出一种算法 找到满足这两个条件的 G 的生成树的总权重 按优先级排序 生成树必须有相同权重的最大边数 与实际重复重量值无关 应最小化总生成树重量 这意味着 例如 权重为 120
  • 为什么.NET不验证BCL/CLR?

    BCL 和 CLR 中的所有 NET 程序集 以后仅使用 CLR 都是强命名和数字签名 https stackoverflow com questions 1334631 signing of net assemblies 提供数字证书是为
  • AngularJS,防止在茉莉花测试期间启动控制器上的 init 方法

    我有一个带有在实例化时启动的 init 方法的控制器 它做了很多对我的应用程序在实时环境中有用的事情 但这会扰乱我的单元测试间谍 在单元测试环境中实例化控制器时 有没有办法阻止它的调用 或者也许有一种方法可以在 web 应用程序上下文中自动
  • 这个R符号是什么意思?

    我将主题模型的文本上传到第四列 但显示的不是文本 而是此符号 当我将鼠标悬停在它上面时 我可以阅读文本 但是 我想确保这个符号不会误导我的结构主题模型分析 谢谢你 我刚刚运行主题模型没有问题 我认为这个符号表明单元格包含大文本 例如 几页单
  • R 将 RSelenium 驱动程序环境作为函数参数传递

    我可能没有看到明显的东西 无论如何我想创建函数来自动从远程驱动程序已处理的 URL 中提取文本 我想将 xpath 表达式和可以找到远程驱动程序的环境作为函数参数传递 library RSelenium url http stackover
  • ActiveMQ:如何使旧消息出队?

    我正在学习如何使用ActiveMQ 现在我们面临以下问题 假设我在 ActiveMQ 上有一个名为 topic test 的主题 它有两个订阅者 在特定时刻 我只有一个订阅者在等待消息 而生产者则为我上面提到的主题发送一条消息 好的 连接的
  • 没有模块前缀路由路径的 Rails 名称范围模型对象

    我对 Rails 路由器和表单生成器有一点问题 我的应用程序具有用于模型和控制器的命名空间模块 模块用于更轻松地抽象到另一个项目 我用在routes rb范围方法而不是命名空间 因为我不想有 丑陋 的路径助手 看起来像 scope modu
  • 如何使用 scrapy.Request 将另一个页面的元素加载到项目中

    我使用 Scrapy 创建了一个网络抓取工具 它能够从每张票证中抓取元素website http www vividseats com concerts awolnation tickets html但无法刮掉票价 因为页面上没有该票价 当
  • 如何将预先填充的 Default.realm 文件加载到设备上?

    我有一个领域文件 其中已填充了在设备上加载应用程序时需要的数据 我可以做什么来将领域文件获取到我的设备上进行测试 以及当有人从应用程序商店下载应用程序时 我需要做什么来确保它已经存在 我正在使用斯威夫特 Add your database
  • Intellij 14.1.4 CE spring boot 1.3.0.M1,spring-dev-tools 热重载不起作用

    刚刚使用 spring 初始化程序和 spring dev tools 启动了一个 spring boot 应用程序 然后导入到 Intellij 14 1 4 CE 中 我可以使用 gradle 很好地运行应用程序bootRun但无法使热
  • javascript图像覆盖在指定的div上

    我是 JavaScript 新手 实际上很新 这应该是我的第一个脚本 谁能向我解释如何在任何指定的固定宽度区域 例如 700x300px 上制作透明叠加层 您可以定义覆盖 例如 div class myoverlay contents di
  • 如何在高空照片中高效找到地平线?

    我试图检测从高空拍摄的图像中的地平线 以确定相机的方向 我也试图让它运行得更快 理想情况下 我希望能够在 Raspberry Pi 上实时处理帧 即每秒几帧 到目前为止我所采取的方法是基于这样一个事实 在高海拔地区 天空非常暗 如下所示 我