首页 文章 精选 留言 我的

精选列表

搜索[快速入门],共10000篇文章
优秀的个人博客,低调大师

OSS 数据湖实践 —— EMR+OSS入门

对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件;E-MapReduce(EMR)构建于云服务器ECS上,基于开源的Apache Hadoop和Apache Spark,可以方便地使用Hadoop和Spark生态系统中的其他周边系统(例如,Apache Hive、Apache Pig和HBase等)来分析和处理数据;E-MapReduce还可以与阿里云的云数据存储系统OSS进行数据传输,把二者各自优势结合起来,使存储计算分离,方便快捷搭建大数据计算环境,实现大数据分析需求。 前提条件 • 已注册阿里云账号,详情请参见注册阿里云账号。• 已开通E-MapReduce服务和OSS服务。• 已完成云账号的授权,详情请参见角色授权。 步骤一:创建EMR集群及相关配置 在使用spark 操作oss中的数据之前,您需要在本地安装MAVEN、JAVA、SCALA环境,以及在E-MapReduce上创建Hadoop集群。 1、在本地安装JAVA、MAVEN、SCALA环境; 2、登录阿里云E-MapReduce控制台,创建Hadoop集群(可选服务中必选spark、smartdata、bigboot、knox服务) 3、在创建集群时,设置knox账号密码,挂载公网 及设置集群登录密码; 4、集群创建之后,在集群服务smartdata smartdata-site配置oss数据源; 增加两个配置项,分别为fs.jfs.cache.oss-accessKeyId、fs.jfs.cache.oss-accessKeySecret;然后点击保存,以及右上方操作中重启组件; 5、登录hadoop集群header节点,验证oss 数据源是否生效 hadoop fs -ls oss://your-bucket-name/dir/ #测试读OSS hadoop fs -mkdir oss://your-bucket-name/dir/ #测试写OSS 步骤二:使用EMR集群提交spark作业,读写OSS 1、编写spark代码,从OSS中读取json数据,然后向OSS写入delta格式数据,制作为jar包 import org.apache.spark.sql.{Row, SparkSession} object WriteOSS { def main(args: Array[String]): Unit = { val spark = SparkSession .builder .appName("Spark OSS") .getOrCreate() val data=spark.read.json("oss://bucketname/test.json") data.write.format("delta").save("oss://bucketname/test_delta_data") } } 2、把jar包上传至EMR集群上,然后把jar包放在本地hdfs下,或者利用hadoop命令把jar包上传到oss中都可 • 使用scp工具把jar包传送到EMR集群的header节点上• 把jar包拷贝到oss bucket下 ./ossutil64 cp test.jar oss://bucket-name/dir • 把jar包拷贝到本地集群hfs文件系统中 hadoop fs -put localfile hdfsfile 3、在数据开发中创建spark job作业 4、在test job编辑框中输入作业提交命令 --class OSSReadWrite --master yarn --deploy-mode client --driver-memory 5g --num-executors 50 --executor-memory 3g --executor-cores 3 --conf spark.default.parallelism=500 --conf spark.yarn.am.memoryOverhead=1g --conf spark.yarn.am.memory=2g oss://your-bucket-name/test.jar 5、运行作业,查看作业日志 总结 至此,我们就完成了从创建EMR hadoop集群,配置好OSS数据源,开发OSS读写作业,数据开发中创建test job,提交作业,并且查看运行日志一系列操作。在此基础之上,我们可以根据个人需求,进行其他作业开发,分析利用OSS上存储的数据。

优秀的个人博客,低调大师

【从入门到放弃-Java】工具-词频分析

