HITS(科普向)

文章整理自:https://blog.csdn.net/hguisu/article/details/8013489 简介 HITS(HITS(Hyperlink - Induced Topic Search) ) 算法是由康奈尔大学(Cornell University)的Jon Kleinberg博士于1997年首先提出的,为IBM公司阿尔马登研究中心(IBM Almaden Research Center)的名为“CLEVER”的研究项目中的一部分。 HITS算法是链接分析中非常基础且重要的算法,目前已被Teoma搜索引擎(www.teoma.com)作为链接分析算法在实际中使用。 Hub页面与Authority页面 Hub页面(枢纽页面)和Authority页面(权威页面)是HITS算法最基本的两个定义。 所谓“Authority”页面,是指与某个领域或者某个话题相关的高质量网页,比如搜索引擎领域,Google和百度首页即该领域的高质量网页,比如视频领域,优酷和土豆首页即该领域的高质量网页。 所谓“Hub”页面,指的是包含了很多指向高质量“Authority”页面链接的网页,比如hao123首页可以认为是一个典型的高质量“Hub”网页。 图1给出了一个“Hub”页面实例,这个网页是斯坦福大学计算语言学研究组维护的页面,这个网页收集了与统计自然语言处理相关的高质量资源,包括一些著名的开源软件包及语料库等,并通过链接的方式指向这些资源页面。这个页面可以认为是“自然语言处理”这个领域的“Hub”页面,相应的,被这个页面指向的资源页面,大部分是高质量的“Authority”页面。 HITS算法的目的即是通过一定的技术手段,在海量网页中找到与用户查询主题相关的高质量“Authority”页面和“Hub”页面,尤其是“Authority”页面,因为这些页面代表了能够满足用户查询的高质量内容,搜索引擎以此作为搜索结果返回给用户。 算法分析 基本思想:相互增强关系 基本假设1: 一个好的“Authority”页面会被很多好的“Hub”页面指向; 基本假设2: 一个好的“Hub”页面会指向很多好的“Authority”页面; 步骤 具体算法:可利用上面提到的两个基本假设,以及相互增强关系等原则进行多轮迭代计算,每轮迭代计算更新每个页面的两个权值,直到权值稳定不再发生明显的变化为止。 根集合 将查询q提交给基于关键字查询的检索系统,从返回结果页面的集合总取前n个网页(如n=200),作为根集合(root set),记为root,则root满足: root中的网页数量较少root中的网页是与查询q相关的网页root中的网页包含较多的权威(Authority)网页 这个集合是个有向图结构:$G(V,E)$ 扩展集合 在根集root的基础上,HITS算法对网页集合进行扩充(参考图2)集合base,扩充原则是:凡是与根集内网页有直接链接指向关系的网页都被扩充到集合base,无论是有链接指向根集内页面也好,或者是根集页面有链接指向的页面也好,都被扩充进入扩展网页集合base。HITS算法在这个扩充网页集合内寻找好的“Hub”页面与好的“Authority”页面。 计算扩展集base中所有页面的Hub值(枢纽度)和Authority值(权威度) $a(i), h(i)$ 分别表示网页结点 i 的Authority值(权威度)和Hub值(中心度)。对于“扩展集base”来说,我们并不知道哪些页面是好的“Hub”或者好的“Authority”页面,每个网页都有潜在的可能,所以对于每个页面都设立两个权值,分别来记载这个页面是好的Hub或者Authority页面的可能性。在初始情况下,在没有更多可利用信息前,每个页面的这两个权值都是相同的,可以都设置为1,即:$a_0=1, h_0=1$每次迭代计算Hub权值和Authority权值: 网页$a(i)$在此轮迭代中的Authority权值即为所有指向网页$a(i)$页面的Hub权值之和: $$a(i)=\sum{h(i)}$$ 网页$a(i)$的Hub分值即为所指向的页面的Authority权值之和: $$h(i)=\sum{a(i)}$$ 对$a(i), h(i)$进行规范化处理: 将所有网页的中心度都除以最高中心度以将其标准化: $$a(i)=\frac{a(i)}{|a(i)|}$$将所有网页的权威度都除以最高权威度以将其标准化: $$h(i)=\frac{h(i)}{|h(i)|}$$如此不断的重复3:上一轮迭代计算中的权值和本轮迭代之后权值的差异,如果发现总体来说权值没有明显变化,说明系统已进入稳定状态,则可以结束计算,即$a(u), h(v)$收敛。 如图3所示,给出了迭代计算过程中,某个页面的Hub权值和Authority权值的更新方式。假设以A(i)代表网页i的Authority权值,以H(i)代表网页i的Hub权值。在图4的例子中,“扩充网页集合”有3个网页有链接指向页面1,同时页面1有3个链接指向其它页面。那么,网页1在此轮迭代中的Authority权值即为所有指向网页1页面的Hub权值之和;类似的,网页1的Hub分值即为所指向的页面的Authority权值之和。 输出排序结果 将页面根据Authority权值得分由高到低排序,取权值最高的若干页面作为响应用户查询的搜索结果输出。 HITS算法存在的问题 HITS算法整体而言是个效果很好的算法,目前不仅应用在搜索引擎领域,而且被“自然语言处理”以及“社交分析”等很多其它计算机领域借鉴使用,并取得了很好的应用效果。尽管如此,最初版本的HITS算法仍然存在一些问题,而后续很多基于HITS算法的链接分析方法,也是立足于改进HITS算法存在的这些问题而提出的。 归纳起来,HITS算法主要在以下几个方面存在不足: 计算效率较低 因为HITS算法是与查询相关的算法,所以必须在接收到用户查询后实时进行计算,而HITS算法本身需要进行很多轮迭代计算才能获得最终结果,这导致其计算效率较低,这是实际应用时必须慎重考虑的问题。 主题漂移问题 如果在扩展网页集合里包含部分与查询主题无关的页面,而且这些页面之间有较多的相互链接指向,那么使用HITS算法很可能会给予这些无关网页很高的排名,导致搜索结果发生主题漂移,这种现象被称为“紧密链接社区现象”(Tightly-Knit CommunityEffect)。 易被作弊者操纵结果 HITS从机制上很容易被作弊者操纵,比如作弊者可以建立一个网页,页面内容增加很多指向高质量网页或者著名网站的网址,这就是一个很好的Hub页面,之后作弊者再将这个网页链接指向作弊网页,于是可以提升作弊网页的Authority得分。 结构不稳定 所谓结构不稳定,就是说在原有的“扩充网页集合”内,如果添加删除个别网页或者改变少数链接关系,则HITS算法的排名结果就会有非常大的改变。 HITS算法与PageRank算法比较 HITS算法和PageRank算法可以说是搜索引擎链接分析的两个最基础且最重要的算法。从以上对两个算法的介绍可以看出,两者无论是在基本概念模型还是计算思路以及技术实现细节都有很大的不同,下面对两者之间的差异进行逐一说明。 HITS算法是与用户输入的查询请求密切相关的,而PageRank与查询请求无关。所以,HITS算法可以单独作为相似性计算评价标准,而PageRank必须结合内容相似性计算才可以用来对网页相关性进行评价;HITS算法因为与用户查询密切相关,所以必须在接收到用户查询后实时进行计算,计算效率较低;而PageRank则可以在爬虫抓取完成后离线计算,在线直接使用计算结果,计算效率较高;HITS算法的计算对象数量较少,只需计算扩展集合内网页之间的链接关系;而PageRank是全局性算法,对所有互联网页面节点进行处理;从两者的计算效率和处理对象集合大小来比较,PageRank更适合部署在服务器端,而HITS算法更适合部署在客户端;HITS算法存在主题泛化问题,所以更适合处理具体化的用户查询;而PageRank在处理宽泛的用户查询时更有优势;HITS算法在计算时,对于每个页面需要计算两个分值,而PageRank只需计算一个分值即可;在搜索引擎领域,更重视HITS算法计算出的Authority权值,但是在很多应用HITS算法的其它领域,Hub分值也有很重要的作用;从链接反作弊的角度来说,PageRank从机制上优于HITS算法,而HITS算法更易遭受链接作弊的影响。HITS算法结构不稳定,当对“扩充网页集合”内链接关系作出很小改变,则对最终排名有很大影响;而PageRank相对HITS而言表现稳定,其根本原因在于PageRank计算时的“远程跳转”。

