0%

Hexo:用Github搭建自己的博客网站!

作为一名程序猿,拥有一个自己的博客来记录学习和一闪而过的灵感是一件好处多多的事,既可以帮助自己进步,也可以在别人遇到类似问题的时候帮上忙,甚至还可以面试的时候装个*。当然,现在网络上的各类博客有很多,诸如大家耳熟能详的CSDN、博客园、简书等等,可以直接发表自己的文章,这些网站用户交互做的很好,并且贴心地支持Markdown。

然而自己购买域名和服务器专门来搭建博客网站,除了购买成本令人望而生畏外,光是花力气搭建网站、定期维护就需要可观的精力和时间。

那么,接下来就要隆重介绍今天的主角——hexo

Hexo 简介


Hexo是一款基于Node.js的静态博客框架,网页托管在Github上,安装使用非常方便,完全是搭建博客的首选!

文章分为两个部分:

  • hexo的初级搭建,github部署,以及个人域名的绑定
  • hexo的基本配置,主题更换等

Let’s Go!

第一部分 hexo的初级搭建


Hexo搭建步骤

  1. 安装Git
  2. 安装Node.js
  3. 安装Hexo
  4. Github创建个人仓库
  5. 生成SSH添加到GitHub
  6. 将hexo部署到Github
  7. 设置个人域名
  8. 发布文章!

1. 安装Git

绝对不能不知道这个工具!不了解它的同学们!出门左转赶紧学起来!

  • Windows
      到Git官网下载Git Download ,安装后就可以用 Git Bash 命令行工具来使用Git了。安装好后,在Git Bash中输入git --version检验是否安装成功

  • Linux

  对Linux来说,就是一行代码的事儿

1
sudo apt-get install git

  同样,安装好后,用git --version查看版本

2. 安装Node.js

hexo是基于Node.js编写的,所以需要一下Node.js和里面的npm工具。

  • Windows

  Node.js官网下载LTS版本,64位msi安装包,安装后分别在命令行(win+R输入cmd调用)输入node -vnpm -v检验PATH环境变量是否配置了Node.js

  

  • Linux
1
2
sudo apt-get install nodejs
sudo apt-get install npm

  检验安装成功方式同Windows

3. 安装hexo

Windows环境进入Git Bash,Linux环境进入终端,开始搭博客啦!

首先新建一个文件夹blog来存放自己的博客,然后cd进入到这个文件夹下,输入下面的命令安装hexo

1
npm install -g hexo-cli

同样,安装完毕后需要hexo -v查看一下版本

至此需要的工具都安装完了。接下来初始化一下hexo

1
hexo init blog

这里的blog取什么名字都行

这时,在你的blog文件夹下会出现一个新的blog文件夹,进入到这个子文件夹后新建hexo

1
npm install

新建完成后,指定文件夹目录下应该有以下主要文件:

  • node_modules:依赖包
  • scaffolds:生成文章的一些模板
  • source:用来存放自己的文章
  • themes:网站主题
  • __config.yml:博客的配置文件
1
2
hexo g
hexo server

输入以上命令来开启hexo服务,在浏览器中输入localhost:4000就可以看到博客的初始化界面啦,现在还是有点丑丑的,大概长这样

ctrl-c可以把服务关掉

此时再回到文件夹,你会发现多了一个public文件夹,这时用来存放生成的页面的。

4. GitHub创建个人仓库

上文提到过,hexo的静态网页是托管在GitHub中的,所以需要在GitHub中新建一个 和你用户名相同的 仓库,后面加 .github.io,也就是xxxx.github.io,只有这样将来要部署到GitHub Page的时候才会被识别。

5. 生成SSH添加到GitHub

回到Git Bash中,输入命令

1
2
git config --global user.name "yourname"
git config --global user.email "youremail"

这里的yourname对应你的GitHub用户名,youremail对应你的GitHub注册邮箱,这样GitHub才能知道你是不是对应它的用户。不放心的话可以用下面两条命令来检查一下:

1
2
git config user.name
git config user.email