前言 最近有根据文件内容进行词频分析的需求,如果是纯英文的,写个程序处理比较容易,但涉及到中文词频分析,最关键的一步就是中文分词。 搜了不少文章,最后找到一篇比较好用的 Java实现中文词频统计。主要利用了ansj_seg进行中文分词,分词后再进行词频统计。 针对文章中提供的代码示例,做了稍许改动,贴在下面 做个记录。 依赖 添加最新版ansj_seg依赖 <dependency> <groupId>org.ansj</groupId> <artifactId>ansj_seg</artifactId> <version>5.1.6</version> </dependency> 代码实现 代码可见 AloofJr package com.my.tools.ansj; import com.alibaba.common.lang.StringUtil; import org.ansj.splitWord.analysis.ToAnalysis; import java.io.*; import java.util.*; /** * 对文件中文分词后,根据词频排序输出 * @author wq * @date 2020/4/8 */ public class Analysis { public static void main(String[] args) throws IOException { wordFrequency(""); } public static void wordFrequency(String path) throws IOException { List<Map.Entry<String, Integer>> wordList = getWordList(path); wordList.forEach(entry -> { System.out.println(entry.getKey() + "\t" + entry.getValue()); }); } /** * 获取 分词-词频 列表 * */ private static List<Map.Entry<String, Integer>> getWordList(String path) throws IOException { Map<String, Integer> map = new HashMap<>(16); String result = ToAnalysis.parse(getString(path)).toStringWithOutNature(); //分词后的内容,分词间使用英文逗号分隔。 String[] words = result.split(","); for (String word : words) { String str = word.trim(); // 过滤空白字符 if (StringUtil.isBlank(str)) { continue; } // 过滤一些高频率的符号 else if (str.matches("[)|(|.|,|。|+|-|“|”|:|?|\\s]")) { continue; } // 此处过滤长度为1的str else if (str.length() < 2) { continue; } if (!map.containsKey(word)) { map.put(word, 1); } else { int n = map.get(word); map.put(word, ++n); } } return sortByValue(map); } /** * 根据词频从高到低排序 * */ private static List<Map.Entry<String, Integer>> sortByValue(Map<String, Integer> map) { if (map == null) { return null; } List<Map.Entry<String, Integer>> list = new ArrayList<>(); list.addAll(map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return o2.getValue().compareTo(o1.getValue()); } }); return list; } /** * 获取文件内容 * */ private static String getString(String path) throws IOException { FileInputStream inputStream = new FileInputStream(new File(path)); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder strBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { strBuilder.append(line); } reader.close(); inputStream.close(); return strBuilder.toString(); } } 参考 作者:Asche 出处:https://www.cnblogs.com/asche/p/9673611.html 更多文章 见我的博客:https://nc2era.com written by AloofJr,转载请注明出处

优秀的个人博客,低调大师

Spark 进阶之路之「SparkSQL」入门概述

云栖号:https://yqh.aliyun.com第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策! 在之前的文章中,我们已经完成了对于Spark核心SparkCore的详细介绍。而今天想为为大家介绍的是SparkSQL的概述。 什么是Spark SQL? Spark SQL是Spark用来处理结构化数据的一个模块,它提供了2个编程抽象:DataFrame和DataSet,并且作为分布式SQL查询引擎的作用。 我们已经学习了Hive,它是将Hive SQL转换成MapReduce然后提交到集群上执行,大大简化了编写MapReduc的程序的复杂性,由于MapReduce这种计算模型执行效率比较慢。所有Spark SQL的应运而生,它是将Spark SQL转换成RDD,然后提交到集群执行,执行效率非常快! Spark SQL的特点 1)易整合 2)统一的数据访问方式 3)兼容Hive 4)标准的数据连接 什么是DataFrame? 与RDD类似,DataFrame也是一个分布式数据容器。然而DataFrame更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即schema。 同时,与Hive类似,DataFrame也支持嵌套数据类型(struct、array和map)。从API易用性的角度上看,DataFrame API提供的是一套高层的关系操作,比函数式的RDD API要更加友好,门槛更低。 上图直观地体现了DataFrame和RDD的区别。左侧的RDD[Person]虽然以Person为类型参数,但Spark框架本身不了解Person类的内部结构。而右侧的DataFrame却提供了详细的结构信息,使得Spark SQL可以清楚地知道该数据集中包含哪些列,每列的名称和类型各是什么。DataFrame是为数据提供了Schema的视图。可以把它当做数据库中的一张表来对待,DataFrame也是懒执行的。性能上比RDD要高,主要原因:优化的执行计划:查询计划通过Spark catalyst optimiser(Spark的优化器)进行优化。 比如下面一个例子: 为了说明查询优化,我们来看上图展示的人口数据分析的示例。图中构造了两个DataFrame,将它们join之后又做了一次filter操作。如果原封不动地执行这个执行计划,最终的执行效率是不高的。因为join是一个代价较大的操作,也可能会产生一个较大的数据集。如果我们能将filter下推到 join下方,先对DataFrame进行过滤,再join过滤后的较小的结果集,便可以有效缩短执行时间。而Spark SQL的查询优化器正是这样做的。 简而言之,逻辑查询计划优化就是一个利用基于关系代数的等价变换,将高成本的操作替换为低成本操作的过程。 什么是DataSet? 1)是Dataframe API的一个扩展,是Spark最新的数据抽象。2)用户友好的API风格,既具有类型安全检查也具有Dataframe的查询优化特性。3)Dataset支持编解码器,当需要访问非堆上的数据时可以避免反序列化整个对象,提高了效率。 4)样例类被用来在Dataset中定义数据的结构信息,样例类中每个属性的名称直接映射到DataSet中的字段名称。 5)Dataframe是Dataset的特列,DataFrame=Dataset[Row] ,所以可以通过as方法将Dataframe转换为Dataset。Row是一个类型,跟Car、Person这些的类型一样,所有的表结构信息我都用Row来表示。 6)DataSet是强类型的。比如可以有Dataset[Car],Dataset[Person] 7)DataFrame只是知道字段,但是不知道字段的类型,所以在执行这些操作的时候是没办法在编译的时候检查是否类型失败的,比如你可以对一个String进行减法操作,在执行的时候才报错,而DataSet不仅仅知道字段,而且知道字段类型,所以有更严格的错误检查。就跟JSON对象和类对象之间的类比。 本次分享就到这里,你还有什么想知道的或者对本文有什么建议,欢迎在评论区告诉我们! 云栖号:https://yqh.aliyun.com第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策! 原文发布时间:2020-03-04本文作者:Alice菌本文来自:“CSDN云计算”,了解相关信息可以关注“CSDN云计算”

优秀的个人博客,低调大师

每日一博 | Charles 从入门到精通

内容清单 Charles 的简介 安装 Charles Charles 初始化设置 过滤网络请求 截取HTTP/HTTPS数据 模拟弱网环境 修改网络请求 修改服务器返回内容 服务器压力测试 反向代理 解决与翻墙软件的冲突 Charles 的简介 Charles 是目前最主流的网络调试工具(Charles、Fiddler、Wireshark...)之一,对于一个开发者来说与网络打交道是日常需求,因此很多时候我们需要调试参数、返回的数据结构、查看网络请求的各种头信息、协议、响应时间等等。所以了解 Charles 并使用它 Charles 通过将自己设置为系统的网络访问代理服务器,这样所有的网络请求都会通过它,从而实现了网路请求的截获和分析。 Chareles 不仅可以分析电脑本机的网络请求(HTTP 和 HTTPS),还可以分析移动端设备的网络请求。 Charles 是收费软件,作者开发出这样一个方便开发者使用的伟大工具,我们鼓励使用正版软件,但是对于一些囊中羞涩或者学生来说,有破解版的更好,别担心,这些我都准备好了,下一个 section 会讲解如何下载安装。 安装 Charles 方式1: Charles 官网地址,根据你的电脑操作系统选择合适的下载方式。此时下载下来的是需要收费的,不差钱的同学当然可以直接购买。购买链接 方式2:按照方式1的方式去官网下载,然后下载相应 JAR包。这里以 MAC 为例,打 Finder,选择应用程序,选中 Charles,右击并选择“显示包内容”,看到 Contents 目录,点击进去选择 Java 文件夹,将下载下来的 JAR包 拖进去替换。至此,完成了 Charles 的破解。 Charles 初始化设置 Charles 的工作原理是将自身设置为系统的代理服务器来捕获所有的网络请求。所以使用 Charles ,我们必须设置 Charles 为系统的代理服务器。 打开 Charles,当第一次启动的时候如果没有购买或者没有破解,会有倒计时,之后会看到软件的主界面,然后会请求你赋予它为系统代理的权限。点击授权会让你输入当前系统用户的密码。当然你也可以忽略或者拒绝该请求,然后等想要抓包的时候将它设置为系统的代理服务器。步骤:**选择菜单中的“Proxy” -> "Mac OS X Proxy"。**如下图: 之后你的电脑上的任何网络请求都可以在 Charles 的请求面板中看到 看看 Charles 的主界面 图上红色圈1:这里代表所有网络请求的展示方式。分别名为 “Structure” 和 “Sequence”。 Structure 将所有的网络请求按照域名划分并展示 Sequence 将所有的网络请求按照时间排序并展示 图上红色圈2:一些的网络请求设置比如 HTTPS 以及端口等信息都在这个菜单栏设置 图上红色圈3:证书设置都在这里进行 过滤网络请求 由于 Charles 可以将电脑或者设置过的手机的所有网络请求捕获到,而且我们分析网络传输应该是针对某个特定的网络下的抓包分析,为了清楚明显地看到我们感兴趣的网络请求通常会用到 Charles 的**“过滤网络请求的功能”**。 方法1:在 Charles 主面板的左侧所有网络请求的下方可以看到看到一个 ”Filter“ 输入栏,在这里你可以输入关键词来筛选出自己感兴趣的网络请求。比如我想分析的网络请求来自于”www.baidu.com" 下,你可以在下面输入"baidu"即可。 方法2:在 Charles 菜单栏的顶部会看到 “Proxy” 的选项,点击菜单栏选择 “Proxy” -> "Recording Settings" 。选择 “include”。看到面板上面有一个 “Add” 按钮,点击后在弹出的面板里面设置好我们需要分析的网络请求的协议、主机名、端口、路径、参数,当然你也可以只设置一些主要的信息,比如协议和主机名的组合。 方法3:一般打开 Charles 并设置好配置信息后(比如电脑本机或者设置过代理的手机)所有的网络请求都将在 Charles 的面板上显示,同时我们感兴趣的网络请求如果也在面板上显示的话,“Structure”模式下可以选中需要分析的网络请求,鼠标右击选择**“Focus”。“Sequence”模式下可以在面板的网络请求显示面板的右下角看到一个Focus**按钮,点击勾选后 Charles 只会显示你感兴趣的网络请求。 截取HTTP/HTTPS数据 截取 HTTP 请求 Charles 的主要目的是抓取捕获网络请求,这里以 iPhone 的抓包为例讲解。 Charles 的设置 要截获 iPhone 的网络请求就需要为 Charles 开启代理功能。在菜单栏选择**“Proxy” ->"Proxy Settings"。填写代理的端口号并将“Enable transparent HTTP proxying”**勾选上。 iPhone 上的设置 在电脑“系统偏好设置”中心打开网络查看本机 IP 地址,打开手机“设置”->“无线局域网”,进入当前使用的网络,点击进入当前 WIFI 的详情页(可以看到当前 WIFI 的基本信息,包括子网掩码、端口、IP地址、路由器),在最下角可以看到**“DNS”和“HTTP代理”2个section。我们点击“配置代理”**,设置 HTTP 代理选中“手动”。服务器处填写电脑ip地址,端口写8888。设置好后,我们打开 iPhone 上的任意需要网络请求的应用,就可以看到 Charles 弹出请求的确认菜单,单击"Allow"按钮,即可完成设置。 截取 HTTPS 请求 如果你需要捕获 HTTPS 协议的网络请求,那么则需要安装 Charles 的 CA 证书。步骤如下; 首先需要在 MAC 上安装证书。点击 Charles 顶部的菜单栏,选择 “Help” -> "SSL Proxying" -> "Install Charles Root Certificate"。 在 keychain 处将新安装的证书设置为永久信任 即使安装了 CA 证书,Charles 默认是不捕获 HTTPS 协议的网络请求,所以我们需要对某个主机下的网络请求抓包分析的话,选中该网络请求右击选中 “SSL Proxying Enabled”。这样就可以看到我们感兴趣的HTTPS 网络请求了。 如果你需要捕获移动设备的 HTTPS 网络请求,则需要在移动设备上安装证书并作简单的设置 选择 Charles 顶部菜单栏选择 “Help” ->"Install Charles Root Certificate on a Mobile Device or Remote Browser"。然后就可以看到 Charles 弹出的安装说明了。 在手机设置好 Charles 代理的情况下,在手机浏览器输入 “chls.pro/ssl”。安装提示下载好CA证书。 验证刚刚安装的 CA证书 iPhone 打开设置 -> 通用 -> 关于本机 -> 证书信任设置 -> 开启开关 在 Charles 菜单栏 Proxy -> SSL Proxying Setting -> 点击 Add 按钮 -> 在弹出的对对话框设置需要监听的 HTTPS 域(*:代表通配符) 设置完毕,尽情抓取你想要的 HTTPS 网络请求吧。 模拟弱网环境 在平时开发的时候我们经常需要模拟弱网环境,并作弱网环境下的适配工作。Charles 为我们提供了这个服务。 在 Charles 菜单栏选择 “Proxy” -> "Throttle Settings"。在弹出的面板上设置网络请求的参数(上行,下行带宽、利用率、可靠性等等信息)。如下图所示。 如果你想对指定主机进行弱网环境下的测试,可以点击上图的“Add”按钮,在弹出的面板上设置协议、主机、端口来对指定的主机进行弱网设置。 修改网络请求 对于捕获的网络请求,我们经常需要修改网络请求的cookie、Headers、Url等信息。Charles 提供了对网络请求的编辑和重发功能。只需要选中需要修改编辑的网络请求,在对应的右上角看到有一个“钢笔”的按钮,点击后就可以对选中的网络请求进行编辑了,编辑好后可以在右下角看到 Execute 按钮。这样我们编辑后的网络请求就可以被执行了。 修改服务器返回内容 很多时候为了方便调试代码,我们会有这种需求,修改接口返回的数据节点或者内容、甚至是状态码。比如数据为空、数据异常、请求失败、多页数据的情况。 Charles 为我们提供了超实用的功能,“Map(Map Local、Map Remote)功能”、Rewrite功能、Breakpoints功能 ,都可以实现修改服务端返回数据的功能。但是有区别和适用场景: Map 功能适合长期地将某一请求重定向到另一个指定的网络地址或者本地 JSON 文件 Rewrite 功能适合对网络请求进行一些正则替换 Breakpoints 功能适合对网络请求进行一些临时性的修改(类似于我们开发的断点作用) Map 功能 Map 功能分为 Map Local(将某个网络请求重定向到本地 JSON 文件) 和 Map Remote 功能(将网络请求重定向到另一个网络接口)。 在 Charles 菜单栏选择 “Tools” -> "Map Remote" 或 “Map Local” 即可进入相应的功能模块。 Map Remote 功能 适合于切换线上到本地、测试服务到正式服务的场景。比如下图从正式服务切换到测试服务 Map Local 功能 我们需要填写重定向的原地址信息和本地目标文件。我们可以先将某个接口的响应内容保存下来(选择对应的网络请求,右击点击 Save Response )成为 data.json 文件。然后我们编辑里面的 status 、message、data 等信息为我们想要的目标映射文件。 如下所示,我将一个网络请求的内容映射到我本地的一个 JSON 文件。之后这个请求的内容都从网络变为返回我本地的数据了。 Map Local 可能会存在一个小缺陷,其返回的 HTTP Response Header 与正常的网络请求不一样,如果程序设置了校验 Header 信息,此时 Map Local 就会失败,解决办法是同时使用 Rewrite功能将相关的HTTP 头部信息 rewrite 成我们需要的信息 Rewrite 功能 Rewrite 适合对某个网络请求进行正则替换,以达到修改结果的目的。 假如我的 App 的界面上的显示的功能模块及其点击事件是根据接口来完成的,我想实现替换功能模块的名称的目的。步骤:点击顶部菜单栏的**“Tools” -> "Rewrite"**。在弹出的面板上勾选 “Enable Rewrite”。点击左下角的 Add按钮,在右上角的 **Name:**处写好本次配置的名称(如果有多个 Rewrite,为了后期容易区分)。 可以针对特定的网络请求进行 Rewrite。可以点击右上角 Location 面板下面的 Add按钮。在弹出的面板上设置网络请求配置信息。注意此时需要同时设置 Protocol、Port、Host、Path信息(我测试加了 Protocol、Host、Port这3个是无效的) 然后对指定的 Type 和 Action 进行 Rewrite。 Type 主要有 Add Header、Modify Header、Remove Header、Host、Path等等。 Where 可以选择 Request 和 Response。指的是下面的修改是针对 Request 还是 Response 完成设置后点击 Apply 按钮,即可生效。下次继续请求该网络,返回的内容就是我们刚刚设置的内容。比如当前的“政策法规”要变成“哈哈哈,我是假的政策法规”。这时候就可以使用 Rewrite 功能 Breakpoints 功能 Breakpoints 相比于其他几个修改网络请求的特点是只是针对当前的网络请求,Breakpoints 只存在于设置过的当前的网络请求,Charles 关闭后下次打开 Breakpoints 消失了。想要修改网络请求 Breakpoints 步骤最简单,跟我们调试工具里面设置的断点一样方便。 对于我们设置了 Breakpoints 的网络请求, Charles 会在下次继续访问该请求的时候停止掉,就跟 debug 一样。此时我们可以 Edit Request,修改过 Request 之后点击右下角的 Execute 按钮。然后等到服务端返回的时候继续是断点状态,此时可以 Edit Response。步骤: 选中某个网络请求 -> 右击 -> 点击“Breakpoints”。 如下图:对该接口设置了 Breakpoints。请求网络后 Edit Response,点击 execute 后服务端返回的结果就是我们编辑的内容了。 服务器压力测试 我们可以使用 Charles 的 Repeat 功能地对服务器进行并发访问进行压力测试。步骤:**选中某个网络请求 -> 右击 -> Repeat Advanced -> 在弹出的面板里面设置总共的迭代次数(Iterations)、并发数(Concurrency) -> 点击“OK” 。**开始执行可以看到以设置的并发数的规模,进行总共达设置的总共迭代次数的访问。(专业的压力测试工具:Load Runner) 反向代理 Charles 的反向代理功能允许我们将本地指定端口的请求映射到远程的另一个端口上。设置:点击顶部菜单栏 Proxy -> 点击 Reverse Proxies。 如下所示,我将本地的 8080 端口映射到远程的 80 端口上,点击 OK 生效后,当我继续访问本地的 80 端口,实际返回的就是远程 80 端口的提供的内容了。 解决与翻墙软件的冲突 Charles 的工作原理是把自己设置为系统的代理服务器,但是我们开发者经常会利用 VPN 翻墙访问谷歌查找资料(这些翻墙软件的工作原理也是把自己设置成为系统的代理服务器),为了2者和平共处。我们可以在 Charles 的 External Proxy Settings 中将翻墙的代理端口等信息填写。同时我们需要关闭翻墙软件的自动设置,更改为**“手动模式”**。(使其不主动修改系统代理) 总结 Charles 功能强大、界面简洁,读完这篇文章并做出练习,相信你能很快掌握它,“工欲善其事,必先利其器” ,掌握了它,相信可以为你大大提高开发中调试网络的效率。Enjoy yourself 参考链接 唐巧的博客

优秀的个人博客,低调大师

每日一博 | 通俗视频编码技术入门

1、引言 如今我们所处的时代,是移动互联网时代,也可以说是视频时代。从快播到抖音,从“三生三世”到“延禧攻略”,我们的生活,被越来越多的视频元素所影响。 而这一切,离不开视频拍摄技术的不断升级,还有视频制作产业的日益强大。 此外,也离不开通信技术的飞速进步。试想一下,如果还是当年的56K Modem拨号,或者是2G手机,你还能享受到现在动辄1080P甚至4K的视频体验吗? 除了视频拍摄工具和网络通信技术升级之外,我们能享受到视频带来的便利和乐趣,还有一个重要因素,就是视频编码技术的突飞猛进。 视频编码技术涉及的内容太过专业和庞杂,市面上的书籍或博客多数都只是枯燥的技术概念罗列,对于新手来说读完依旧蒙逼是常态,本文将借此机会,专门给大家做一个关于视频编码的零基础科普。 2、图像基础知识 2.1 什么是像素? 说视频之前,先要说说图像。图像,大家都知道,是由很多“带有颜色的点”组成的。这个点,就是“像素点”。 像素点的英文叫Pixel(缩写为PX)。这个单词是由 Picture(图像) 和 Element(元素)这两个单词的字母所组成的。 ▲ 电影《像素大战(Pixels)》,2015年 像素是图像显示的基本单位。我们通常说一幅图片的大小,例如是1920×1080,就是长度为1920个像素点,宽度为1080个像素点。乘积是2,073,600,也就是说,这个图片是两百万像素的。 1920×1080,这个也被称为这幅图片的分辨率。 ▲ 分辨率也是显示器的重要指标 2.2 什么是PPI? 那么,我们经常所说的PPI又是什么东西呢? PPI,就是“Pixels Per Inch”,每英寸像素数。也就是,手机(或显示器)屏幕上每英寸面积,到底能放下多少个“像素点”。这个值当然是越高越好啦!PPI越高,图像就越清晰细腻。 以前的功能机,例如诺基亚,屏幕PPI都很低,有很强烈的颗粒感。 后来,苹果开创了史无前例的“视网膜”(Retina)屏幕,PPI值高达326(每英寸屏幕有326像素),画质清晰,再也没有了颗粒感。 2.3 颜色在计算机里是如何表示的? 像素点必须要有颜色,才能组成缤纷绚丽的图片。那么,这个颜色,又该如何表示呢? 大家都知道,我们生活中的颜色,可以拥有无数种类别。 ▲ 光是妹纸们的口红色号,就足以让我们这些屌丝瞠目结舌。。。 在计算机系统里,我们不可能用文字来表述颜色。不然,就算我们不疯,计算机也会疯掉的。在数字时代,当然是用数字来表述颜色。这就牵出了“彩色分量数字化”的概念。 以前我们美术课学过,任何颜色,都可以通过红色(Red)、绿色(Green)、蓝色(Blue)按照一定比例调制出来。这三种颜色,被称为“三原色”。 在计算机里,R、G、B也被称为“基色分量”。它们的取值,分别从0到255,一共256个等级(256是2的8次方)。所以,任何颜色,都可以用R、G、B三个值的组合表示。 ▲ RGB=(183,67,21) 通过这种方式,一共能表达多少种颜色呢?256×256×256=16,777,216种,因此也简称为1600万色。RGB三色,每色有8bit,这种方式表达出来的颜色,也被称为24位色(占用24bit)。这个颜色范围已经超过了人眼可见的全部色彩,所以又叫真彩色。再高的话,对于我们人眼来说,已经没有意义了,完全识别不出来。 3、视频编码基础知识 3.1 视频和图像和关系 好了,刚才说了图像,现在,我们开始说视频。所谓视频,大家从小就看动画,都知道视频是怎么来的吧?没错,大量的图片连续起来,就是视频。 衡量视频,又是用的什么指标参数呢?最主要的一个,就是帧率(Frame Rate)。在视频中,一个帧(Frame)就是指一幅静止的画面。帧率,就是指视频每秒钟包括的画面数量(FPS,Frame per second)。 帧率越高,视频就越逼真、越流畅。 3.2 未经编码的视频数据量会有多大? 有了视频之后,就涉及到两个问题: 一个是存储; 二个是传输。 而之所以会有视频编码,关键就在于此:一个视频,如果未经编码,它的体积是非常庞大的。 以一个分辨率1920×1280,帧率30的视频为例: 共:1920×1280=2,073,600(Pixels 像素),每个像素点是24bit(前面算过的哦); 也就是:每幅图片2073600×24=49766400 bit,8 bit(位)=1 byte(字节); 所以:49766400bit=6220800byte≈6.22MB。 这是一幅1920×1280图片的原始大小,再乘以帧率30。 也就是说:每秒视频的大小是186.6MB,每分钟大约是11GB,一部90分钟的电影,约是1000GB。。。 吓尿了吧?就算你现在电脑硬盘是4TB的(实际也就3600GB),也放不下几部大姐姐啊!不仅要存储,还要传输,不然视频从哪来呢?如果按照100M的网速(12.5MB/s),下刚才那部电影,需要22个小时。。。再次崩溃。。。 正因为如此,屌丝工程师们就提出了,必须对视频进行编码。 3.3 什么是编码? 编码:就是按指定的方法,将信息从一种形式(格式),转换成另一种形式(格式)。视频编码:就是将一种视频格式,转换成另一种视频格式。 编码的终极目的,说白了,就是为了压缩。各种五花八门的视频编码方式,都是为了让视频变得体积更小,有利于存储和传输。 我们先来看看,视频从录制到播放的整个过程,如下: 首先是视频采集。通常我们会使用摄像机、摄像头进行视频采集。限于篇幅,我就不打算和大家解释CCD成像原理了。 采集了视频数据之后,就要进行模数转换,将模拟信号变成数字信号。其实现在很多都是摄像机(摄像头)直接输出数字信号。信号输出之后,还要进行预处理,将RGB信号变成YUV信号。 前面我们介绍了RGB信号,那什么是YUV信号呢? 简单来说,YUV就是另外一种颜色数字化表示方式。视频通信系统之所以要采用YUV,而不是RGB,主要是因为RGB信号不利于压缩。在YUV这种方式里面,加入了亮度这一概念。在最近十年中,视频工程师发现,眼睛对于亮和暗的分辨要比对颜色的分辨更精细一些,也就是说,人眼对色度的敏感程度要低于对亮度的敏感程度。 所以,工程师认为,在我们的视频存储中,没有必要存储全部颜色信号。我们可以把更多带宽留给黑—白信号(被称作“亮度”),将稍少的带宽留给彩色信号(被称作“色度”)。于是,就有了YUV。 YUV里面的“Y”,就是亮度(Luma),“U”和“V”则是色度(Chroma)。 大家偶尔会见到的Y'CbCr,也称为YUV,是YUV的压缩版本,不同之处在于Y'CbCr用于数字图像领域,YUV用于模拟信号领域,MPEG、DVD、摄像机中常说的YUV其实就是Y'CbCr。 ▲ YUV(Y'CbCr)是如何形成图像的 YUV码流的存储格式其实与其采样的方式密切相关。(采样,就是捕捉数据) 主流的采样方式有三种: 1)YUV4:4:4; 2)YUV4:2:2; 3)YUV4:2:0。 具体解释起来有点繁琐,大家只需记住,通常用的是YUV4:2:0的采样方式,能获得1/2的压缩率。 这些预处理做完之后,就是正式的编码了。 有关视频编码的更多专业知识,可以详细阅读以下文章: 《即时通讯音视频开发(一):视频编解码之理论概述》 《即时通讯音视频开发(二):视频编解码之数字视频介绍》 《即时通讯音视频开发(三):视频编解码之编码基础》 《即时通讯音视频开发(四):视频编解码之预测技术介绍》 《即时通讯音视频开发(五):认识主流视频编码技术H.264》 4、视频编码的实现原理 4.1 视频编码技术的基本原理 前面我们说了,编码就是为了压缩。要实现压缩,就要设计各种算法,将视频数据中的冗余信息去除。当你面对一张图片,或者一段视频的时候,你想一想,如果是你,你会如何进行压缩呢? ▲ 对于新垣女神,我一bit也不舍得压缩… 我觉得,首先你想到的,应该是找规律。是的,寻找像素之间的相关性,还有不同时间的图像帧之间,它们的相关性。 举个例子:如果一幅图(1920×1080分辨率),全是红色的,我有没有必要说2073600次[255,0,0]?我只要说一次[255,0,0],然后再说2073599次“同上”。 如果一段1分钟的视频,有十几秒画面是不动的,或者,有80%的图像面积,整个过程都是不变(不动)的。那么,是不是这块存储开销,就可以节约掉了? ▲ 以上图为例,只有部分元素在动,大部分是不动的 是的,所谓编码算法,就是寻找规律,构建模型。谁能找到更精准的规律,建立更高效的模型,谁就是厉害的算法。 通常来说,视频里面的冗余信息包括: 视频编码技术优先消除的目标,就是空间冗余和时间冗余。 接下来,就和大家介绍一下,究竟是采用什么样的办法,才能干掉它们。以下内容稍微有点高能,不过我相信大家耐心一些还是可以看懂的。 4.2 视频编码技术的实现方法 视频是由不同的帧画面连续播放形成的。 这些帧,主要分为三类,分别是: 1)I帧; 2)B帧; 3)P帧。 I帧:是自带全部信息的独立帧,是最完整的画面(占用的空间最大),无需参考其它图像便可独立进行解码。视频序列中的第一个帧,始终都是I帧。 P帧:“帧间预测编码帧”,需要参考前面的I帧和/或P帧的不同部分,才能进行编码。P帧对前面的P和I参考帧有依赖性。但是,P帧压缩率比较高,占用的空间较小。 ▲ P帧 B帧:“双向预测编码帧”,以前帧后帧作为参考帧。不仅参考前面,还参考后面的帧,所以,它的压缩率最高,可以达到200:1。不过,因为依赖后面的帧,所以不适合实时传输(例如视频会议)。 ▲ B帧 通过对帧的分类处理,可以大幅压缩视频的大小。毕竟,要处理的对象,大幅减少了(从整个图像,变成图像中的一个区域)。 如果从视频码流中抓一个包,也可以看到I帧的信息,如下: 我们来通过一个例子看一下。 这有两个帧: 好像是一样的? 不对,我做个GIF动图,就能看出来,是不一样的: 人在动,背景是没有在动的。 第一帧是I帧,第二帧是P帧。两个帧之间的差值,就是如下: 也就是说,图中的部分像素,进行了移动。移动轨迹如下: 这个,就是运动估计和补偿。 当然了,如果总是按照像素来算,数据量会比较大,所以,一般都是把图像切割为不同的“块(Block)”或“宏块(MacroBlock)”,对它们进行计算。一个宏块一般为16像素×16像素。 ▲ 将图片切割为宏块 好了,我来梳理一下。 对I帧的处理,是采用帧内编码方式,只利用本帧图像内的空间相关性。对P帧的处理,采用帧间编码(前向运动估计),同时利用空间和时间上的相关性。简单来说,采用运动补偿(motion compensation)算法来去掉冗余信息。 需要特别注意,I帧(帧内编码),虽然只有空间相关性,但整个编码过程也不简单。 如上图所示,整个帧内编码,还要经过DCT(离散余弦变换)、量化、编码等多个过程。限于篇幅,加之较为复杂,今天就放弃解释了。 那么,视频经过编码解码之后,如何衡量和评价编解码的效果呢? 一般来说,分为客观评价和主观评价。客观评价,就是拿数字来说话。例如计算“信噪比/峰值信噪比”。 信噪比的计算,我就不介绍了,丢个公式,有空可以自己慢慢研究... 除了客观评价,就是主观评价了。主观评价,就是用人的主观感知直接测量,额,说人话就是——“好不好看我说了算”。 5、视频编码的国际标准 5.1 视频编码格式的标准化 接下来,我们再说说标准(Standard)。任何技术,都有标准。自从有视频编码以来,就诞生过很多的视频编码标准。 提到视频编码标准,先介绍几个制定标准的组织。 首先,就是大名鼎鼎的ITU(国际电信联盟)。 ITU是联合国下属的一个专门机构,其总部在瑞士的日内瓦。 ITU下属有三个部门: 1)分别是ITU-R(前身是国际无线电咨询委员会CCIR); 2)ITU-T(前身是国际电报电话咨询委员会CCITT); 3)ITU-D。 除了ITU之外,另外两个和视频编码关系密切的组织,是ISO/IEC。 ISO大家都知道,就是推出ISO9001质量认证的那个“国际标准化组织”。IEC,是“国际电工委员会”。1988年,ISO和IEC联合成立了一个专家组,负责开发电视图像数据和声音数据的编码、解码和它们的同步等标准。这个专家组,就是大名鼎鼎的MPEG,Moving Picture Expert Group(动态图像专家组)。 三十多年以来,世界上主流的视频编码标准,基本上都是它们提出来的: 1)ITU提出了H.261、H.262、H.263、H.263+、H.263++,这些统称为H.26X系列,主要应用于实时视频通信领域,如会议电视、可视电话等; 2)ISO/IEC提出了MPEG1、MPEG2、MPEG4、MPEG7、MPEG21,统称为MPEG系列。 ITU和ISO/IEC一开始是各自捣鼓,后来,两边成立了一个联合小组,名叫JVT(Joint Video Team,视频联合工作组)。 JVT致力于新一代视频编码标准的制定,后来推出了包括H.264在内的一系列标准。 ▲ 压缩率对比 ▲ 视频编码标准的发展关系 大家特别注意一下上图里面的HEVC,也就是现在风头正盛的H.265。 作为一种新编码标准,相比H.264有极大的性能提升,目前已经成为最新视频编码系统的标配。 最后,我再说说封装。 5.2 视频数据的封装 对于任何一部视频来说,只有图像,没有声音,肯定是不行的。所以,视频编码后,加上音频编码,要一起进行封装。 封装:就是封装格式,简单来说,就是将已经编码压缩好的视频轨和音频轨按照一定的格式放到一个文件中。再通俗点,视频轨相当于饭,而音频轨相当于菜,封装格式就是一个饭盒,用来盛放饭菜的容器。 目前主要的视频容器有如下:MPG、VOB、MP4、3GP、ASF、RMVB、WMV、MOV、Divx、MKV、FLV、TS/PS等。 封装之后的视频,就可以传输了,你也可以通过视频播放器进行解码观看。(本文同步发布于:http://www.52im.net/thread-2840-1-1.html)

优秀的个人博客,低调大师

Python3入门(十二)错误和异常

学习 Python 编程时,经常会看到一些报错信息,在前面我们没有提及,这章节我们会专门介绍。Python 有两种错误很容易辨认:语法错误和异常 一、语法错误 语法错误也可以称之为解析错误,如下 if True print("ok") 会出现错误,因为if条件后没有加: 二、异常 即便Python程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常,大多的异常都不会被程序所处理,都是抛出异常信息 a = int("你好") 会出现如下异常: Traceback (most recent call last): File "/Users/colin/PycharmProjects/demo/ex/TestError.py", line 4, in <module> a = int("你好"

优秀的个人博客,低调大师

Python3入门(九)输入和输出

前面几章介绍了一些常用的输入输出,本文将具体介绍Python的输入和输出 一、输出格式美化 Python两种输出值的方式: 表达式语句和print()函数。第三种方式是使用文件对象的write()方法,标准输出文件可以用sys.stdout引用。如果你希望输出的形式更加多样,可以使用str.format()函数来格式化输出值。如果你希望将输出的值转成字符串,可以使用repr()或str()函数来实现: str():返回一个用户易读的表达形式 repr():返回一个解释器易读的表达形式,可以转义字符串中的特殊字符,参数可以是python中的任何对象 例子: for x in range(1, 5): print(repr(x).rjust(1), repr(x * x).rjust(2), repr(x * x * x).rjust(3

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册