Skip to content

Commit

Permalink
update python part
Browse files Browse the repository at this point in the history
  • Loading branch information
CharonChui committed May 6, 2024
1 parent 25830ce commit a902bd8
Show file tree
Hide file tree
Showing 2 changed files with 313 additions and 0 deletions.
131 changes: 131 additions & 0 deletions JavaKnowledge/python3入门.md
Original file line number Diff line number Diff line change
Expand Up @@ -603,3 +603,134 @@ tesla.get_battery()
- 方法__init__()接受创建子类实例所需的信息

super()是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让子类包含父类的所有属性。


## 标准库

Python标准库是一组模块,安装的Python都包含它。
类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。


### 读取文件

一次性读取整个文件:
```python
with open('test.txt') as file_object:
contents = file_object.read()
print(contents)
```

要以每次一行的方式检查文件,可对文件对象使用for循环:

```python
filename = 'test.txt'
with open(filename) as file_object:
for line in file_object:
print(line)
```
这里使用了关键字with,让Python负责妥善地打开和关闭文件。
使用关键字with时,open()返回的文件对象只在with代码块内可用。


要将文本写入文件,你在调用open()时需要提供另一个实参,告诉Python你要写入打开的文件。

```python
filename = 'test.txt'

with open(filename, 'w') as fo:
fo.write("Hello World")
```
调用open()时提供了两个实参:

- 第一个实参是要打开的文件的名称
- 第二个实参('w')告诉Python,我们要以写入模式打开这个文件。

打开文件时,可指定读取模式('r')、写入模式('w')、附加模式('a')或让你能够读取和写入文件的模式('r+')。如果你省略了模式实参,Python将以默认的只读模式打开文件。
如果你要写入的文件不存在,函数open()将自动创建它。然而,以写入('w')模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件。
注意 Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式。

如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式打开文件。你以附加模式打开文件时,Python不会在返回文件对象前清空文件,而你写入到文件的行都将添加到文件末尾。如果指定的文件不存在,Python将为你创建一个空文件。


### 异常

异常是使用try-except代码块处理的。try-except代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。使用了try-except代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。


### 分割字符串

方法split()以空格为分隔符将字符串分拆成多个部分,并将这些部分都存储到一个列表中。

```python
title = "Alice in Wonderland"
title.split()
```

['Alice','in','Wonderland']


### pass

Python有一个pass语句,可在代码块中使用它来让Python什么都不要做。


### json

函数json.dump()接受两个实参:要存储的数据以及可用于存储数据的文件对象。下面演示了如何使用json.dump()来存储数字列表:

```python
import json
numbers = [2,3,5,7,11,13]
filename = 'numbers.json'
with open(filename,'w') as f_obj:
json.dump(numbers,f_obj)
```

使用json.load()将这个列表读取到内存中:
```python
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
```

### 网络请求

Web API是网站的一部分,用于与使用非常具体的URL请求特定信息的程序交互。这种请求称为API调用。请求的数据将以易于处理的格式(如JSON或CSV)返回。依赖于外部数据源的大多数应用程序都依赖于API调用,如集成社交媒体网站的应用程序。



requests包让Python程序能够轻松地向网站请求信息以及检查返回的响应。要安装requests,请执行类似于下面的命令:

$pip install --user requests
或者直接在ide中点击修复安装就可以:

![Image](https://raw.githubusercontent.com/CharonChui/Pictures/master/python_install_requests.png)

```python
import requests
# 执行API调用并存储响应
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:",r.status_code)
# 将API响应存储在一个变量中
response_dict = r.json()
# 处理结果
print(response_dict.keys())
```

执行结果为:
```
Status code: 200
dict_keys(['total_count', 'incomplete_results', 'items'])
```

这个API返回JSON格式的信息,因此我们使用方法json()将这些信息转换为一个Python字典。我们将转换得到的字典存储在response_dict中。
最后,我们打印response_dict中的键。





182 changes: 182 additions & 0 deletions VideoDevelopment/OpenGL/13.LUT滤镜.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,188 @@
# 13.LUT滤镜


LUT全称LookUpTable,也称为颜色查找表,它代表的是一种映射关系,通过LUT可以将输入的像素数组通过映射关系转换输出成另外的像素数组。

比如一个像素的颜色值分别是R1 G1 B1,经过一次LUT操作后变为R2 G2 B2。

通过这个映射关系就可以将一个像素的颜色转换为另外一种颜色。


LUT从查找方式上可以分为1D LUT和3D LUT:

- 1D LUT

对于一张RGB图像,每个通道都可以作为一个输入,用公式可以描述如下:
![Image](https://raw.githubusercontent.com/CharonChui/Pictures/master/lut_1d.jpg)


由于颜色值的范围是(0~255),我们可以用`256*3` 的表来表示一个1D LUT,在实际操作中,我们通常以一张`256*3*1`的图片来存储这个映射表,如下,这是一张1D LUT在Mac访达中文件信息图:
![Image](https://raw.githubusercontent.com/CharonChui/Pictures/master/lut_1d_map.jpg)


由于1D LUT各个通道都是相互独立的,无法对其他通道产生影响,因此1D LUT 只能用来调节亮度/伽马/饱和度/色彩平衡等,如果我们希望对其他通道产生影响,就需要了解另一种滤镜查找方式--3D LUT。




- 3D LUT

3D LUT在滤镜中的影响比1D LUT更为深刻,下面我们用一张图(图是网上找的,参考“参考资料”)来说面3D LUT,假设下图的红色平面发生移动,其中对应的绿色和蓝色分量也会发生改变,也就是说,一个颜色通道改变可以影响其他的颜色通道,理论上 3D LUT 可以在立体色彩空间中描述所有颜色调整行为,所以它可以处理任何显示的非线性属性,从简单的 gamma 值、颜色范围和追踪错误,到修正高级的非线性属性、颜色串扰(去耦)、色相、饱和度、亮度等,3D LUT都可以胜任。


![Image](https://raw.githubusercontent.com/CharonChui/Pictures/master/lut_3d.webp)

常见的3D LUT滤镜文件与.cube或者.3dl都是把3D坐标二维化后的数据表现,如下图

![Image](https://raw.githubusercontent.com/CharonChui/Pictures/master/3d_lut.jpg)







我们看到的这些方格子里面的蓝色是固定的,然后每个格子横坐标是红色,纵坐标是绿色,最左上角的格子因为蓝色全无,所以红色和绿色就很明显,而最右下角的那个格子,蓝色色值达到最大,因此整体看上去就非常的蓝。

对于RGB颜色,每种颜色可以有256种取值,因此一个3D LUT 如果全量表示的话,大小为256*256*256,如果我们有一个大小为256*256*256的3D LUT文件,那么颜色映射将非常简单,只要根据RGB的像素值按照用蓝色找到对应的格子,然后用红色和绿色找到对应格子的横列就可以找到映射的颜色值。但是通常情况下,我们不会这么干,因为一张256*256*256的图实在是太大了,至少需要48MB的存储空间,因此,通常会通过降低采样的方式来减少数据量。




我们看到的这些方格子里面的蓝色是固定的,然后每个格子横坐标是红色,纵坐标是绿色,最左上角的格子因为蓝色全无,所以红色和绿色就很明显,而最右下角的那个格子,蓝色色值达到最大,因此整体看上去就非常的蓝。
对于RGB颜色,每种颜色可以有256种取值,因此一个3D LUT 如果全量表示的话,大小为256*256*256,如果我们有一个大小为256*256*256的3D LUT文件,那么颜色映射将非常简单,只要根据RGB的像素值按照用蓝色找到对应的格子,然后用红色和绿色找到对应格子的横列就可以找到映射的颜色值。但是通常情况下,我们不会这么干,因为一张256*256*256的图实在是太大了,至少需要48MB的存储空间,因此,通常会通过降低采样的方式来减少数据量。在专业领域一般认为17x17x17的3D LUT足够适用于预览和监看;65x65x65或者更大的3D LUT更适合渲染和调色。3D LUT的实现在计算机环境会相对容易,在嵌入式环境就意味着成本的提高,越大的LUT需要越昂贵的硬件支持。所以行内比较常用的LUT box一般都不是很大,比如说BMD的HDLink Pro采用了17x17x17的3D LUT(495美元);Fujifilm的IS-Mini则采用了26x26x26的3D LUT(865英镑)。
下面我们就以一个64*64*64的3D LUT为例,来说明一下3D LUT如何查找和使用的(用glsl来实现),一张3D LUT如下:





肉眼可见的有8*8个方格,假设整个图的范围我们定义为0.0~1.0 ,也就是说每个格子所表示的范围是1./8. = 0.125, 我们首先通过蓝色来查找我们在哪个方格,由于涉及到插值,因此通过蓝色进行查找的时候,可能不会那么幸运一定映射到整数的格子上面,因此我们需要通过向下取整和向上进位两种方式来获取蓝色所对应的方格,然后通过蓝色的颜色值来mix这两种的颜色值,从而获取最终的颜色值,glsl实现如下:


## 为什么使用LUT滤镜



在正常情况下,8位的RGB颜色模式可以表示的颜色数量为256X256X256种,如果要完全记录这种映射关系,设备需要耗费大量的内存,并且可能在计算时因为计算量大而产生性能问题, 为了简化计算量,降低内存占用,可以将相近的n种颜色采用一条映射记录并存储,(n通常为4)这样只需要64X64X64种就可以表示原来256X256X256的颜色数量,我们也将4称为采样步长。
要想熟练使用LUT滤镜,我们首先要了解它是怎么建立颜色映射关系的, 我们看下以下这张图,这张图展示了在LUT中RBG颜色是如何实现映射关系的:
lut映射关系图
首先这张图的大小是512X512,在横竖方向上这张图都被分成了8个小方格,每个小方格的大小是64X64,也就是一张512X512的图被分割成64个小方格,每个小方格的大小是64X64,这64个小方格就代表了64种B通道的颜色映射, 然后每个B通道的小方格上又是一个64X64像素大小的图像,这个小图像的横坐标代表R分量的64种映射情况,纵坐标代表了G分量的64种映射情况,这样就刚好这就和采样步长是4的映射表对应上了。
在使用上面这张LUT表的时候首选需要找对B分量对应的小格子,然后在找到的小个子上再计算出R分量和G分量的映射结果即可得到完整的RGB映射结果。



对输入图颜色转换时,以颜色(rgb)的b值作为索引,找到所属于的小格。
最后根据r和g的值在小格中定位到映射的目标值上(两个格子上对应的像素进行插值)。

最后根据r和g的值在小格中定位到映射的目标值上(两个格子上对应的像素进行插值)。


每个小方格的横向有512 / 8 = 64个像素,表示间距为4的R通道,即R色值序列为0, 4, 8, .....251, 255;纵向同样有64个像素,表示间距为4的G通道;B通道被巧妙的放在大格子中(从左到右,从上到下共64个小方格,表示B通道的64个数值)




整张图从左到右和从上到下为蓝色的渐变,每个小格子从左到右为红色渐变,从上到下为绿色渐变

64只是一种颜色粒度的划分,可以是其它数值,具体的看设计师给出查找表是怎么规划的,此处的粒度为64,也就是将RGB的分量划分为64份,颜色[0.0, 1.0] -> [0.0, 63.0]


以一个具体的颜色Color(r = 30.0, g = 30.0, b = 25.4)为例子来说明是如何通过LUT来做映射的。



蓝色值用来定位两个相邻的小格子

第一个小格子:

float blueColor = textureColor.b * 63.0;
vec2 quad1;
// blueColor = 25.4, 第3行的第1个小格子
// floor:向下取整
quad1.y = floor(floor(blueColor) / 8.0);
quad1.x = floor(blueColor) - (quad1.y * 8.0);

第二个小格子:


vec2 quad2;
// blueColor = 25.4,第3行的第2个小格子
// ceil:向上取整
quad2.y = floor(ceil(blueColor) / 8.0);
quad2.x = ceil(blueColor) - (quad2.y * 8.0);

红色值和绿色值用来确定相对于整个LUT的纹理坐标:

vec2 texPos1;
texPos1.x = (quad1.x * 1.0 / 8.0) + (63.0 / 512.0) * textureColor.r);
texPos1.y = (quad1.y * 1.0 / 8.0) + (63.0 / 512.0) * textureColor.g);

vec2 texPos2;
texPos2.x = (quad2.x * 1.0 / 8.0) + (63.0 / 512.0) * textureColor.r);
texPos2.y = (quad2.y * 1.0 / 8.0) + (63.0 / 512.0) * textureColor.g);

通过纹理坐标获取两个新的颜色:

vec4 newColor1 = texture2D(u_LookupTable, texPos1);
vec4 newColor2 = texture2D(u_LookupTable, texPos2);

然后根据蓝色值小数部分作为权重做线性混合,获取最终的颜色输出:

// mix(x, y, a) -> x * (1 - a) + y * a
vec4 newColor = mix(newColor1, newColor2, fract(blueColor));

完整的顶点着色器:


attribute vec4 a_Position;
attribute vec4 a_TextureCoordinate;

varying vec2 vTextureUnitCoordinate;

void main() {
gl_Position = a_Position;
vTextureUnitCoordinate = a_TextureCoordinate.xy;
}


片元着色器代码

precision mediump float;

uniform sampler2D u_TextureSampler;
uniform sampler2D u_LookupTable;
uniform float u_Intensity;

varying vec2 vTextureUnitCoordinate;

void main() {
vec4 textureColor = texture2D(u_TextureSampler, vTextureUnitCoordinate);
float blueColor = textureColor.b * 63.0;
vec2 quad1;
quad1.y = floor(floor(blueColor) / 8.0);
quad1.x = floor(blueColor) - (quad1.y * 8.0);

vec2 quad2;
quad2.y = floor(ceil(blueColor) / 8.0);
quad2.x = ceil(blueColor) - (quad2.y * 8.0);

vec2 texPos1;
texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);

vec2 texPos2;
texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);

vec4 newColor1 = texture2D(u_LookupTable, texPos1);
vec4 newColor2 = texture2D(u_LookupTable, texPos2);

vec4 newColor = mix(newColor1, newColor2, fract(blueColor));
gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), u_Intensity);
}





Expand Down

0 comments on commit a902bd8

Please sign in to comment.