MCLK和PCLK的区别与联系

PCLK:pixel clock, used for MCU camera sensor controller to capture each pixel. MCLK:master clock for sensor logical chip. HSYNC and VSYNC used for MCU camera sensor controller to capture the pixels line by line and frame by frame. They work just like the LCD reversely. mclk由BB提供,是CCM sensor的时钟源。 mclk经过sensor处理后变成传输数据所需要的时钟PCLK,将数据传到BB端

android开发注意事项

1、某些机型rom定制较为严格,在后台(按home键返回)的应用会在某一时间段被杀掉 解决:application中添加registerActivityLifecycleCallbacks方法,监听Activity生命周期,在生命周期中进行某些判断 2、运行在Android Q设备上,并且设置了target>28,权限设置会不同,参考高德定位中对android Q的权限适配 3、android 10 系统获取图片权限问题 选择照片路径为null? 解决:androidmanifest中<application android:requestLegacyExternalStorage = “true”>

TypeScript超详细入门教程(上)

TypeScript超详细入门教程(上) 01 开篇词:Hello~TypeScript 01 开篇词:Hello~TypeScript 更新时间:2019-10-30 13:49:46 既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。——康德 同学你好,我是Lison。很高兴你对TypeScript感兴趣,或许你对TypeScript了解还不多,或许还有很多疑问,比如: 学 TypeScript 是不是就不需要学 JavaScript 了? Vue 用 TypeScript 改写发布 3.0 后是不是不用 TypeScript 不行? TypeScript 靠谱吗? 诸如此类疑惑,导致你一直对它犹豫不决,那么本节我将代替 TypeScript 向你做一个自我介绍。 同学你好,我是 TypeScript,如果你觉得我是 JavaScript 的孪生兄弟,或者觉得我是前端圈新扶持起来的太子,那你可能对我是有点误解了。其实我并不是一个新的语言,用大家公认的说法,我是JavaScript的超集,你可以理解为,我是加了一身装备铭文的进化版 JavaScript。JavaScript 有的,我都有,而且做得更好。JavaScript 没有的,我也有,而且我是在很长一段时间内不会被 JavaScript 赶上的。 虽然我作为超集,但是我始终紧跟 ECMAScript 标准,所以 ES6/7/8/9 等新语法标准我都是支持的,而且我还在语言层面上,对一些语法进行拓展。比如新增了枚举(Enum)这种在一些语言中常见的数据类型,对类(Class)实现了一些ES6标准中没有确定的语法标准等等。 如果你是一个追赶技术潮流的开发者,那你应该已经将 ES6/7/8/9 语法用于开发中了。但是要想让具有新特性的代码顺利运行在非现代浏览器,需要借助Babel这种编译工具,将代码转为ES3/5版本。而我,可以完全不用 Babel,就能将你的代码编译为指定版本标准的代码。这一点,我可以说和 JavaScript 打了个平手。 另外我的优势,想必你也略有耳闻了那就是我强大的类型系统。这也是为什么造世主给我起名TypeScript。如果你是一名前端开发者,或者使用过 JavaScript 进行开发,那么你应该知道,JavaScript 是在运行的时候,才能发现一些错误的,比如: 访问了一个对象没有的属性; 调用一个函数却少传了参数; 函数的返回值是个字符串你却把它当数值用了; … 这些问题在我这里都不算事。我强大的类型系统可以在你编写代码的时候,就检测出你的这些小粗心。先来简单看下我工作的样子: interface 定义的叫接口,它定义的是对结构的描述。下面的 info 使用 ES6 的新关键字 const 定义,通过 info: Info 指定 info 要实现 Info 这个结构,那 info 必须要包含 name 和 age 这两个字段。实际代码中却只有 name 字段,所以你可以看到 info 下面被红色波浪线标记了,说明它有问题。当你把鼠标放在 info 上时,VSCode 编辑器会做出如下提示:

最新最全百度网盘在线倍速播放方法

(这篇文章写的稍微长一点,因为我想让大家细节性的了解一些东西,同时我比较喜欢发图片,这样的话印象比较深刻。阅读这篇文章大概需要5分钟时间,实际操作大概10分钟可以完成!) 今天,我想试试百度网盘的在线播放视频,因为学习使用。这个加速功能还是不错的。 那么,最新最全的方法是哪些? 我首先想到的方案就是谷歌的video speed control插件,但是发现这个插件不能对网盘视频加速。 1.开通会员(土豪使用) 2.下载视频之后,电脑可以使用PotPlayer进行倍速播放 如图所示,可以进行快捷键调整倍速播放,按C是加速,X是减速。 注意,这中方法可以对任何的视频使用,不光是百度网盘,你只要把视频下载下来就可以,PotPlayer倍速调整的范围很大,最高能达到12倍(这么快的播放其实用处不大) 并且,PotPlayer体积小,是个不错的播放器。 3.(核心)在线播放 (1)使用Edge浏览器,Edge浏览器登录百度网盘首页,打开你的网盘里面的视频,点击右键就可以倍速播放。 右键选择播放速度即可调整。 优点:方便快捷,很多win10系统自带的浏览器是Edge,不用下载新的浏览器。 缺点:只能加速固定倍速比如1.5,2。不能1.2,1.3 (2)谷歌浏览器(推荐这个方法) 谷歌打开网页后F12输入 videojs.getPlayers("video-player").html5player.tech_.setPlaybackRate(1.5) 之后回车就可以 这个方法好处是可以调任意倍率! 可以建立一个书签,用于快速输入代码! 只需要点击这个书签就可以! javascript:videojs.getPlayers("video-player").html5player.tech_.setPlaybackRate(1.5) 没错,代码与刚才的完全一样,只是添加书签的时候需要前面加上前缀javascript: 注意冒号必须打! 可以建立多个书签达到任意调速度的目的,很方便使用。我个人喜欢1.1,1.2,1.5 所有方法都有时效性,以上方案是我目前测试可用、不是很复杂的方案。 有人说火狐也可以,大家也可以试试。最后选择一个可用的方法就可以。以上是最新可以用的方案。

