Hydra使用

最简单使用

安装

1
pip install hydra-core

初步测试

目前的代码结构

1
2
3
4
folder
├── conf
│ └── recoro_train.yaml
└── main.py

其中main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
from omegaconf import DictConfig, OmegaConf
import hydra

@hydra.main(config_path="./conf", config_name="recoro_train")
def main(cfg: DictConfig):
    running_dir = str(hydra.utils.get_original_cwd())
working_dir = str(Path.cwd())
print(f"The current running directory is {running_dir}")
print(f"The current working directory is {working_dir}")


if __name__ == "__main__":
main()

结果

1
2
The current running directory is C:\Users\xx\xx\xx\folder\
The current working directory is C:\Users\xx\xx\xx\folder\outputs\2023-02-08\22-47-06

可以看到hydra运行时,会自动建立一个输出文件夹,包含日期和时间信息,然后还会直接将路径调到里面去,以方便保存脚本内的各种东西。这就是初步测试,全部都在这一行:配置的路径在”conf”,配置的文件名为”recoro_train”

因此,无论在代码的任何地方,新建文件都会在working directory下 进行新建写入。

【Python】Hydra 库使用记录_Kin__Zhang的博客-CSDN博客_python hydra

python常用指令

查看pytorch版本

1
2
import torch
print(torch.__version__)

python 文件管理

文件列表
1
2
3
4
filefolder = os.listdir(root)
filefolder.sort()
for f in filefolder:
    print(f)
删除文件
1
2
3
4
5
6
7
8
import os
import shutil

os.remove(path) #删除文件
os.removedirs(path) #删除空文件夹

os.rmdir(path) #删除空文件夹
shutil.rmtree(path) #递归删除文件夹,即:删除非空文件夹
文件读取
1
2
3
4
with open('./loss.txt','a+') as f:   
for key in losssum:
f.write(f"test_img : losses {key}: {losssum[key]/items}\n")
f.close()

python 直接使用os.system

1
2
3
command = 'ffmpeg -i ./results/%s/'%(datasetname[i]) +'%06d.png ./results'+'/%s.mp4'%(datasetname[i])
print(command)
os.system(command)

python 读写、创建 文件 - juandx - 博客园

python超参传递

1
2
3
4
5
6
7
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-in", "--inputA", help="this is parameter a", type=str, default="")
parser.add_argument("-out", "--outputB", help="this is parameter b", type=str, default="")
args = parser.parse_args()
print(args.inputA)
1
python3 /Users/PeppaZhu/Desktop/studio_light/zoom_VB/test_V4_1NGF.py -in test_video_gfdebug/peppa_13test.mov -out peppa_13test_V4_4

