Flutter异常分类 可以分为三大类
Dart异常Framework异常Engine异常 1. Dart异常捕获 局部捕获
//使用try-catch捕获同步异常 try { throw StateError('This is a Dart exception'); }catch(e) { print(e); } //使用catchError捕获异步异常 Future.delayed(Duration(seconds: 1)) .then((e) => throw StateError('This is a Dart exception in Future.')) .catchError((e)=>print(e)); 全局捕获:在dart代码中,zone表示一段代码执行的范围,概念类似iOS的沙盒,不同沙盒之间是相互隔离的。如果想要处理zone中代码执行的异常,可以通过其提供的onError回调来处理,如下:
//同步抛出异常 runZoned(() { throw StateError('This is a Dart exception.'); }, onError: (dynamic e, StackTrace stack) { print('Sync error caught by zone'); }); //异步抛出异常 runZoned(() { Future.delayed(Duration(seconds: 1)) .then((e) => throw StateError('This is a Dart exception in Future.
学习笔记:乘法溢出问题 1、3n+1问题
对于任意大于1的自然数,若n为奇数就将n变为3n+1,否则变为n的一半。当n变为1时,进行了多少次变换?
程序一:
#include<iostream> #include<cstdio> using namespace std; int main() { int n; int count=0; cin>>n; while(n>1) { if(n%2==0) n=n/2; else n=3*n+1; count++; } cout<<count<<endl; return 0; } 此程序看似没问题,但当输入比int上界小一点点的n时,会乘法溢出。 可以用以下程序解决 程序二:
#include<iostream> #include<cstdio> using namespace std; int main() { long long n; int count=0; cin>>n; while(n>1) { if(n%2==0) n=n/2; else n=3*n+1; count++; } cout<<count<<endl; return 0; } 二、阶乘之和问题
计算S=1!+2!+……+n!的末六位。
程序一:
#include<iostream> #include<cstdio> using namespace std; int main() { int n; int sum=0; cin>>n; for(int i=1;i<=n;i++) { int factorial=1; for(int j=i;j>=1;j--) factorial=factorial*j; sum+=factorial; } printf("
两种方式:
第一种,根据Excel某列的值,进行下拉框选择、 1.新建一个sheet页生成下拉框的数据, (生成方法可以 notepad++或者 自动填充,手动万能大法也行)
eg:
2.选中原sheet页中 需要添加下拉框的某列或单元格,
2.上方 “数据” --> “数据验证”--> “数据验证”
3.内容选择 刚新增的sheet页的列
4.确认 OK 第二种,手动输入 (适合下拉框值不多情况) 打开Excel,并打开需要处理的工作簿。
2
选中需要设置下拉选项的单元格或列,并点击功能列表中的【数据】页面。
3
继续点击数据工具组中的【数据验证】选项,从其下拉列表中选择【数据验证】选项。
4
在弹出来的【数据验证】对话框的验证条件中,将【任何值】切换为【序列】。
5
之后在弹出来的来源中写上需要定义的下拉值,例如是或否,中间切记要用英文的逗号字符进行分隔。
6
设置好之后,再回到工作表,下拉填充,那些选定的区域的单元格下拉选项就设置好了。
Z3是微软研究院开发的高性能定理证明程序。Z3有许多应用场合,如:软件/硬件验证和测试,约束求解,混合系统的分析,安全,生物(硅分析),几何问题。 Z3发行版还包含C、C++、.Net、Java和OCaml 的api。Z3Py的源代码可以在GitHub上的Z3发行版中获得.
导入z3 !pip install "z3-solver" from z3 import * 从一个简单例子开始 x = Int('x') y = Int('y') solve(x > 2, y < 10, x + 2*y == 7) ''' [y = 0, x = 7] ''' 在Z3中函数Int('x')创建了一个整数变量x,solve函数求解一个约束系统。上面的例子使用了两个变量x和y以及3个约束.
公式/表达式的化简 x = Int('x') y = Int('y') print(simplify(x + y + 2*x + 3)) print(simplify(x < y + x + 2)) print(simplify(And(x + 1 >= 3, x**2 + x**2 + y**2 + 2 >= 5))) ''' 3 + 3*x + y Not(y <= -2) And(x >= 2, 2*x**2 + y**2 >= 3) ''' 设置显示方法 默认情况下,Z3Py(用于web)使用数学符号显示公式和表达式。通常,∧是逻辑的和,∨是逻辑的或,等等。命令set_option(html_mode=False)使所有公式和表达式以Z3Py表示法显示。这也是Z3发行版附带的Z3Py脱机版本的默认模式
在之前的文章「简单了解InnoDB底层原理」聊了一下MySQL的Buffer Pool。这里再简单提一嘴,Buffer Pool是MySQL内存结构中十分核心的一个组成,你可以先把它想象成一个黑盒子。
黑盒下的更新数据流程 当我们查询数据的时候,会先去Buffer Pool中查询。如果Buffer Pool中不存在,存储引擎会先将数据从磁盘加载到Buffer Pool中,然后将数据返回给客户端;同理,当我们更新某个数据的时候,如果这个数据不存在于Buffer Pool,同样会先数据加载进来,然后修改修改内存的数据。被修改过的数据会在之后统一刷入磁盘。
MySQL 崩溃恢复
这个过程看似没啥问题,实则不讲武德。假设我们修改Buffer Pool中的数据成功,但是还没来得及将数据刷入磁盘MySQL就挂了怎么办?按照上图的逻辑,此时更新之后的数据只存在于Buffer Pool中,如果此时MySQL宕机了,这部分数据将会永久的丢失;
再者,我更新到一半突然发生错误了,想要回滚到更新之前的版本,该怎么办?那不完犊子吗,连数据持久化的保证、事务回滚都做不到还谈什么崩溃恢复?
Redo Log & Undo Log 而通过MySQL能够实现崩溃恢复的事实来看,MySQL必定实现了某些骚操作。没错,这就是接下来我们要介绍的另外的两个关键功能,Redo Log和Undo Log。
这两种日志是属于InnoDB存储引擎的日志,和MySQL Server的Binlog不是一个维度的日志。
Redo Log 记录了此次事务**「完成后」** 的数据状态,记录的是更新之 **「后」**的值
Undo Log 记录了此次事务**「开始前」** 的数据状态,记录的是更新之 **「前」**的值
所以这两种日志有明显的区别,我用一种更加通俗的例子来解释一下这两种日志。
Redo Log就像你在命令行敲了很长的命令,敲回车执行,结果报错了。此时我们只需要再敲个↑就会拿到上一条命令,再执行一遍即可。
Undo Log就像你刚刚在Git中Commit了一下,然后再做一个较为复杂的改动,但是改着改着你的心态崩了,不想要刚刚的改动了,于是直接git reset --hard $lastCommitId回到了上一个版本。
实现日志后的更新流程 有了Redo Log和Undo Log,我们再将上面的那张图给完善一下。
MySQL 崩溃恢复
首先,更新数据还是会判断数据是否存在于Buffer Pool中,不存在则加载。上面我们提到了回滚的问题,在更新Buffer Pool中的数据之前,我们需要先将该数据事务开始之前的状态写入Undo Log中。假设更新到一半出错了,我们就可以通过Undo Log来回滚到事务开始前。
然后执行器会更新Buffer Pool中的数据,成功更新后会将数据最新状态写入Redo Log Buffer中。因为一个事务中可能涉及到多次读写操作,写入Buffer中分组写入,比起一条条的写入磁盘文件,效率会高很多。
redo-log-buffer
那为什么Undo Log不也搞一个Undo Log Buffer,也给Undo Log提提速,雨露均沾?那我们假设有这个一个Buffer存在于InnoDB,将事务开始前的数据状态写入了Undo Log Buffer中,然后开始更新数据。
突然啪一下,很快啊,MySQL由于意外进程退出了,此时会发生一件很尴尬的事情,如果更新的数据一部分已经刷回磁盘了,但是此时事务没有成功需要回滚,你发现Undo Log随着进程退出一起没了,此时就没有办法通过Undo Log去做回滚。
使用conda创建虚拟环境
conda create -name tf
激活虚拟环境
conda activate tf
pip安装tf,使用豆瓣镜像。
pip install tensorflow-cpu==2.4 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install tensorflow==2.4 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
改变interpreter
验证tf是否可以正常使用
import tensorflow as tf print(tf.__version__) #输出'2.4.0'
文章目录 前言一、基本操作1.引入库2.array创建数组3.获取array相关信息(维数,形状,元素数) 二、array的创建1.引入库2.dtype设置数组的数据类型3.zeros创建全零数组4.ones创建全1数组5.empty创建全空数组6.arange创建连续数组7.reshape改变数组形状8.linespace创建连续数组 前言 这同样是我根据b站大佬莫烦的numpy库学习视频而整理的笔记,有时间可以前去观看
https://www.bilibili.com/video/BV1Ex411L7oT
本文主要介绍numpy的一些基本操作和array的创建
一、基本操作 1.引入库 import numpy as np 2.array创建数组 array = np.array([[1, 2, 3], [2, 3, 4]]) # 二维数组 print(array) # 输出显示 结果显示:
3.获取array相关信息(维数,形状,元素数) print("number of dim:", array.ndim) # 维数 print("shape:", array.shape) # 行数,列数 print("size:", array.size) # 总共的元素个数 结果显示:
二、array的创建 1.引入库 import numpy as np 2.dtype设置数组的数据类型 a = np.array([[2, 22, 4], [1, 34, 5]], dtype = np.int) # int8/16/32/64 float16/32/64等类型 # 我的电脑int默认为int32 print(a) print(a.dtype) 结果显示:我的电脑默认的int为int32
什么是Umi.js? Umi,中文可发音为乌米,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
为什么使用Umi.js? 我们做react开发的时候会不会遇到以下问题?:
1.项目做大的时候,开发调试的启动和热更新时间会变得很长。
2.大应用下,网站打开很慢,有没有办法基于路由做到按需加载。
3.dva的model每次都要手写载入,能否一开始就同项目初始化好?
使用乌米,即可解决以上问题,并且还能提供如下优势:
🎉开箱即用,内置 react、react-router 等📦类 next.js 且功能完备的路由约定,同时支持配置的路由方式🐠完善的插件体系,覆盖从源码到构建产物的每个生命周期🚀 一键兼容到 IE9🍉完善的 TypeScript 支持🍗与 dva 数据流的深入融合 umi 有 2 和 3 两个版本。两个版本的使用都差不多。umi2 对 javascript 支持比较好,umi3 默认支持 typeScript
起步Umi node环境安装 建议安装最新的稳定版本,笔者这里为 14.15.3。同时建议使用 yarn
Umi快速上手 创建空目录 umi-learn
# 新建应用 $ mkdir umi-learn && cd umi-learn # 使用命令 $ yarn create umi # 安装依赖 $ yarn install 安装过程选择 app
项目工程结构 mock // mock文件 src |-- assets // 静态资源文件 |-- layouts // 全局布局文件 |-- pages // 项目页面文件 |-- globals // 全局样式 |--.
1、Vue是什么 Vue (读音 /vjuː/,类似于view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
2、引入Vue 直接用<script>引入
直接下载并用<script>标签引入,Vue会被注册为一个全局变量。
开发版本 : 包含完整的警告和调试模式
生产版本 :删除了警告,33.30KB min+gzip
在开发环境下不要使用压缩版本,不然你就失去了所有常见错误相关的警告!
#CDN 完整版引入:
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.min.js"></script> 非完整版引入:
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.runtime.min.js"></script> 命令行工具 (CLI) Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂的脚手架。它为现代前端工作流提供了 batteries-included 的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本。更多详情可查阅 Vue CLIcli.vuejs.org 3、两种Vue的区别 1、文件名:
完整版:vue.js
只包含运行时版:vue.runtime.js
完整版:同时包含编译器和运行时的版本。编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。 2、文件大小:
运行时版本(没有compiler)相比完整版(有compiler)体积要小大约 30%,所以应该尽可能使用这个版本。
3、完整版vs只包含运行时版
完整版:视图写在 HTML里或者 template选项里。由于有 compiler(编译器)的存在,完整版运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。只包含运行时版:视图写在render函数里面,用h函数来创建标签。由于没有 compiler(编译器),需要使用vue-loader ,把vue文件里面的HTML转成h函数。 完整版(template渲染HTML):
const vm=new Vue({ el:'#app', data:{ n:0 }, template:` <div>{{n}} <button @click='add'>+1</button> </div> `, methods:{ add(){ this.
老套路看图:
实现方法很简单只需要在启动Activity清单文件配置data属性就好了:
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <data android:host="without_icon" android:scheme="cn.xiayiye5.app" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> 上面配置后你的apk安装后在你手机桌面是找不到启动图标的,想打开这个APP怎么办呢?很简单通过隐式跳转即可
val intent = Intent() //隐式跳转方法一: // 两个参数意思 1:被打开APP的包名 2:被打开APP页面所在的activity路径 val cn = ComponentName("com.xiayiye5.withouticonapp","com.xiayiye5.withouticonapp.MainActivity") intent.component = cn startActivity(intent) 完整代码可以查看代码库:源码下载
再次感谢博主提供线索:博主1 博主2
选择排序(Select Sort):找到待排序数据里的最小值/最大值放入到对应位置。
假如待排序数据为12,8,1,9,3,我们假设开始时下标为0的元素是最大元素max。
第一趟:max是12,max跟8比,比8大,下标不改变,max跟1比,比1大,下标不改变,max跟9比,比9大,下标不改变,max跟3比,比3大,3是最后一个元素,则把max与3交换位置,即交换下标为0和下标为n-1的数据。
数据变成 3,8,1,9,12,且经过第一趟n-1的位置已经是最大值。
第二趟:max是3,下标为0,max跟8比,比8小,下标改变,下标变成1,即max现在是8,max跟1比,比1大,下标不改变,max跟9比,比9大,下标改变,下标变成3,max是9,下标3等于n-2,就相当于不发生改变。
数据变成 3,8,1,9,12,且现在最后两个位置已经放好
第三趟:max是3,下标为0,max跟8比,比8小,下标改变,下标变成1,即max现在是8,max跟1比,比1大,下标不改变,交换下标为1和下标为n-3的数据。
数据变成3,1,8,9,12,现在后三个位置都已经放好。
第四趟:max是3,下标为0,max跟1比,比1大,下标不改变,交换下标为0和下标为n-4的数据。
数据变成1,3,8,9,12,结束,即有n个数据的序列,需要n-1趟排序完成。
假定最大值代码如下:
void SelectSort(int arr[],int nlength) { if(arr == NULL ||nlength <= 0) return; int nMax; int i; int j; for(i = 0;i < nlength-1;i++) //要有n-1趟循环 { nMax = 0; //每次都假设下标为0的元素是最大值 for(j = 0;j<nlength-i;j++) //因为每1趟都会排好1个元素,则经过i趟以后就有i个排好的元素,每次后i个无需比较 { if(arr[j] > arr[nMax]) { nMax = j; } } //最大值放入相应位置 if(nMax != nlength-i-1) //如果下标与除去遍历完的元素最后一个不同,交换 { arr[nMax] = arr[nlength-i-1]^arr[nMax]; arr[nlength-i-1] = arr[nlength-i-1]^arr[nMax]; arr[nMax] = arr[nlength-i-1]^arr[nMax]; } } } 假定最小值代码如下:
想做用PYB做ROS机器人的主控,陀螺仪和加速度计怎么能少呢?
文章目录 MPU6050模块硬件连接代码MPU6050库文件 主程序参数解析三轴加速度计三轴陀螺仪数据处理与实现校准卡尔曼滤波 MPU6050模块 MPU6050是一种非常流行的空间运动传感器芯片,可以获取器件当前的三个加速度分量和三个旋转角速度。由于其体积小巧,功能强大,精度较高,不仅被广泛应用于工业,同时也是航模爱好者的神器,被安装在各类飞行器上驰骋蓝天。
MPU6050芯片内自带了一个数据处理子模块DMP,已经内置了滤波算法,在许多应用中使用DMP输出的数据已经能够很好的满足要求。在使用时只需要将偏移量减去即可使用,如果对精度有更高的要求可以使用上位机或这里使用卡尔曼滤波再次对数据进行优化。
大家在购买的时候,如果只需要陀螺仪和加速度计的话,就买和上图或者下图一样的六轴的GY-521六轴MPU6050模块即可,某宝上只需要4块钱左右即可买到还包邮,挺便宜的,一定不要买错型号,否则你在使用的时候一定会让你欲哭无泪。这里的库你可能不能直接用了。
硬件连接 接线和MPU数据的方向示意如图所示:
PYBMPU6050VCCVCCGNDGNDSCL(X9, IIC1)SCLSDL(X10, IIC1)SDL 代码 MPU6050库文件 mpu6050.py
import machine class accel(): def __init__(self, i2c, addr=0x68): self.iic = i2c self.addr = addr self.iic.start() self.iic.writeto(self.addr, bytearray([107, 0])) self.iic.stop() def get_raw_values(self): self.iic.start() a = self.iic.readfrom_mem(self.addr, 0x3B, 14) self.iic.stop() return a def get_ints(self): b = self.get_raw_values() c = [] for i in b: c.append(i) return c def bytes_toint(self, firstbyte, secondbyte): if not firstbyte & 0x80: return firstbyte << 8 | secondbyte return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1) def get_values(self): raw_ints = self.
先说结论:
除了字母不一样之外没有任何区别 当然你可能会看到很多类似一下的说法
但实际上,这些说法就像定义一个Map型的变量常用 map 起名,定义数组常用 array起名一样,只是一个贴切的名字,实际上用什么都可以。
以下这几种写法全都对,都能正常运行:
private static <T> T genericAdd(T a) { System.out.println(a ); return a; } private static <E> E genericAdd(E a) { System.out.println(a ); return a; } private static <ABCD > ABCD genericAdd(ABCD a) { System.out.println(a ); return a; } private static <AAAAAA> AAAAAA genericAdd(AAAAAA a) { System.out.println(a ); return a; }
文章目录 一、subplot多合一显示二、subplot分格显示方法一:subplot2grid方法二:gridspec方法三:定义简单结构 一、subplot多合一显示 代码如下:
import matplotlib.pyplot as plt plt.figure() plt.subplot(2, 1, 1) # 两行一列 位置一 plt.plot([0, 1], [0, 1]) plt.subplot(2, 3, 4) # 两行三列 位置四 plt.plot([0, 1], [0, 2]) plt.subplot(2, 3, 5) # 两行三列 位置五 plt.plot([0, 1], [0, 3]) plt.subplot(2, 3, 6) # 两行三列 位置六 plt.plot([0, 1], [0, 4]) plt.show() 显示结果:
二、subplot分格显示 方法一:subplot2grid 代码如下:
import matplotlib.pyplot as plt plt.figure() """ (3,3)表示将整个图像窗口分成3行3列, (0,0)表示从第0行第0列开始作图,colspan=3表示此图跨3列, rowspan=1表示行的跨度为1. colspan和rowspan默认跨度为1且为缺省值. """ ax1 = plt.subplot2grid((3, 3), (0, 0),colspan=3, rowspan=1) ax1.
pyqtgragh可以实现动态实时绘图,非常的强大!所以学习一下!
文章目录 环境准备绘图实战使用PyQtGraph绘制折线图绘制静态数据的单条曲线绘制静态数据的双曲线(分别绘制,不在同一个图表中)绘制静态数据的双曲线(在同一个图表中)绘制静态数据的双曲线(在同一个窗口,不同的图标中) 绘制动态实时图表数据绘制单条动态曲线 绘制动态数据的双曲线(在同一个窗口,不同的图标中)数据来源绘制动态双曲线 环境准备 pip install pyqtgraph pip install PyQt5 绘图实战 创建静态数据:
import pyqtgraph as pg import numpy as np a = np.random.random(100) b = np.random.random(50) 使用PyQtGraph绘制折线图 绘制静态数据的单条曲线 import pyqtgraph as pg import numpy as np a = np.random.random(100) def pg_plot(): app = pg.QtGui.QApplication([]) pg.plot(a,title='Irvingao') app.exec_() pg_plot() 绘制静态数据的双曲线(分别绘制,不在同一个图表中) import pyqtgraph as pg import numpy as np a = np.random.random(100) b = np.random.random(50) def pg_plot(): app = pg.QtGui.QApplication([]) pg.
源代码: Lib/tempfile.py 该模块用于创建临时文件和目录,它可以跨平台使用。TemporaryFile、NamedTemporaryFile、TemporaryDirectory 和 SpooledTemporaryFile 是带有自动清理功能的高级接口,可用作上下文管理器。mkstemp() 和 mkdtemp() 是低级函数,使用完毕需手动清理。
所有由用户调用的函数和构造函数都带有参数,这些参数可以设置临时文件和临时目录的路径和名称。该模块生成的文件名包括一串随机字符,在公共的临时目录中,这些字符可以让创建文件更加安全。为了保持向后兼容性,参数的顺序有些奇怪。所以为了代码清晰,建议使用关键字参数。
这个模块定义了以下内容供用户调用:
tempfile.TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None) 返回一个 file-like object 作为临时存储区域。创建该文件使用了与 mkstemp() 相同的安全规则。它将在关闭后立即销毁(包括垃圾回收机制关闭该对象时)。在 Unix 下,该文件在目录中的条目根本不创建,或者创建文件后立即就被删除了,其他平台不支持此功能。您的代码不应依赖使用此功能创建的临时文件名称,因为它在文件系统中的名称可能是可见的,也可能是不可见的。
生成的对象可以用作上下文管理器(参见 例子)。完成文件对象的上下文或销毁后,临时文件将从文件系统中删除。
mode 参数默认值为 'w+b' 因此创建的文件可以读取或写入而不用关闭。 因为是使用二进制模式,所以它在所有平台上的行为都保持一致而不用关心所存储的是什么数据。 buffering, encoding 和 newline 的解读方式与 open() 相同。
参数 dir、prefix 和 suffix 的含义和默认值都与它们在 mkstemp() 中的相同。
在 POSIX 平台上,它返回的对象是真实的文件对象。在其他平台上,它是一个文件类对象 (file-like object),它的 file 属性是底层的真实文件对象。
如果可用,则使用 os.O_TMPFILE 标志(仅限于 Linux,需要 3.11 及更高版本的内核)。
在 3.5 版更改: 如果可用,现在用的是 os.O_TMPFILE 标志。
tempfile.NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True) 此函数执行的操作与 TemporaryFile() 完全相同,但确保了该临时文件在文件系统中具有可见的名称(在 Unix 上表现为目录条目不取消链接)。从返回的文件类对象的 name 属性中可以检索到文件名。在临时文件仍打开时,是否允许用文件名第二次打开文件,在各个平台上是不同的(在 Unix 上可以,但在 Windows NT 或更高版本上不行)。如果 delete 为 true(默认值),则文件会在关闭后立即被删除。该函数返回的对象始终是文件类对象 (file-like object),它的 file 属性是底层的真实文件对象。文件类对象可以像普通文件一样在 with 语句中使用。
文章目录 CRT显示器与人眼视觉非线性显示与渲染伽马校正sRGB 纹理正确的点光衰减补充参考资料 CRT显示器与人眼视觉 过去, 大多数监视器是阴极射线管显示器(CRT). 这些监视器有一个物理特性就是两倍的输入电压产生的不是两倍的亮度. 输入电压产生约为输入电压的 2.2 次幂的亮度. 这本质上是一个问题, 但是由于一个神奇的巧合, CRT显示器的这一特性被保留了下来.
这个神奇的巧合就是: 人类的视觉系统进化出了一个特性, 黑暗环境下的辨识能力要强于明亮环境, 这可能有助于我们及时发现黑暗中隐藏的危险. 如下图所示, 第一行表示的人眼感受到的亮度, 第二行表示实际的物理亮度. 物理亮度基于光子数量, 是线性的, 而感知亮度基于人的感觉是非线性的.
通过观察可以看到物理亮度在我们眼中会显得暗部细节缺失而亮部细节过剩. 人眼对物理亮度的感知和 CRT 显示器显示亮度对电压的感知很接近, CRT亮度是电压的2.2次幂而人眼的观察亮度相当于物理亮度的2次幂, 因此CRT这个缺陷正好能满足人的需要, 后面的硬件也都保留了这一非线性特性.
2.2 这一数字就是所谓的伽马(Gamma), 也叫灰度系数, 各种显示设备会有各自的伽马值, 矫正使用的伽马值取决于显示器, 但是现代系统基本上都统一使用 2.2.
非线性显示与渲染 显示器的非线性特性让亮度在我们眼中看起来更好, 但是在渲染时反而会因此导致问题. 我们的渲染计算都是在伽马值为 1 的理想线性空间进行的. 比如现在我们输入了一个暗红色的光照(0.5, 0.0, 0.0), 然后希望将亮度提升一倍变为 (1.0, 0.0, 0.0). 但是由于显示器的非线性特性, 最终显示的颜色实际是从 (0.218, 0.0, 0.0) 变成了 (1.0, 0.0, 0.0).
我们一度忽略了这一问题, 通常是美术同学将光照设置的比本来更亮一些来抵消显示器对亮度的削减. 但是这本来就是一个数学上的错误, 使用更高级的光照算法时, 这个问题会越来越明显. 在 Physically Based Rendering 兴起之后, 我们更是不可能在渲染底层存在这样的问题, 于是便产生了伽马校正技术(Gamma Correction).
文章目录 前言一、散点图二、柱状图三、等高线图 前言 三种图的简单绘制介绍
一、散点图 代码如下:
import matplotlib.pyplot as plt import numpy as np n = 1024 # np.random.normal()函数 正态分布函数 X = np.random.normal(0, 1, n) # X值,均值是0,标准差是1 Y = np. random.normal(0, 1, n) # Y值 # np.arctan2()函数 按照元素(Y,X)所在象限返回X/Y的反正切值。 # 用作颜色 T = np.arctan2(Y, X) plt.scatter(X, Y, s = 75, c = T, alpha = 0.5) # x,y,大小,颜色,透明度 plt.xlim((-1.5, 1.5)) plt.ylim((-1.5, 1.5)) plt.xticks(()) # 隐藏x坐标轴 plt.yticks(()) # 隐藏y坐标轴 plt.show() 结果显示:
文章目录 前言一、标注二、能见度 前言 本次是对图像增加注释的两个函数annotate()和text()的运用和图像能见度的设置
一、标注 代码如下:
import matplotlib.pyplot as plt import numpy as np # 定义函数 x = np.linspace(-3, 3, 50) y = 2 * x + 1 制图和画坐标轴在上一节有比较详细的说明
https://blog.csdn.net/qq_40680007/article/details/112972554
# 定义图像以及制图 plt.figure(figsize=(8, 5)) plt.plot(x, y) # 画坐标轴 ax = plt.gca() ax.spines["right"].set_color("none") ax.spines["top"].set_color("none") ax.xaxis.set_ticks_position("bottom") ax.yaxis.set_ticks_position("left") ax.spines["bottom"].set_position(("data", 0)) ax.spines["left"].set_position(("data", 0)) # 画点 x0 = 1 y0 = 2 * x0 + 1 plt.scatter(x0, y0, s = 50, color = "b") # scatter()散点函数 分别传入点x坐标 y坐标 大小 颜色 plt.
SQLZOO练习 前言一、SELECT basics二、SELECT name三、SELECT from WORLD四、SELECT in SELECT五、SUM and COUNT六、The JOIN operation七、More JOIN operation八、Using Null九、Self join 前言 这是来自SQLZOO的练习
地址:https://igs.sqlzoo.net/
一、SELECT basics 1.顯示德國 Germany 的人口
select name, population from world where name='Germany'; 2.查詢面積為 5,000,000 以上平方公里的國家,對每個國家顯示她的名字和人均國內生產總值(gdp/population)
select name,gdp/population from world where area>5000000; 3.顯示“Ireland 愛爾蘭”,“Iceland 冰島”,“Denmark 丹麥”的國家名稱和人口
select name ,population from world where name in('Ireland','Iceland','Denmark'); 4.顯示面積為 200,000 及 250,000 之間的國家名稱和該國面積。
select name,area from world where area between 200000 and 250000; 二、SELECT name 1.