然后创建SSH,你可以选择密钥的保存位置,然后一路回车

1
ssh-keygen -t rsa -C "youremail"

创建成功后,文件夹下会有两个文件,其中id_rsa是你这台电脑的私人密钥,id_rsa.pub是公共密钥。把公钥放在GitHub上,这样当你链接GitHub自己的账户时,她就会根据公钥匹配你的私钥,匹配成功才能通过git上传自己的文件到GitHub上。

在GitHub的setting(右上角头像下拉)中找到SSH and GPG keys的设置选项,点击New SSH key,把的id_rsa.pub里面的内容复制进去。

然后回到Git Bash,试试能否ssh通。

6. 将hexo部署到GitHub

在这步中,我们将要把hexo和GitHub关联起来,使得hexo生成的文章都部署到GitHub上。

打开网站配置文件_config.yml,拉到最后,将deploy部分修改为:

1
2
3
4
deploy:
type: git
repo: https://github.com/YourGithubName/YourGithubName.github.io.git
branch: master

其中,YourGithubName对应你的GitHub账户,并且注意:后必须要跟一个空格。

接下来安装deploy-git,也就是部署的命令,只有这样才能用命令将文章部署到GitHub上

1
npm install hexo-deployer-git --save

然后

1
2
3
hexo clean
hexo generate
hexo deploy
  • hexo clean:清除之前生成的东西,在日后新部署文章的时候可以使用,现在加不加没什么区别
  • hexo generate:生成静态文章,缩写hexo g
  • hexo deploy:部署文章,缩写hexo d

出现下图说明部署成功

在浏览器地址栏中输入https://yourname.github.io就可以看到你的博客网站了!!像这样⬇

7. 设置个人域名

是不是觉得.github.io逼格太低了?那就来氪金设置个人域名吧!

阿里云上注册一个账号,再买一个域名,每个后缀的价格都不一样,最便宜的是.top,而应用最广泛的.com就比较贵。实名认证后进入控制台,展开左侧菜单栏,选择域名进入,你会看到自己购买的域名,点解析进入。

选择添加记录,设置如下:

然后重新进入之前创建的仓库,点击Settings,在Options中下拉到GitHub Pages部分,在Custom domain中输入自己的域名。随后在博客文件夹blog下新建一个名为CNMAE的文件,不要加后缀,在里面写上自己的域名。最后重新在Git Bash中

1
2
3
hexo clean
hexo g
hexo d

等一小会儿时间,再打开浏览器,输入自己的域名,就可以看到刚才的初始化界面啦

接下来就可以开始写文章并发布了。

1
hexo new "newArticleName"

它会在source/_post文件夹下新建一个同名的markdown文件,编辑完成后,再

1
2
3
hexo clean
hexo g
hexo d

等一会儿就可以看到更新了,是不是很!简!单!

第二部分 hexo的基本配置


这部分我们来介绍hexo的基本配置、主题更换等。

1. hexo基本配置

blog文件夹下的_config.yml文件是整个hexo框架的配置文件,下面我们简单介绍几个常用配置,详细信息可以参考官方的配置描述。

网站 - Site

这部分参数包括了

  • title:网站标题
  • subtitle:网站副标题
  • description:网站描述
  • author:博客作者,也就是你的名字
  • language:网站语言,中文使用zh-CN
  • timezone:网站时区。默认使用电脑时区,或者自己设置Asia/Shanghai

网址 - URL

这部分参数包括了

  • url:网址,也就是你的网站域名
  • root:网站根目录,默认为\
  • permalink:生成文章永久链接时的格式,不同的参数表示不同的链接格式,官方文件有详细说明,这里给出几种例子
参数 描述
:year/:month:day:title/ 2019/10/26/hello-world
:year-:month-:day-:title.html/ 2019-10-26-hello-world.html
:category/:title/ foo/bar/hello-world
  • permalink_defaults:永久链接格式中各部分的默认值

主题 - theme

theme参数决定了你选择什么主题,官网上有很多个主题,默认的是landscape,你可以在官网上下载自己喜欢的主题,放在theme文件夹下,同时将这个参数修改为主题文件夹名称即可。