cplusplus文件管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;
std::string path = "/Users/oliverzhu/Desktop/test_video/";
for (const auto &entry : fs::directory_iterator(path)){
        //将文件夹下所有文件名得到
std::string inputpath = entry.path();
std::string::size_type nPos1 = std::string::npos;
std::string::size_type nPos2 = std::string::npos;
nPos1 = inputpath.find_last_of("/");
nPos2 = inputpath.find_last_of(".");
        //截取/开始 长度为nPos2-nPos1-1的字符串
std::string strPath = inputpath.substr(nPos1 + 1, nPos2-nPos1-1);
std::string input_path;
std::string output_path;
if (nPos2-nPos1 > 1)
{
// vaild input path
input_path = inputpath;
output_path = "/Users/oliverzhu/Desktop/results/" + strPath + ".mp4";
std::cout << input_path << std::endl;
std::cout << output_path << std::endl;
        }

https://codeantenna.com/a/vhWRDy0wan

cplusplus里数据类型的大小和存储方式

不同数据类型的大小

相同位数的系统下,每一个变量的地址大小相同

1
2
3
4
5
6
7
8
9
        int32_t va; int32_t* vb; double vc; double* vd; uint8_t ve; uint8_t* vf; intptr_t vg;

        int32_t a = sizeof(&va); //8
int32_t b = sizeof(&vb); //8
int32_t d = sizeof(&vc); //8
int32_t e = sizeof(&vd); //8
int32_t f = sizeof(&ve); //8
int32_t g = sizeof(&vf); //8
int32_t h = sizeof(&vg); //8

以上变量地址大小都是 8 ,因为在64位体统下。

相同位数的系统下,不同类型变量占有的空间大小不同

1
2
3
4
5
6
7
8
9
10
int32_t va; int32_t* vb; double vc; double* vd; uint8_t ve; uint8_t* vf; intptr_t vg;

int32_t a = sizeof(va); //4
int32_t b = sizeof(vb); //8
int32_t d = sizeof(vc); //8
int32_t e = sizeof(vd); //8
int32_t f = sizeof(ve); //1
int32_t g = sizeof(vf); //8
int32_t h = sizeof(vg); //8
int32_t i = sizeof(*vb); //4

这里*vb == vb[0]

不同位数的系统下,不同/相同变量占有的大小不同

当申请一块 uint_8* buff 时,系统划分出一个8字节的大小,存储了一个指向随机位置的指针。

buff = (uint_8*)calloc(seizeof(*buff) * 10,0 ); 时,buff指向了一块地址。这块地址保存的都是十个 1字节的uint_8数据。

1
2
3
4
5
6
7
8
        uint8_t* aa;
aa = (uint8_t*)zltCMemoryBasic::zlt_calloc(sizeof(*aa) * bufSizeB * 12, 0);

        aa[0] = 1; aa[1] = 2;
uint8_t a = aa[0]; //1
uint8_t c = aa[1]; //2
uint8_t b = *aa; //1
uint8_t d = *(aa+1); //2

uint8 int float double 怎么在计算机内存储

uint8:占一个字节八位, 无符号数,0~255,算数or逻辑左移右移就是左右移动,舍去移动的位数然后补零

int32 :四个字节32位,有符号数,最高位代表符号。

最大数2147483647的原码为0111 1111 1111 1111 1111 1111 1111 1111

最小数-2147483648的补码表示为1000 0000 0000 0000 0000 0000 0000 0000,在32位没有原码。

对有符号数逻辑左右移动不考虑符号,算数右移补符号位。

float32: 四字节32位,有符号数,最高位代表符号。E代表指数 2E M代表尾数

https://zhuanlan.zhihu.com/p/84453627

Shell指令

语法基础

作为可执行程序

将代码保存为name.sh,并 cd 到相应目录

chmod +x ./test.sh #使脚本具有执行权限

./test.h 运行,或者将文件拖入终端运行

注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。

#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器(sh、bash、php等等)来执行。

使用模版

1
2
3
4
5
#!/bin/bash
echo "Hello World !"
ffmpeg -r 30 -i output/%05d.jpg -vcodec libx264 -vf zscale=matrix=709:r=full output.mp4
mkdir backlit
ffmpeg -i backlit.mp4 -r 30 backlit/%05d.png

https://www.runoob.com/linux/linux-command-manual.html

Shell脚本书写规范 - That’s_it - 博客园

文件操作

1
2
3
4
5
6
7
8
9
10
删除文件
rm -r *.pdf
但是一次性删除太多的话就会报错 zsh: argument list too long: rm 此时用
find . -name "*.pdf" -print0 | xargs -0 rm

移动文件
mv folder2/*.* folder/
移动太多会报错
find folder2 -name '*.*' -exec mv {} folder \;
-exec runs any command, {} inserts the filename found, \; marks the end of the exec command.

linux - Argument list too long error for rm, cp, mv commands - Stack Overflow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
查看当前路径下文件个数(不包括下一级子目录里文件个数)
ls -l | grep "^-" | wc -l
查看当前路径下文件个数(包括下一级子目录里文件个数)
ls -lR| grep "^-" | wc -l
查看某目录下文件夹(目录)的个数(包括子目录)
ls -lR | grep "^d" | wc -l

命令解析:
ls -l
长列表输出该目录下文件信息(注意这里的文件是指目录、链接、设备文件等),每一行对应一个文件或目录,ls -lR是列出所有文件,包括子目录。

grep "^-"
过滤ls的输出信息,只保留一般文件,只保留目录是grep "^d"。

wc -l
统计输出信息的行数,统计结果就是输出信息的行数,一行信息对应一个文件,所以就是文件的个数。

Linux统计文件夹下的文件数目 | SnailTyan

Bilateral and Guided Filter

双边滤波 for gray and color images

原理

在滤波加权的时候计算几何相似度和光学相似度,在亮度差别大的地方不进行平均加权,从而达到保边。

公式

test

在上述公式中,k代表正则化,c(.)代表几何相似度,也就是距离, s(.) 代表光学相似度,可以是色彩的差,亮度的差等。

实验现象

如果只做色彩滤镜相当于对直方图进行压缩,也就是只做色彩滤镜相当于把全图色彩平均,向中灰度压缩。

当像素相似度比较大的时候(100~300),对于小的范围参数影响不大了,因为几乎小范围内的所有数据都在像素相似度内。整图结果主要由范围半径控制。

当范围半径比较大的时候,双边滤波更像是色彩相似度滤镜,表现为对直方图的压缩,现象就是偏灰。

常说到的导致梯度反转

首先,是双边滤波在做Tone Mapping时才会导致梯度反转。并不是直接用双边滤波得到保边平滑图就会出现梯度反转。

双边滤波在做Tone Mapping时,Fast Bilateral Filtering for the Display of High-Dynamic-Range Images ,将图像分成base层和ditail 层 base = BF(ori_img) detail = ori_img./base。由于base层在边缘处加权的数据少,所以不稳定,偏向没有边缘的那一侧的值。导致的detail层也不稳定,在增强或者压缩base后,叠加detail会出现梯度反转。

Guided Filter

目的

保边平滑,线性时间复杂度(与滤波半径无关),以及和matting Laplacian matrix理论有相似形式。可以用于:去噪,细节增强/平滑,HDR压缩,抠图,羽化,去雾,联合双边上采样。

原理

在一个小的局部区域,输出是guidance I 的一个线性变化,通过这个假设来确保,在局部,输出q的梯度和guidance I的梯度成比例,从而引入,或者说保留guidance I的梯度。

在一个局部的区域内,输出q,或者说是去噪音后的输入p,是引导图I的一个kI+b的线性变化。kI也就是,引导图的变化趋势都被保留,b是为了模拟p所在域的bias。eps控制a不能太大,这项是为了控制平滑(模糊)程度的

公式

公式意义:

当I没有梯度的时候,a等于0 ;当p没有梯度的时候,a等于0; 也就是任意一方是平坦图的时候,输出q 退化为p的两次boxfilter

当I有比较大的梯度,p也有比较大梯度,且他们有相关性的时候(分母一定,也就是I方差一定,Ip相关性越大分子越大),a越大,I的梯度得到保留

当引导图的方差远小于eps时,a几乎等于0,像素被平滑,也就是引导图方差相对于eps的关系决定了平滑的力度。

对于引导图I,滤波图p为一副图的情况,a = 方差/方差+eps b = avg - a*avg。输出就变成了根据方差和eps关系,来选择性输出原图或者是avg图。对于方差比较大的边缘,输出原图的权重高,对于方差比较小的地方,输出平均图的权重高。

公式几何意义:在一个局部区域内,I为横轴p为纵轴,q = aI+b,也就是一条直线尽量拟合每一个(I,p) ,那么根据这个拟合结果,可以对原本的p有一个新的输出q。

考虑到eps 对a的限制,输出可能更平滑一些

线性复杂度:由于一个固定方框内的均值方差可以采用box filter的优化方式变成线性复杂度,因此本算法也可以优化成线性复杂度。

实验现象

参数: GuidedFilter(guided,10,0.000001),对于引导图是黑白图像,输出会引入边缘处其他梯度,会导致有些边缘模糊。模糊可能是因为,第一,p在该区域不全为0,有梯度变化。引导图在该区域有梯度,a有值,再加上a的平均,导致在边缘区域加入了引导图。第二,引入边缘处的梯度就是不完全的加权加了一部分原图的自然结果。且a并不是1,是-1~11的数据。简单来说,在边缘处黑度图他们不可清晰分类。

对于引导图是彩色图,其结果好转。彩色图在计算时,a是引导图三通道3*3方差 * (I * P), 也就是单独通道颜色不匹配(哪怕亮度匹配),a依旧很小。防止引入相同亮度不同颜色的边缘信息。简单来说,在rgb色彩空间,边缘可分。

抠图潜在危险

  1. 半径不能太大。不然线性无法拟合。而且脸部要是有白色高光容易和背景墙混淆。

  2. 几乎完全相同颜色的边缘信息会引入。比如白色衣服白色墙体。黑色头发黑色椅子,因为本质上相同颜色不可分。于是会出现更多错误。

  3. 边缘处有rgb色彩重叠,会有些错分,带来就是部分引入错误,淡化原本01的强分割边界。

代码

https://github.com/lisabug/guided-filter

针对于抠图的潜在危险设计的S_Guided Filter

针对于缺点2,设计了选择区域的GF,总的来说是颜色差别较大的区域Guided Filter生效,当颜色差别较小的区域不使用Guided Filter

具体做法:在算引导图I 方差的时候,标记I 大于一定值的区域作为生效区域。当引导图为彩色图是,存在RR,RG,RB..等九个协方差,选取最大那个作为判定值。(因为当有一种颜色RR GG BB,或者一对颜色关系RG RB GB 可分时这个区域就可以区分)。

引入的危险:阈值如何计算。太小了的话,那些高噪音的平台区域也变成working area了,太大了的话,一些本来可以使用GF的区域也失效了。

测试case:尽量让浅肤色和白墙,深色头发和黑墙可以区分,不让白衣服白墙,全黑衣服和黑墙,以及高噪音全黑衣服和黑墙引入错误。

针对于缺点3,对GF后的结果进行了一些拉伸,让分割锐利,且剔除被分到前景的背景,但不在原基础上新增内容(可能有的前景被CNN分到了背景但是GF也无法加回来了)

具体做法:

•Q, Workingarea  = GuidedFilter(guidedI,ori_mask) ;//得到可分区域或者纹理复杂区域

•Q是GF算法的直接结果,包含错分区域,纹理复杂区域,以及正确区域

•M = ori_mask - Q;//改变值, M本身在-1~1之间

•M = M * 2 – 0.3(beta);//将改变的数据进行拉伸,后在-2.3 ~1.7之间放大改变值的。

•M[M<0]= 0; // 1:不会新添加东西 2:如果改变值过小就忽视 。

•M[M>1] = 1; //数据合理性约束

•Output = (Workingarea == TRUE)? (ori_mask – M) : ori_mask

•Output < 0 = 0; // 数据合理性

引入的危险:*2 - 0.3 是手调拉伸超参数。为了保证变化锐利而非自然。且舍弃了将前景补足的潜力。

测试case:卷曲的头发剔除背景合理,不增加黑头发后面的复杂背景。

卡尔曼滤波

卡尔曼滤波

更通用的,一个变量(状态)的卡尔曼滤波

就是利用历史数据(根据状态转移方法)预测新数据,并且根据当前观测的新数据值,和其不确定性,综合修正预测的数据。

干了这么

如果有两个系统对一个数据(高度,位置或者其他的)都有测量或者说是观测,但是都不准。那如何通过这两个不准的东西得到一个更准的结果。

更简单的说法:怎么去求两个数据的加权平均

如何通俗并尽可能详细地解释卡尔曼滤波? - Kent Zeng的回答 - 知乎 https://www.zhihu.com/question/23971601/answer/26254459

翻译理解

接下来按照

https://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/

一文简单翻译理解一下 这是一个多变量 运动定位系统

what is it ?

你有一个不准确但是可以观测的,连续变化的系统。此外,你还能对着干观测值进行一些科学的推论。但是也不准。通过卡尔曼滤波(合理的对不准确的推理和不准确的观测结果加权),可以得到一个更准确的当前值的结果。

what can we do with a Kalman filter

假设你有一个小机器人,这个机器人在森林里行走,需要定位。

这个小机器人有一个状态,这个状态包括了当前位置和当前速度。这个速度是某种码表里可以读出来的。此外,这个机器人还有一个GPS定位,表明了当前的位置。不管是GPS还是速度都是不太准的的。怎么得到更准确的当前位置呢?

how a Kalman filter sees your problem

我们有两个连续变化的数据(假设都服从高斯分布),位置和速度,虽然这些都不准,方差衡量了不同变量各自的不确定性,协方差衡量了他们之间的关系。

Describe the problem with martics

我们可以得到,当前状态的(速度和位置)的均值,然后和这两个变量之间的斜方差矩阵

下一步,我们可以通过p = p + vt 得到下一次的位置,速度预测。这步就是科学推倒得到的合理的预测。同时更新均值和其斜方差。

此外,考虑再复杂一些,我们加入外力(加速度)和不确定性。

最终影响下一次状态的均值的是,当前状态以及外力,影响下一次斜方差的是当前斜方差,不确定噪音。

Refining the estimate with measures

我们可以通过直接读数,得到一个位置速度分布的概率。我们还可以通过科学推倒得到一个速度位置分布的概率。那将这两个概率相乘归一化,就是更准的概率了。

putting it all together

新的位置等于 根据老位置预测出来的新位置,以及新位置读数的加权。加权值由推倒公式,读数概率等原始数据共同决定。

信号去噪之卡尔曼滤波_卡尔曼滤波 去噪-CSDN博客

卡尔曼滤波去噪python_mob64ca12f7e7cf的技术博客_51CTO博客

【译】图解卡尔曼滤波(Kalman Filter)-腾讯云开发者社区-腾讯云

git在干什么

Git

git pull

1.0 如果在本地有更新,但是没有commit, pull会失败 ?不会,如果本地有更新,但是远程没有更新,pull好像没啥区别。

1.1 但是不是远程有更新,本地也有更新,并且本地没有commit这时候pull才会失败?

1.2 正常来说,需要commit将本地更新记录到本地仓库 或者 checkout . 把本地跟新的退回

2 假设本地我修改了A文件,别人在远方修改了B文件,我commit后pull,B文件会被更新,但是A文件我的修改不会丢失

3 假设本地我修改了A文件,别人在远方修改了A文件,我commit后pull会失败,需要git pull origin sara-ep-attlit –rebase

参考

https://www.jianshu.com/p/27718f0741d8

https://blog.csdn.net/lzxlfly/article/details/103837258#:~:text=git%20pull%E7%9B%B8%E5%BD%93%E4%BA%8E%E6%98%AF%E4%BB%8E,%E5%8F%96%E4%B8%8B%E6%9D%A5%E7%9A%84commitid%E8%AE%B0%E5%BD%95%E3%80%82

https://www.jiqizhixin.com/articles/2020-05-20-3

http://chuquan.me/2022/05/21/understand-principle-of-git/

https://xiaowenxia.github.io/git-inside/2020/12/06/git-internal.objects/index.html

深入理解 Git 底层实现原理 | 楚权的世界