【C++】数据结构 struct,结构体相关操作

代码: #include <iostream> #include <cstring> using namespace std; struct Book{ char title[50]; char author[50]; double price; int bookId; }; void printBook(struct Book book){ cout << "书名:" << book.title <<endl; cout << "作者:" << book.author <<endl; cout << "价格:" << book.price <<endl; cout << "ID:" << book.bookId <<endl; } int main(){ Book book1; Book book2; strcpy(book1.title,"C++ 教程"); strcpy(book1.author, "Runoob"); book1.price = 51.50; book1.bookId = 123456; strcpy(book2.title, "Python 教程"); strcpy(book2.author, "GuidoVanRossum"); book2.

详解throws方式

1.语法: throws+异常类型 1⃣️写在方法的声明处。指出此方法执行时,可能会抛出的异常类型。一旦当方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象。此对象满足throws后异常类型时,就会被抛出。异常代码后面的代码就不会再执行了。 2⃣️try-catch-finally:真正将异常给处理掉了。 throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉。 public class ExceptionTest2 { public static void main(String[] args){ CC cc=new CC(); try { cc.method2(); }catch (IOException e){ e.printStackTrace(); } // cc.method3(); } } class CC{ public static void method1() throws FileNotFoundException, IOException { File file = new File("hello.txt"); FileInputStream fis = new FileInputStream(file); int data = fis.read(); while (data != -1) { System.out.print((char) data); data = fis.read(); } fis.close(); } public static void method2() throws IOException{ //IOException是 // FileNotFoundException的父类 method1(); } public static void method3(){ try { method2(); }catch (IOException e){ e.

win10安装jdk1.8(附国内下载镜像)

0. JDK版本的选择 JDK 13 都已经发布了,JDK5,6,7,8,9,10,11,12和13怎么选择版本,2018年12月,由 Snyk 和 The Java Magazine 联合推出发布的 2018 JVM 生态调查报告 显示有 70% 的用户使用 Oracle JDK,21% 的用户使用 OpenJDK。其中 Java 8 的使用者占到了 79%。都已经 JDK 13 了,为什么还有这么多公司使用旧版本。Java 8 已经算好的了,有的公司还在使用 7,更有甚者还在用 6,你说是不是很 6。之所以会出现这种状况,是因为升级版本耗时费力,最重要的是有可能影响服务的稳定性,虽然说 Java 是向后兼容的,但是谁知道是不是有坑在里面。在没有重大安全漏洞或重大性能提升的情况下,大多数公司还是以稳定性为主,既然 Java 8 已经能满足业务需求了,那就用它好了。 1. 下载JDK1.8 我选择的是Java SE Development Kit 8u202,首先需要接受协议,然后点击jdk-8u202-windows-x64.exe进行下载。我不是从官网下载的,下图仅仅是一个实例。 官网下载需要登录,而且下载速度比较慢,推荐使用国内的下载镜像。华为提供的下载服务:https://repo.huaweicloud.com/java/jdk/清华大学提供的下载服务:https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/ 2. 安装jdk1.8 安装JDK 选择安装目录 安装过程中会出现两次 安装提示 。第一次是安装 jdk ,第二次是安装 jre 。建议两个都安装在同一个java文件夹中的不同文件夹中。注意: 不能都安装在java文件夹的根目录下,jdk和jre安装在同一文件夹会出错。 创建文件夹E:\JDK1.8(202) 用于安装 jdk ,创建文件夹E:\JRE 用于安装 jre 安装 jdk,选择的文件夹为 E:\JDK1.8(202) 安装 jre ,安装的路径是:E:\JRE

python3基础篇(七)——函数

python3基础篇(七)——函数 前言: 1 阅读这篇文章我能学到什么? 这篇文章将为你详细介绍python3函数的用法,将会非常详细。 ——如果你觉得这是一篇不错的文章,希望你能给一个小小的赞,感谢您的支持。 目录 python3基础篇(七)——函数 1 定义函数2 函数调用2.1 如何调用一个函数2.2 函数参数与可变及不可变类型2.2.1 可变及不可变类型2.2.2 可变及不可变类型函数参数2.2.3 几种函数参数2.2.3.1 必选参数2.2.3.2 关键字参数2.2.3.3 可选参数2.2.3.3 不定长参数2.2.3.4 强制必选参数2.2.3.4.1 /参数2.2.3.4.2 *参数 2.3 递归调用 3 匿名函数3.1 匿名函数的定义3.2 匿名函数的参数 程序的函数概念就类似数学上的函数概念。按照一定语法结构能完成特定的功能的代码段,函数可以具有输入和输出(严格来说函数必须具有输出,没有任何输出的函数是没有意义的,只是语法结构上满足函数定义)。 1 定义函数 python3以def关键字表示定义函数,随后自定义一个函数名,需要注意函数名在作用域内不能同名(后面补一章讲下python3的作用域吧,这里不懂先不必纠结)。函数名之后()内为参数列表,参数列表可以为空,它表示传入函数的参数。最后不要忘了:符号。另起一行的是可选的“函数说明字符串”,用于对函数简要描述,可省略不写。函数体必须比函数名至少缩进一个空格或table。与c/c++类似,函数可以搭配return关键词结束函数并返回一个值给调用方,当函数不需要返回值时可以返回None,也可以省略None,甚至可以省略return。 语法结构: def FunctionName(ParameterList): "Information" FunctionBody 代码示例: def Fun1(): #无参数函数 "函数描述信息" #这不是必须的,看个人喜好,我个人是不喜欢在这里写函数注释 print("Fun1") #无返回值,省略return def Fun2(a): #单参数参数列表 print("Fun2: %d" % (a)) return None #无返回值,返回None相当于无返回值 def Fun3(a, b): #多个参数的参数列表 print("Fun3: %d" % (a + b)) return #无返回值 #可以看到上面三种函数返回值都是等同的,返回值都是None print(Fun1()) print(Fun2(1)) print(Fun3(1, 2)) 运行结果:

java牛客网②-Spring Boot实践,开发社区登录模块

2.1 发送邮件 邮箱设置 src/main/resources/application.properties # MailProperties spring.mail.host=smtp.qq.com spring.mail.port=465 spring.mail.username=你的邮箱 spring.mail.password=你的授权码 spring.mail.protocol=smtps spring.mail.properties.mail.smtp.ssl.enable=true spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true 邮箱实例 src/main/java/com/nowcoder/community/util/MailClient.java package com.nowcoder.community.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; @Component public class MailClient { private static final Logger logger = LoggerFactory.getLogger(MailClient.class); @Autowired private JavaMailSender mailSender; @Value("${spring.mail.username}") private String from; public void sendMail(String to, String subject, String content) { try { MimeMessage message = mailSender.

深度学习自学记录(3)——两种多分类混淆矩阵的Python实现(含代码)

深度学习自学记录(3)——两种多分类混淆矩阵的Python实现(含代码) 1、什么是混淆矩阵2、分类模型评价指标3、两种多分类混淆矩阵3.1直接打印出每一个类别的分类准确率。3.2打印具体的分类结果的数值 4、总结 1、什么是混淆矩阵 深度学习中,混淆矩阵是ROC曲线绘制的基础,同时它也是衡量分类型模型准确度中最基本,最直观,计算最简单的方法。它可以直观地了解分类模型在每一类样本里面表现,常作为模型评估的一部分。它可以非常容易的表明多个类别是否有混淆(也就是一个class被预测成另一个class)。 首先要明确几个概念: T或者F:该样本 是否被正确分类。 P或者N:该样本 原本是正样本还是负样本。 真正例(True Positive,TP):预测正确;模型预测也是正例,样本的真实类别是正例, 真负例(True Negative,TN):预测正确:模型预测为负例,样本的真实类别是负例, 伪正例(False Positive,FP):预测错误:模型预测为正例,样本的真实类别是负例, 伪负例(False Negative,FN):预测错误;模型预测为负例,样本的真实类别是正例, 将这四个指标一起呈现在表格中,就能得到如下这样一个矩阵,我们称它为混淆矩阵(Confusion Matrix),这里从其他博客偷了张图: 在混线矩阵中,以对角线为分界线。以上图为例子:对角线的位置表示预测正确,对角线以外的位置表示把样本错误的预测为其他样本。 2、分类模型评价指标 从混淆矩阵可以直观地看出各个参数的数值大小。 查准率是在模型预测为正的所有样本中,模型预测对的比重,即:“分类器认为是正类并且确实是正类的部分占所有分类器认为是正类的比例”。计算公式如下式所示: P r e c i s i o n = T P / ( T P + F P ) Precision=TP/(TP+FP) Precision=TP/(TP+FP) 召回率是在真实值是正的所有样本中,模型预测对的比重,即:“分类器认为是正类并且确实是正类的部分占所有确实是正类的比例”。计算公式如下式所示: R e c a l l = T P / ( T P + F N ) Recall=TP/(TP+FN) Recall=TP/(TP+FN) F1-Score指标综合了Precision与Recall的产出的结果。F1-Score的取值范围从0到1的,1代表模型的输出最好,0代表模型的输出结果最差,计算公式如下式所示: 除了F1分数之外,F2分数和F0.5分数在统计学中也得到大量的应用。其中,F2分数中,召回率的权重高于精准率,而F0.5分数中,精准率的权重高于召回率。 3、两种多分类混淆矩阵 多分类混淆矩阵根据不同需求可以绘制不同的矩阵:

leetcode C++ 6. Z 字形变换 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

一、思路: 对于Z字型的第i行数据为:let temp1=(row-i-1)*2 temp2=i*2 i i+temp1 i+temp1+temp2 1+temp1*2+temp2 1+temp1*2+2*temp ... 二、C++代码: class Solution { public: string convert(string s, int numRows) { if (numRows < 2) return s; int N = s.size(); string res = s; int count = 0; for (int i = 0; i < numRows; i++) { res[count++] = s[i]; int nowPos = i; int temp1 = (numRows - i - 1) * 2; int temp2 = 2 * i; while (nowPos < N) { nowPos += temp1; if (nowPos >= N) break; if (i !

三维重建系列——坐标系从二维到三维

首先上一个总图: 下面依次介绍平移坐标,内参矩阵外参矩阵的具体表示: 一,图像坐标系和像素坐标系 像素坐标系中,每一像素的坐标(u,v)分别是该像素在数组中的列数和行数。所以(u,v)是以像素为单位的图像坐标系的坐标。由于(u,v)只表示像素位于数组中的行列数,并没有用物理单位表示出该像素在图像中的位置。所以建立以物理单位(毫米)表示的图像坐标系。该坐标系以图像内某一点O为原点,原点O定义在相机光轴与图像平面的交点,该点一般位于图像中心处.x轴与y轴分别与u、v两轴平行,如下图所示; 若O在u,v坐标系中的坐标为(u0,v0),每一个像素在x轴与y轴方向上的物理尺寸为dx、dy,则图像中任意一个像素在两个标系下的坐标有如下对应关系: 用齐次坐标与矩阵形式将上式表示为平移公式: 二,二维到三维的转换 首先完成从相机坐标系到图像坐标系的转化, 其中由焦距组成的矩阵为投影矩阵,将平移公式代入可得其中,Zc为比例因子, 为u轴上的尺度因子,也称为u轴上的归一化焦距; 为v轴上的尺度因子,也称为v轴上的归一化焦距;由于 这些参数只与相机的内部参数有关,因此他们所组成的矩阵成为称为相机的内参矩阵 三,相机坐标系向世界坐标系的转换关系 下图所示为相机成像的几何关系。其中O点称为相机光心,Xc轴与x轴平行,Yc轴与图像的y轴平行,Zc轴为相机的光轴,并且与图像平面垂直。光轴与图像平面的交点即为图像坐标系的原点,由点O点与Xc,Yc,Zc轴所组成的直角坐标系称为相机坐标系,其中OOc为相机焦距。相机坐标系与世界坐标系之间的关系可以用旋转矩阵R与平移向量t来描述。假设空间中某一点P在世界坐标系与相机坐标系下的齐次坐标分别是(Xw,Yw,Zw,1)T与(Xc,Yc,Zc,1)T,则存在如下对应关系: 其中,K2矩阵包含了旋转矩阵和平移矩阵,这是将相机坐标下的坐标转化为世界坐标系的过程,由相机相对于世界坐标系的方位决定,因此称K2为外参矩阵维度为4*4。

leetcode C++ 48. 旋转图像 给定一个 n × n 的二维矩阵表示一个图像。 将图像顺时针旋转 90 度。

一、思路: 某一个的转化后的路径变化:(i,j)-->(j,n-1-i)-->(n-1-i,n-1-j)-->(i,j), 所以转变一个,就等于转变4个,n为偶数数时,遍历n*n/4;n为奇数时,遍历(n*n-1)/4,因为中心不会变化 二、代码: class Solution { public: void rotate(vector<vector<int>>& matrix) { int n = matrix.size(); for (int i = 0; i < (n + 1) / 2; i++) { for (int j = 0; j < (n) / 2; j++) { int temp = matrix[i][j]; matrix[i][j] = matrix[n - 1 - j][i]; matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j]; matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i]; matrix[j][n - 1 - i] = temp; } } } };

Dev-c++怎么设置背景色

我们在使用Dev-c++这个软件的时候,遇到夜晚等的条件下,希望使用一种暗一点的颜色,而默认的是白色的背景十分亮眼,如何进行设置呢? 在教程的开始先附上设置后的效果图 显然这种背景更加适合晚上开发。话不多说,直接开始设置步骤。 设置步骤: 1.菜单上面的工具选项 2.点击编辑器选项 3.点击语法 语法的预设里面有很多种设置,我这里设置的是Twillight 但是设置好后有个问题,我们发现,选中一行后会有个很亮眼的蓝色的杠,这种严重影响了体验感 那么怎么去掉这个杠呢?很简单就可以 1.点击编辑器选项 2,将高亮显示当前行去掉 这样,看上去就舒服一些了 最终效果

Visual Studio 2019 Community 许可证过期解决方法

Visual Studio 2019 Community 许可证过期怎么解决? 今天使用的时候发现我的VS打不开了,点击更新许可证,“无法下载许可证,请检查你的网络连接或代理设置”。他提示我许可证过期,然后我即使点击更新许可证仍然不行! 后来经过探索找到了解决方法: 1.找到你的VS安装位置,如果找不到的话,右击图标,选择属性,然后打开文件位置 2.进入路径 3.注意到点击DDConfigCA.exe 点击这个文件会立刻闪退,然后重启VS,就可以了!

pyqt5如何在同一个窗口下切换不同界面

本文为浙江大学数据库系统课程lab5进行图书管理系统设计过程中的经验总结 ——zju gehao 问题的提出和基本前提 网上找了半天也没发现什么靠谱的解答,自己捣鼓着花费了好几个小时,总算是发现了两种能用的方法,先假设一下使用的场景:现在窗口的右半部分有两个界面想要切换显示 我们主体窗口的控件为self.main_widget,网格布局为self.main_layout,分为左右两部分: 布局的左半部分为self.left_widget,它的作用是导航栏(标签和按钮),因此有一个就足够了布局的右半部分是self.right_widget,我想通过点击不同的按钮让这个区域显示不同的界面,但由于一个Qwidget只能容纳一组layout的布局,因此怎么切换界面是一个很令人苦恼的问题 我总结出了两种思路: 首先前提是,必须要有2个(或者两个以上的界面),每一个界面我都用一个Qwidget来表示,这个Qwidget里面可以使用QGridlayout网格布局(或者其他布局)来存放各种各样不同的子控件,比如按钮、标签、文本框等 假设我已经准备好了self.right_widget1和self.right_widget2,整体布局、左侧布局和右侧两个界面的布局如下所示: class MainUi(QMainWindow): def __init__(self): super().__init__() self.init_ui() def init_ui(self): ''' 初始化整体布局 ''' self.resize(1000, 800) self.desktopWidth = QApplication.desktop().width() # 获取当前桌面的宽 self.desktopHeight = QApplication.desktop().height() # 获取当前桌面的高 self.main_widget = QWidget() # 创建窗口主部件 self.main_widget.setObjectName('main_widget') # 对象命名 self.main_layout = QGridLayout() # 创建网格布局的对象 self.main_widget.setLayout(self.main_layout) # 将主部件设置为网格布局 self.init_left() # 初始化左侧空间 self.init_right() # 初始化右侧空间 # 将初始化完成的左侧、右侧空间加入整体空间的网格布局 self.main_layout.addWidget(self.left_widget, 0, 0, 1, 1) self.main_layout.addWidget(self.right_widget1, 0, 1, 1, 6) #self.main_layout.addWidget(self.right_widget2, 0, 1, 1, 6) self.

7个必备网站,查征信、查三无产品、查老赖、查犯罪记录!

7个必备网站,查征信、查三无产品、查老赖、查犯罪记录! 网站介绍 1、全国企业信用信息公示系统:http://www.gsxt.gov.cn/index.html 介绍:毕业学生找工作不知道公司靠不靠谱,可以上这里查询面试公司是不是正规公司。 2、中国执行信息公开网:http://zxgk.court.gov.cn/?dt_dapp=1 介绍:输入姓名或身份证号就可以查到一个人的失信记录,可以查询企业法人、老板、对象是否靠谱,也可以在借钱之前查看对方是否是老赖! 3、征信中心(银行一般规定:一个月不要查询超过三次):https://ipcrs.pbccrc.org.cn/ 介绍:这个是用来查询自己的个人信用记录,违约、延迟还款和查询是否存在不良记录,信用不足会影响银行贷款等行为! 4、中国裁判文书网:http://wenshu.court.gov.cn 介绍:输入你要查询的人物姓名,检索对方的各种信息,刑事案件,个人经济纠纷,债权债务信息一目了然! 5、国家药品监督管理局:http://www.nmpa.gov.cn/WS04/CL2042/ 介绍:输入检索项目搜索,凡是没有通过国家药监局备案的产品都是三无产品! 6、商务部直销行业管理:http://zxgl.mofcom.gov.cn 介绍:可以查询所处单位是是传销还是直销! 7、莆系网:http://m.putianxi.cn/ 介绍:可以查询全国各地的莆田系医院! 使用介绍 使用方法都很简单, 直接输入检索目标即可, 使用方法和百度等搜索引擎差不多。 更对资源请关注作者对应的专栏!

【笔记】跟着LearnOpenGL自说自话地学习OpenGL(三)

呼,又是搬砖忙碌的一天,回到家坐下来不禁思考了一下,学这玩意跟我搬砖的工作半毛钱关系都没有忙着干啥? Em……可能是觉得好玩? 打开教程的"你好,三角形"章节,开头的那一段描述让我一阵头皮发麻,文字太长,图都不想截了,免得影响我笔记的篇幅,有兴趣的童鞋自己读一读吧。 大概提炼一下关键词: 图形渲染管线,大白话描述一下就是:举个栗子,大家高中都学过空间直角坐标系吧?真实的空间直角坐标系你画在纸上的这个过程。再具体点就是用数学方法描述的三维坐标(x,y,z),但是屏幕就像一张纸呀,显卡(注意这是显卡不是CPU了哦)就这样把一个三维的图形很多很多的坐标点变成屏幕上很多很多的像素点让你看上去画的跟三维的一样,另外别忘了我们看到的都是彩图,还可以给这些像素点涂上很真实的颜色,就这么个工具的样子。 着色器,就上面说的这个画图的过程,再细分一下步骤,其实这是两个人干的事情,一个人在画点,一个人在上色,画点的那个人叫顶点着色器,上色的那个人叫片段着色器。为了告诉OpenGL这个大家伙如何去把图形画准确并且画的更有色彩,OpenGL着色器语言OpenGL Shading Language, GLSL就成了我们的画笔来书写逻辑步骤。 其余的内容,什么顶点数组对象:Vertex Array Object,VAO,顶点缓冲对象:Vertex Buffer Object,VBO等等概念。后面拿代码来用大白话聊聊,现在写到这里聊这玩意,我自己还搞不懂,硬上这不耍流氓么? 接下来看一下,我们描述三角形常用坐标来描述,这里先搞一个数组这。 float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; 这里又有一些概念要理解了,怎么这么麻烦? Z坐标为深度坐标,描述的是屏幕到想要模拟的虚拟空间距离,这个好理解 标准化设备坐标(Normalized Device Coordinates),我还是先贴官方描述吧 咋理解? 我觉着是这么个过程,首先我们的屏幕大小完全是不可控的,想想自己的手机屏幕和电脑屏幕,那么我在描述物体大小的时候定义的一系列坐标完全不可能适配所有屏幕。所以将坐标数据单位化成为标准化设备坐标,然后再真正的屏幕上再次按照一定比例进行坐标转换(glViewport函数,视口变换Viewport Transform),这样我们可以获得,更多尺寸的画面。是不是比较像拍照的过程?景物->底片->巨幅相片 不过实际上这也是对之前一篇笔记这个函数的理解: void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } 接下来开始准备撸代码,首先又要接触第一个OpenGL对象,顶点缓冲对象(Vertex Buffer Objects, VBO),还来? 在OpenGL的教程中,接下来的代码部分LearnOpenGL给予了大量的详细解释,但是我觉得有个缺陷就是,知识讲解过于零散,并没有把整个代码给串起来,作为笔记,我还是按照自己的理解思路做一个宏观上的理解,分模块进行总结然后再深入细节理解 第一部分,着色器程序的使用 const char *vertexShaderSource = "#version 330 core\n" //顶点着色器 "layout (location = 0) in vec3 aPos;\n"