个别文件变量 - Font matter

Font matter是Markdown文件最上方以---分隔的区域,用于指定文件自己的变量,例如:

预先定义的参数有:

参数 描述
layout 布局
title 标题
date 创建日期
updated 更新日期
comments 开启评论
tags 标签
categories 分类
permalink 覆盖文章默认网址

layout是在每一次创建新文件时使用的布局,也就是说new这个命令实际上是

1
hexo new [layout] <title>

hexo有三种不同的布局,对应了三种不同的存储路径

  • post:这是hexo默认使用的布局,新建的文件保存在source/_posts
  • page:如果想另起一页,就可以使用
1
hexo new page board

  这句命令会让系统在source文件夹下创建一个board文件夹,以及文件夹中的index.md

  • draft:如果文章太长一次写不完,可以先写草稿文件,这样就不会被别人看到了。
1
2
3
4
5
6
hexo new draft newArticle 
# 在source/_draft中创建一个newArticle.md文件。
hexo server --draft
# 在本地端口中开启预览服务
hexo publish draft newpage
# 将完成的草稿文件发送到`post`中发表

像上面例子中的mathjax参数是自己在主题文件夹下_config.yml中修改的,用来开启Latex的使用。

2. 更换主题

如果觉得默认主题不好看,那么就可以在官网主题中选择自己喜欢的进行修改。这里强烈推荐 NexT主题!非常简洁,赏心悦目。

直接从github上下载下来放到theme文件夹下,再把theme参数改成对应主题名字就ok了

图像文件序列按序重命名编号 - std::glob && std::imwrite

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
int extractId(String a)
{
string a_ = a;
string src_ = "D:\\theThirdYear\\RM\\task1\\imageDataset\\";
int pos_a = a_.find(src_);
int n = src_.size();
a_ = a_.erase(pos_a, n);

string tail = ".jpg";
pos_a = a_.find(tail);
n = src_.size();
a_ = a_.erase(pos_a, n);

stringstream ss;
int A;
ss << a_;
ss >> A;

return A;
}

int main()
{
Mat image;
String src = "D:\\theThirdYear\\RM\\task1\\imageDataset\\";
String dst = "D:/theThirdYear/RM/task1/image/";

vector<String> names;
char name[10];
glob(src, names, false);
sort(names.begin(), names.end(),cmp);

for (int i = 0; i < names.size(); i++)
{
image = imread(names[i]);
if (image.data != NULL)
{
sprintf_s(name, "%04d.jpg", i);
imwrite(dst + name, image);
cout << name << endl;
}
else {
cout << "end of reading" << endl;
}

}
return 0;
}

string字符串中删去指定字符/字符串 - string::find && string::erase

1
2
3
4
5
string str;
string target;
int pos = str.find(target);
n = target.size();
str = str.erase(pos,n);

字符串和数字的相互转化 - stringstream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <sstream>

// 字符串->数字
string str = "123";
int id;

stringstream ss;
ss << str;
ss >> id;

// 数字->字符串
int id = 123;
string str;

stringstream ss;
ss << id;
ss >> str;

在图片上打印帧数 - cv::putText

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Mat putFrame(Mat &image, int frame)
{
Mat img = image;
// 输出文本字符串
char id[10];
sprintf_s(id, "%04d", frame++);
string text = "Frame: ";
text = text + id;
// 设置文本参数
int font_face = FONT_HERSHEY_COMPLEX;
double font_scale = 1;
int thickness = 2;
int baseline;
// 获取文本框长宽
Size text_size = getTextSize(text, font_face, font_scale, thickness, &baseline);
Point origin;
origin.x = 0;
origin.y = text_size.height;
putText(img, text, origin, font_face, font_scale, Scalar(255, 255, 255), thickness, 8, 0);
return img;
}

读入视频/图像序列 - cv::VideoCapture

1
2
3
4
5
6
7
8
9
10
11
12
13
14
std::string frame_file = "your/frame_file/path/%d.jpg";
cv::VideoCapture Sequence(frame_file);
if (!Sequence.isOpened())
std::cerr << "Failed to open image dataset" << std::endl;
while(1)
{
Sequence >> img;
if (img.empty())
{
std::cout << "End of Sequence" << std::endl;
break;
}
// 图片处理
}

给定范围内图像二值化 - cv::inRange

1
cv::inRange(hsv_img, cv::Scalar(hmin, smin, vmin), cv::Scalar(hmax, smax, vmax), bin_img);

生成滚动条控制参数变化 - cv::createTrackbar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 滚动条参数,初始值为0/360,反馈滚动条上的数值
int hmin = 0;
int hmax = 360;
int smin = 0;
int smax = 255;
int vmin = 0;
int vmax = 255;
// 滚动条参数最大值,最小值默认为0
int hmin_max = 360;
int hmax_max = 360;
int smin_max = 255;
int smax_max = 255;
int vmin_max = 255;
int vmax_max = 255;

// 设置为全局变量一边在子函数中的使用
Mat hsv_img;
Mat bin_img;

void on_Trackbar(int, void*)
{
cv::inRange(hsv_img, cv::Scalar(hmin, smin, vmin), cv::Scalar(hmax, smax, vmax), bin_img);
cv::imshow("bin_img", bin_img);
}

int main()
{
cv::namedWindow("Trackbar", 1);
cv::createTrackbar("hmin", "Trackbar", &hmin, hmin_max, on_Trackbar);
cv::createTrackbar("hmax", "Trackbar", &hmax, hmax_max, on_Trackbar);
cv::createTrackbar("smin", "Trackbar", &smin, smin_max, on_Trackbar);
cv::createTrackbar("smax", "Trackbar", &smax, smax_max, on_Trackbar);
cv::createTrackbar("vmin", "Trackbar", &vmin, vmin_max, on_Trackbar);
cv::createTrackbar("vmax", "Trackbar", &vmax, vmax_max, on_Trackbar);

while(1)
{
Sequence >> img;
if (img.empty())
{
std::cout << "End of Sequence" << std::endl;
break;
}
hsv_img = cv::Mat(img.size(), img.type());
cv::cvtColor(img, hsv_img, CV_BGR2HSV);

//结果在回调函数中显示
on_Trackbar(hmin, 0);
on_Trackbar(hmax, 0);
on_Trackbar(smin, 0);
on_Trackbar(smax, 0);
on_Trackbar(vmin, 0);
on_Trackbar(vmax, 0);

cv::waitKey();
}
}

寻找列表中的最小值和最大值 - std::minmax()

  该函数返回一个pair,该pairfirst元素值为最小值(第一次出现的),second元素的值为最大值(第一次出现的)。

1
auto it = minmax([1,2,3,4,5]);

旋转矩形类 - cv::RotatedRect(const Point2f& center, const Size2f& size, float angle)

  • center : 矩形中心坐标
  • size: 矩形长宽
  • angle:从水平轴开始的顺时针旋转角度

轮廓提取函数 - void cv::findContours

函数原型
1
2
3
4
findContours( InputOutputArray image, OutputArrayOfArrays contours,
              OutputArray hierarchy, int mode,  
              int method, Point offset=Point()
); 
  • image: 单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;
  • contours: 定义为vector<vector<Point>> contours,是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。有多少轮廓,向量contours就有多少元素。
  • hierarchy: 定义为 vector<Vec4i> hierarchy,也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。向量hiararchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。
      hierarchy向量内每一个元素的4个int型变量——hierarchy[i][0] ~ hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~ hierarchy[i][3]的相应位被设置为默认值-1。
  • mode: 定义轮廓的检索模式:
    • CV_RETR_EXTERNAL: 只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略。
    • CV_RETR_LIST: 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1。
    • CV_RETR_CCOMP: 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层。两个等级关系:顶层为连通域的外围边界,次层为孔的内层边界。
    • CV_RETR_TREE: 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
  • method: 定义轮廓的近似方法:
    • CV_CHAIN_APPROX_NONE: 保存物体边界上所有连续的轮廓点到contours向量内
    • CV_CHAIN_APPROX_SIMPLE: 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留
    • CV_CHAIN_APPROX_TC89_L1CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
  • Point: 偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值

轮廓绘制函数 - void cv::drawContours

函数原型
1
2
3
4
5
6
7
8
9
10
11
12
void drawContours
(
InputOutputArray image,
InputArrayOfArrays contours,
int contourIdx,
const Scalar& color,
int thickness = 1
int lineType = 8
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX,                                       
Point offset = Point()
)
  • image: 要绘制轮廓的图像
  • contours: 所有输入的轮廓,每个轮廓被保存成一个point向量
  • contourIdx: 指定要绘制轮廓的编号,如果是负数,则绘制所有的轮廓
  • color: 绘制轮廓所用的颜色
  • thickness: 绘制轮廓的线的粗细,如果是负数,则轮廓内部被填充
  • lineType: 绘制轮廓的线的连通性
  • hierarchy: 关于层级的可选参数,只有绘制部分轮廓时才会用到
  • maxLevel: 绘制轮廓的最高级别,这个参数只有hierarchy有效的时候才有效
    • maxLevel=0,绘制与输入轮廓属于同一等级的所有轮廓即输入轮廓和与其相邻的轮廓
    • maxLevel=1, 绘制与输入轮廓同一等级的所有轮廓与其子节点
    • maxLevel=2,绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点
  • offset: 偏移量

轮廓的最小外接矩形函数 - Rect cv::boundingRect( InputArray array )

  • InputArray array: 一般为findContours函数查找的轮廓,包含轮廓的点集或者Mat;
  • 返回值为最小外接矩形的Rect,即左上点与矩形的宽度和高度;

返回指定形状和尺寸的结构元素 - Mat cv::getStructuringElement

函数原型:
1
2
3
Mat getStructuringElement(
int shape, Size esize, Point anchor = Point(-1, -1)
);
  • shape: 表示内核的形状
    • MORPH_RECT: 矩形
    • MORPH_CROSS: 交叉形
    • MORPH_ELLIPSE: 椭圆形
  • esize & anchor: 内核的尺寸以及锚点的位置,默认值Point(-1,-1)表示位于中心。
  • 一般在调用膨胀/腐蚀函数dilateerode之前,先定义一个Mat类型的变量来获得该函数的返回值,作为膨胀/腐蚀函数的膨胀操作内核输入。

膨胀函数 - cv::dilate()

使用像素邻域内的局部极大运算符来膨胀一张图片,从src输入, 由dst输出。

函数原型
1
2
3
4
5
6
7
8
9
void dilate(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
  • src: 输入源图像,Mat类即可
  • dst: 和源图像有相同尺寸和类型的目标图像
  • kernel: 膨胀操作的内核,当为NULL时,表示的是使用参考点位于中心$3\times 3$的核。一般使用函数Mat getStructuringElement配合这个参数使用。
  • anchor: 锚点位置,默认值表示位于中心
  • iterations: 迭代使用dilate()函数的次数,默认为1次
  • borderType: 用于推断图像外部像素的某种边界模式,有默认值,可以不考虑
  • borderValue: 当边界为常数时的边界值,有默认值,一般不去考虑
  • 使用膨胀函数,一般只需要填前面三个参数,后面四个都有默认值。

腐蚀函数 - cv::erode()

使用像素邻域内的局部极小运算符来腐蚀一张图片,从src输入, 由dst输出。

函数原型
1
2
3
4
5
6
7
8
9
void erode(
InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);

latex

  • 摄氏度:^{\circ}C
  • equation环境中斜体变直体:{\rm T}
  • 空行:~\\
  • equation环境中输入中文:mbox{中文}
  • 并排图片(子图片)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
\begin{figure}[!htbp]
\centering
\subfigure[name]{
\includegraphics[width=]{path/to/your/image}
\title{}
\label{}
}
\subfigure[name]{
\includegraphics[width=]{path/to/your/image}
\title{}
\label{}
}
\caption
\label{}
\end{figure}
  • 电脑装了Visual Studio如果直接在vscode中”cmake …”会生成VS的工程文件,所以这里需要指定下。
1
2
3
mkdir build
cd build
cmake -G "Unix Makefiles" ../

python异常机制
numpy中的ndim / shape/ dtype/ astype方法
  • ndim 返回数组维度(int)
  • shape 返回各维度大小的元组(元组)
  • dtype 返回该数组的数据类型(整型返回int32,有小数点返回float64)
  • astype 转换数组的数据类型
    • int32 —> float64
    • float64 —> int32 小数部分被截断
    • string —> float64 如果字符串数组表示的全是数字,也可以用astype转化为数值类型
numpy.transpose(a, axes=None)
  • 重置数组的维度
  • 参数:a<输入数组>;axes<整数列表>默认情况下,反转维度,否则根据给定的值对维度进行排列。
  • 返回值:修改维度后的a
PIL.Imagenumpy.array之间的相互转换
1
2
3
4
5
6
from PIL import Image

image = Image.open('path/to/image')
img = numpy.array(image)
# 图像处理
image = Image.fromarray(img.astype('uint8')).convert('RGB')
array[::-1,:,:] 逆序
numpy.flatten(): 多维数组变成一维数组
numpy.mean(array, axes)
中心化与标准化
  • 中心化(又叫零均值化)zero-centered 或者 Mean-subtraction
  • 标准化(又叫归一化)Standardization 或者 Normalization
    • 意义:数据中心化和标准化在回归分析中是取消由于量纲不同、自身变异或者数值相差较大所引起的误差。
    • 原理
      • 数据标准化是指变量减去均值,再除以标准差
      • 数据中心化是指变量减去均值
    • 目的:通过中心化和标准化处理,得到均值为0,标准差为1的服从标准正态分布的数据。在训练神经网络的过程中,通过将数据标准化,能够加速权重参数的收敛;对数据进行中心化预处理,能够增加基向量的正交性
1
2
3
4
5
mean = np.array([np.mean(image[0]),np.mean(image[1]),np.mean(image[2])])

std = np.array([np.std(image[0],ddof=1),np.std(image[1],ddof=1),np.std(image[2],ddof=1)])

np.std(array, ddof=1) # 最后的参数一定要加!!!
  • caffe与PyTorch的图像预处理不同。caffe2中图像的通道与OpenCV相同,是BGR格式,标准化到0-255,PyTorch中图像是RGB格式,标准化到0-1。
numpy.random.get_state() & numpy.random.set_state()
  • 功能:获取/设置随机生成器np.random的状态
  • 作用:具有相同state的随机生成器(random)的随机效果相同。随机生成器random,每执行一次,random的状态(state)就会变化一次,所以每次产生的随机数都不同,或随机操作的效果都不同。而当random的状态(state)不变时,多次执行random的同一操作具有相同的效果。
  • 用途:
    • 通过设置相同的state,使得两次生成的随机数相同
    • 通过设置相同的state,使得random.shuffle以相同的规律打乱两个列表,进而使得两个列表被打乱后,仍旧能维持两个列表间元素的一一对应关系。这一点在深度学习的标注数据集的打乱的过程中很有用。一一对应的image_list 与label_list,在分别打乱后,仍能维持一一对应的关系。
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np

images_list=[1,2,3,4,5,6,7,8,9]
labels_list=[1,2,3,4,5,6,7,8,9]

state = np.random.get_state()
np.random.shuffle(images_list)
np.random.set_state(state)
np.random.shuffle(labels_list)

print(images_list)
print(labels_list)
cv::RotatedRect

这是一个存储旋转矩形的类,通常用来存储最小外接矩形函数minAreaRect()和椭圆拟合函数fitEllipse()返回的结果。它具有三个属性:

  • 矩形中心(质心):const Point2f &center
  • 边长(长和宽):const Size2f &size
  • 旋转角度:float angle

参数angle从平行于x轴射线出发,逆时针为负,顺时针为正。逆时针旋转碰到的第一条边的边长即为width