WiringPi简介

WiringPi是应用于树莓派平台的GPIO控制库函数,WiringPi遵守GUN Lv3。wiringPi使用C或者C++开发并且可以被其他语言包转,例如python、ruby或者PHP等。WiringPi中的函数类似于Arduino的wiring系统,这使得熟悉arduino的用户使用wringPi更为方便。

树莓派具有26个普通输入和输出引脚。在这26个引脚中具有8个普通输入和输出管脚,这8个引脚既可以作为输入管脚也可以作为输出管脚。除此之外,树莓派还有一个2线形式的I2C、一个4线形式的SPI和一个UART接口。树莓派上的I2C和SPI接口也可以作为普通端口使用。如果串口控制台被关闭便可以使用树莓派上的UART功能。如果不使用I2C,SPI和UART等复用接口,那么树莓派总共具有8+2+5+2 =17个普通IO。

wiringPi包括一套gpio控制命令,使用gpio命令可以控制树莓派GPIO管脚。用户可以利用gpio命令通过shell脚本控制或查询GPIO管脚。wiringPi是可以扩展的,可以利用wiringPi的内部模块扩展模拟量输入芯片,可以使用MCP23x17/MCP23x08(I2C 或者SPI)扩展GPIO接口。另外可通过树莓派上的串口和Atmega(例如arduino等)扩展更多的GPIO功能。另外,用户可以自己编写扩展模块并把自定义的扩展模块集成到wiringPi中。WiringPi支持模拟量的读取和设置功能,不过在树莓派上并没有模拟量设备。但是使用WiringPi中的软件模块却可以轻松地应用AD或DA芯片。

I2C

I²C(Inter-Integrated Circuit)字面上的意思是集成电路之间,它其实是I²C Bus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。I²C的正确读法为“I平方C”(”I-squared-C”),而“I二C”(”I-two-C”)则是另一种错误但被广泛使用的读法。自2006年10月1日起,使用I²C协议已经不需要支付专利费,但制造商仍然需要付费以获取I²C从属设备地址。

设计说明

I²C只使用两条双向漏极开路(Open Drain)(串行数据(SDA)及串行时钟频率(SCL))并利用电阻将电位上拉。I²C允许相当大的工作电压范围,但典型的电压准位为+3.3V或+5v。

I²C的参考设计使用一个7比特长度的地址空间但保留了16个地址,所以在一组总线最多可和112个节点通信[a]。常见的I²C总线依传输速率的不同而有不同的模式:标准模式(100 Kbit/s)、低速模式(10 Kbit/s),但时钟频率可被允许下降至零,这代表可以暂停通信。而新一代的I²C总线可以和更多的节点(支持10比特长度的地址空间)以更快的速率通信:快速模式(400 Kbit/s)、高速模式(3.4 Mbit/s)。

虽然最大的节点数目是被地址空间所限制住,但实际上也会被总线上的总电容所限制住,一般而言为400 pF。

I²C通信

如上所述,参考设计为使用串行数据线(SDA)和串行时钟线(SCL)、拥有7bit寻址空间的总线。 总线上有两种类型角色的节点:

  • 主节点 - 产生时钟并发起与从节点的通信
  • 从节点 - 接收时钟并响应主节点的寻址

该总线是一种多主控总线,即可以在总线上放置任意多主节点。此外,在停止位(STOP)发出后,一个主节点也可以成为从节点,反之亦然。

总线上有四种不同的操作模式,虽然大部分设备只作为一种角色和使用其中两种操作模式:

  • 主节点发送 - 主节点发送数据给从节点
  • 主节点接收 - 主节点接收从节点数据
  • 从节点发送 - 从节点发送数据给主节点
  • 从节点接收 - 从节点接收主节点数据

一开始,主节点处于主节点发送模式,发送起始位(START),跟着发送希望与之通信的从节点的7bit位地址,最后再发送一个bit读写位,该数据位表示主节点想要与从节点进行读(1)还是写(0)操作。

如果从节点在总线上,它将以ACK字符比特位应答(低有效)该地址。主节点收到应答后,根据它发送的读写位,处于发送模式或者接收模式,从节点则处于对应的相反模式(接收或发送)。

地址和数据首先发送最高有效位。 起始位在SCL位高时,由SDA上电平从高变低表示;停止位在SCL为高时,由SDA上电平从低变高表示。其他SDA上的电平变化在SCL为低时发生。

如果主节点想要向从节点写数据,它将发送一个字节,然后从节点以ACK位应答,如此重复。此时,主节点处于主节点发送模式,从节点处于从节点接收模式。

如果主节点想要读取从节点数据,它将不断接收从节点发送的一个个字节,在收到每个字节后发送ACK进行应答,除了接收到的最后一个字节。此时,主节点处于主节点接收模式,从节点处于从节点发送模式。

此后,主节点要么发送停止位终止传输,要么发送另一个START比特以发起另一次传输(即“组合消息”)。

应用

I²C被应用在简单且其制造成本较传输速度更为重要的外设上。一些常见的应用如下:

  • 为了保存用户的设置而访问NVRAM芯片。
  • 访问低速的数字模拟转换器(DAC)。
  • 访问低速的模拟数字转换器(ADC)。
  • 改变监视器的对比度、色调及色彩平衡设置(视频数据通道)。
  • 改变音量大小。
  • 获取硬件监视及诊断数据,例如中央处理器的温度及风扇转速。
  • 读取实时时钟(Real-time clock)。
  • 在系统设备中用来打开或关闭电源供应。

I²C的另一个强大用途在于微控制器的应用,利用两根通用的输入输出接脚及软件的规划,可以让微控制器控制一个小型网络。

外设可以在系统仍然在运作的同时加入或移出总线,这代表对于有热插拔需求的设备而言是个理想的总线。

像I²C这样的总线之所以流行起来,是因为计算机工程师发现到对于集成电路设计而言,许多的制造成本源自于封装尺寸及接脚数量。更小的包装通常能够减少重量及电源的消耗,这对于移动电话及手持式计算机而言格外重要。

UART

在通信和计算机科学中,Serial communication是一个通用概念,泛指所有的串行的通信协议,如RS232、USB、I2C、SPI、1-Wire、Ethernet等。这里的串行(serial),是相对并行通信(parallel communication)来说的,如下图:

串行与并行通信

理解串行通信的概念之后,大家可能会有疑问:接收方接收到一长串的、表示0/1电平跳变的信号之后,怎么还原出有效的信息呢?有两种方法:

  • 发送端在发送串行数据的同时,提供一个时钟信号,并按照一定的约定(例如在时钟信号的上升沿的时候,将数据发送出去)发送数据,接收端根据发送端提供的时钟信号,以及大家的约定,接收数据。这就是常说的同步串行通信(Synchronous serial communication),I2C、SPI等有时钟信号的协议,都属于这种通信方式。本文不再详述。

  • 发送端在数据发送之前和之后,通过特定形式的信号(例如START信号和STOP信号),告诉接收端,可以开始(或者停止)接收数据了。与此同时,收发两方会约定一个数据发送的速度(就是大名鼎鼎的波特率),发送端在发送START信号之后,就按照固定的节奏发送串行数据,与此同时,接收端在收到START信号之后,也按照固定的节奏接收串行数据。这就是常说的异步串行通信(Asynchronous serial communication),我们本节的主角—-串口通信,就是这种通信方式。

UART(Universal Asynchronous Receiver/Transmitter) 即是规定编码格式、bit rate,产生通信所需的bit流的标准。

SPI

串行外设接口(Serial Peripheral Interface Bus,SPI),是一种用于短程通信的同步串行通信接口规范,主要应用于单片机系统中。类似I²C。 这种接口首先被Motorola(摩托罗拉)公司开发,然后发展成了一种行业规范。典型应用包含SD卡和液晶显示器。 SPI设备之间使用全双工模式通信,包含一个主机和一个或多个从机。主机产生待读或待写的帧数据,多个从机通过一个片选线路 决定哪个来响应主机的请求。 有时SPI接口被称作四线程接口,SPI准确来讲称为同步串行接口,但是与同步串行接口协议(SSI)不同,SSI是一个四线程 同步通信协议,但是使用差分信号输入同时仅提供一个单工通信信道。

接口

SPI总线规定了4个保留逻辑信号接口:

  • SCLK(Serial Clock):串列时脉,由主机发出
  • MOSI(Master Output,Slave Input):主机输出从机输入信号,由主机发出
  • MISO(Master Input,Slave Output):主机输入从机输出信号,由从机发出
  • SS(Slave Selected):选择信号,由主机发出,一般是低电位有效

尽管上面的引脚名称是最常用的,但在过去,有时会使用其他引脚命名约定,因此旧IC产品的SPI端口引脚名称可能有所不同。

1-Wire

1-Wire是Maxim子公司达拉斯半导体的专利技术,仅用单一信号线就可像I²C、SPI一样,传输时钟(clock)又传输数据(data),并且数据传输是双向的。1-Wire使用较低的数据传输速率,通常是用来沟通小型设备,如数字温度计。1-Wire有两种速率:标准模式16kbps,驱动模式142kbps。

单总线只有一根数据线。设备主机或从机通过一个漏极开路或三态端口连接至该数据线,这样允许设备在不发送数据时释放数据总线,以便总线被其它设备所使用。单总线端口为漏极开路其内部等效电路如下图所示。

单总线硬件接口示意图

参考文献

  1. 树莓派学习笔记——wiringPi简介、安装和管脚说明 , by xukai871105.
  2. I²C, by wikipedia.
  3. UART、RS232、TTL关系浅析, by 老狼.
  4. 串行外设接口,by wikipedia.
  5. 1-Wire,by wikipedia.
  6. 1-Wire单总线的基本原理,by ce123.
  7. 解析单总线协议(1-wire),by zhengqijun_.

MAVLink(Micro Air Vehicle Link,微型空中飞行器链路通讯协议)是无人飞行器与地面站之间通讯,以及无人飞行器之间通讯最常用的协议。它已经在PX4、APM、PIXHAWK和Parrot AR.Drone飞控平台上进行了大量测试。

QGroundControl则是一种操纵基于MAVLink通信协议的无人机的跨平台地面站开源软件。下面记录在Debian Linux下从源码编译QGroundControl的过程。

下载源码

1
2
3
4
# 下载QGroundControl源码
git clone --recursive https://github.com/mavlink/qgroundcontrol.git
# 更新子模块
git submodule update

安装编译环境

  • 下载Qt社区版在线安装器,安装5.11.0版本的Qt,安装路径可在/opt下。
1
2
3
4
# 注意要选择安装5.9+以上版本的Qt,因为构建QGC时需要
# 运行qtcreater
$ cd /opt/Qt/Tools/QtCreator/bin/
$ ./qtcreator
  • 安装必要的包
1
sudo apt-get install speech-dispatcher libudev-dev libsdl2-dev
  • 解决编译时libQt5PositioningQuick.so.5不存在的bug
1
2
3
sudo apt-get install libqt5positioningquick5
sudo find /usr/ -name libQt5PositioningQuick.so.5
cp /usr/lib/x86_64-linux-gnu/libQt5PositioningQuick.so.5 /opt/Qt/5.10.0/gcc_64/lib/libQt5PositioningQuick.so.5
  • 将当前用户添加到dialout组,获取串口访问权限
1
2
# 运行QGroundControl需要当前用户拥有串口访问权限
sudo usermod -a -G dialout $USER

编译运行

打开Qt Creater,打开qgroundcontrol.pro工程,构建后运行,即可打开QGroundControl地面站软件。

参考链接

  1. https://blog.csdn.net/hebbely/article/details/79022799, by hebbely
  2. https://dev.qgroundcontrol.com/en/getting_started/, by Dronecode

记录一些常用的linux命令用法,以备查询。

文件管理

校验文件

下载的文件最好校验完整性,防止被人篡改。以sha256sum为例:

1
2
3
4
5
6
7
8
9
# 以下命令将生成树莓派映像的sha256哈希码,从树莓派官网复制该映像sha256哈希码,以便校验。
# 当然通常应该会提供映像的哈希码校验文件。

sha256sum 2018-10-09-raspbian-stretch.zip >2018-10-09-raspbian-stretch.zip.sha256sum

# 使用下面校验文件的完整性,如果成功则映像与官方一致,未被篡改。
# 注意被校验文件与校验文件应放在同一个目录。

sha256sum -c 2018-10-09-raspbian-stretch.zip.sha256sum

转换和复制文件命令

Linux的dd命令用于复制文件并对原文件的内容进行转换和格式化处理。

1
2
3
4
5
6
7
8
9
10
11
读指定物理扇区:
dd if=<源设备> of=<输出设备或文件> skip=<指定扇区值> bs=512 count=1

写指定物理扇区:
dd if=<输入设备或文件> of=<输出设备> seek=<指定扇区值> bs=512 count=1

读取sd启动扇区示例:
dd if=/dev/mmcblk0 of=mbrsd.data bs=512 count=1

制作光盘iso镜像
dd if=/dev/cdrom of=/home/hch/drone.iso status=progress conv=fsync

查找文件

1
2
3
4
5
# find基本语法:find [PATH] [option] [action]

find /usr/lib -name libQt5Xml.so
# 使用通配符
find /usr/lib -name "*ssl*"

查找文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# grep基本用法:
grep "let's find something" file.[txt,json,js,md,etc]

# 大小写不敏感搜索
grep -i "REact" compiler/apps/playground/app/index.tsx
grep -i "Operation not supported on socket" system.log

# 多模式搜索
grep -e "error" -e "404" system.log

# 统计字符串匹配次数
grep -c "React" compiler/apps/playground/app/index.tsx

# 文件夹递归搜索,-o 仅输出匹配行,-r 递归搜索目录及其子目录
grep -o -r "fs" node_modules | wc -l

批量处理指定文件

1
2
3
4
5
6
7
8
# Find all .txt files and delete them
find . -name "*.txt" | xargs rm

# Creates each directory listed in the file.
cat dirs.txt | xargs mkdir

# Compresses all .log files in the current directory
ls *.log | xargs gzip

批量转换文件格式

1
2
3
4
5
6
7
# 将png格式图像转换为jpg
# -1 – 告诉 ls 每行列出一个图像名称的选项标识
# -n – 指定最多参数个数,例子中为 1
# -c – 指示 bash 运行给定的命令
# ${0%.png}.jpg – 设置新转换的图像文件的名字,% 符号用来删除源文件的扩展名

ls -1 *.png | xargs -n 1 bash -c 'convert "$0" "${0%.png}.jpg"'

终端下载

1
2
3
4
5
6
7
8
9
10
11
12
# 逐条下载uri.txt文件中每一行uri
wget -i uri.txt

# 跳过前1000条再下载
awk 'NR>=1000' url.txt | wget -i -

# install proxy
wget --no-check-certificate https://raw.githubusercontent.com/jwchenzju/teddysunss/master/shadowsocks.sh

chmod +x shadowsocks.sh

./shadowsocks.sh 2>&1 | tee shadowsocks.log

终端中打开文件管理器

1
2
使用gnome文件管理器打开当前文件夹
nautilus ./

统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 统计文件行数
wc -l file

统计某文件夹下文件的个数
ls -l |grep "^-"|wc -l

统计某文件夹下目录的个数
ls -l |grep "^d"|wc -l

统计文件夹下文件的个数,包括子文件夹里的
ls -lR|grep "^-"|wc -l

# 统计文件或文件夹大小
du -a -h -d 1 ./

# 统计文件状态信息
stat file.txt

压缩和解压文件

1
2
3
4
5
6
7
# tar命令
tar zxvf FileName.tar #解压
tar czvf FileName.tar DirName #压缩

# zip命令
unzip FileName.zip #解压
zip -r FileName.zip DirName #压缩

SSH 连接、远程上传下载文件

1
2
3
4
5
6
7
8
9
10
11
# SSH 远程登入 Ubuntu 机 
ssh username@192.168.0.1

# 将 文件/文件夹 从远程 Ubuntu 机拷至本地(scp)
scp -r username@192.168.0.1:/home/username/remotefile.txt remotefile.txt

# 将 文件/文件夹 从本地拷至远程 Ubuntu 机(scp)
scp -r localfile.txt username@192.168.0.1:/home/username/

# rsync大文件断电续传,远程服务器需安装rsync
rsync -P --rsh=ssh root@192.168.0.1:/root/fgdata.tar fgdata.tar

系统管理

修改用户

1
2
# 将用户$USER添加到dialout用户组,以获取串口访问权限
sudo usermod -a -G dialout $USER

特殊符号用法

1
2
3
4
5
6
7
8
9
#| 管道 (pipeline),是 UNIX 系统,基础且重要的观念。连结上个指令的标准输出,做为下个指令的标准输入。
who | wc -l

#! 惊叹号(negate or reverse),通常它代表反逻辑的作用,譬如条件侦测中,用 != 来代表"不等于"
#下例代表显示除了a0, a1 .... a9 这几个文件的其他文件。
ls a[!0-9]

#& 后台工作,单一个& 符号,且放在完整指令列的最后端,即表示将该指令列放入后台中工作。
tar cvfz data.tar.gz data > /dev/null &

系统服务管理

1
2
3
4
5
# service命令用于对系统服务进行管理,比如启动(start)、停止(stop)、重启(restart)、查看状态(status)等。
# service命令本身是一个shell脚本,它在/etc/init.d/目录查找指定的服务脚本,然后调用该服务脚本来完成任务。

# 查看系统所有服务状态
service --status-all

查询本机公网IP

1
2
curl ifconfig.me
curl ipinfo.io

查看环境变量

1
export

查看端口占用情况

1
2
3
4
5
6
7
8
lsof -i:8080:查看8080端口占用

netstat -tunlp | grep 端口号
-t (tcp) 仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化为数字
-l 仅列出在Listen(监听)的服务状态
-p 显示建立相关链接的程序名

Vim使用方法

  • 正向搜索字符串

在普通模式下,按下 / 键,然后输入你要查找的字符串,最后按下 Enter 键。

1
/function
  • 反向搜索字符串

与正向查找相似,使用 ? 键进行反向查找。

1
?error
  • 替换字符串

在命令模式下,替换字符串。

1
:%s/apple/orange/gc

参考链接

  1. 初窥Linux 之 我最常用的20条命令,by ljianhui.
  2. Linux的五个查找命令,by 阮一峰.
  3. shell脚本中一些特殊符号, by 阿笨猫.
  4. vultr proxy
  5. proxychains配置,by Verne.
  6. 10 Essential Terminal Commands Every Developer Should Know,by Trevor I. Lasn.
  7. Vim 查找字符串(超详细),by quanxiaoha.

近期研究目标对象检测和识别,发现谷歌开源的基于tensorflow的object detection api模型效果不错,于是git clone下来测试一下。下面记录我在debian linux上安装配置object detection api模型,构建自定义数据集,训练和测试object detection api模型的过程,以及整个过程中遇到的一下问题,需要注意的事项。

准备工作

docker安装

TensorFlow 程序在 GPU 上的运行速度通常要比在 CPU 上快得多,在系统满足NVIDIA 软件要求的前提下,推荐使用支持 GPU 的 TensorFlow。

官方推荐使用Docker简化TensorFlow的GPU支持配置,这样只需要linux主机安装好Nvidia GPU驱动即可。

  1. 安装docker
    安装docker的方法可参考链接1。

  2. 安装nvidia-docker

1
2
3
4
5
6
7
8
9
# Add the package repositories
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/debian9/nvidia-docker.list | \
sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update

# Install nvidia-docker2 and reload the Docker daemon configuration
sudo apt-get install -y nvidia-docker2
sudo service docker restart
  1. 下载最新支持GPU和Python3的tensorflow映像[2]
1
docker pull tensorflow/tensorflow:latest-gpu-py3
  1. 测试tensorflow映像
1
2
docker run --runtime=nvidia -it --rm tensorflow/tensorflow:latest-gpu-py3 \
python -c "import tensorflow as tf; print(tf.contrib.eager.num_gpus())"

下载TFModel库及其相关库

1
2
3
4
# 基于tensorflow的模型和例子
git clone https://github.com/tensorflow/models.git
# raccoon数据集,可参考其中生成TFRecord格式数据的方法
git clone https://github.com/datitran/raccoon_dataset.git

安装Python虚拟环境管理工具

1
2
3
4
# 具体安装配置过程参见链接3
sudo pip3 install virtualenv
sudo pip3 install virtualenvwrapper
mkvirtualenv object-detection --python=/usr/bin/python3# 创建python3虚拟环境

数据标注

以分类几何形状为例,收集相关图片后,需要对它们进行标注。推荐使用 LabelImg 进行标注,生成的文件是 PASCAL VOC 的 xml 格式。这个工具还可以加载标注文件,检查标注结果[3]。

1
2
3
4
5
6
7
8
9
git clone https://github.com/tzutalin/labelImg.git
workon object-detection
# 启动python3虚拟环境
workon object-detection
# 安装配置labelImg
sudo apt-get install pyqt5-dev-tools
sudo pip3 install -r requirements/requirements-linux-python3.txt
make qt5py3
python3 labelImg.py

除了标注图片,还需创建一个 .pbtxt 文件用来说明标注的分类。例如:

1
2
3
4
5
6
7
8
9
10
11
12
item {
id: 1
name: 'circle'
}
item {
id: 2
name: 'square'
}
item {
id: 3
name: 'triangle'
}

需要特别注意以下两点:

  • name 不支持直接写中文,需要 UTF-8 编码
  • id 从 1 开始编号,不能从 0 开始编号。

数据准备

标注好的数据是图片文件(.jpg)和标注文件(.xml),而 TensorFlow 不能直接用这些数据作为输入,还需要转成 TFRecord 格式。可采用两种方法生成TFRecord格式数据:

  • tensorflow/models中方法

项目中使用create_pascal_tf_record.py, create_pet_tf_record.py生成TFrecord 格式数据

  • raccoon_dataset中方法

项目中使用xml_to_csv.py把xml合并成一个CSV文件,使用split labels.ipynb 随机划分训练集和测试集,以及使用generate_tfrecord.py 生成相对应的 TFRecord 训练集和测试集。

1
2
3
4
5
6
7
8
9
workon object-detection
# 将生成geometry_labels.csv
python xml_to_csv.py
# 打开split labels.ipynb生产训练集train_labels.csv和测试集test_labels.csv
jupyter notebook
# 创建训练用TFRecord文件:
python generate_tfrecord.py --csv_input=data/train_labels.csv --output_path=training/geometry_train.record
# 创建测试用TFRecord文件:
python generate_tfrecord.py --csv_input=data/test_labels.csv --output_path=training/geometry_test.record

第二种方法比较直观,因此我采用第二种方法生产TFRecord数据。

安装配置

安装TFModel依赖

1
2
3
4
5
6
7
8
9
10
11
12
workon object-detection
# For CPU
pip install tensorflow
# For GPU
pip install tensorflow-gpu

pip install --user Cython
pip install --user contextlib2
pip install --user pillow
pip install --user lxml
pip install --user jupyter
pip install --user matplotlib

安装COCO API

1
2
3
4
git clone https://github.com/cocodataset/cocoapi.git
cd cocoapi/PythonAPI
make
cp -r pycocotools <path_to_tensorflow>/models/research/

编译Protobuf

1
2
3
4
5
6
# From tensorflow/models/research/
wget -O protobuf.zip https://github.com/google/protobuf/releases/download/v3.0.0/protoc-3.0.0-linux-x86_64.zip
unzip protobuf.zip

# From tensorflow/models/research/
./bin/protoc object_detection/protos/*.proto --python_out=.

添加库到PYTHONPATH

1
2
3
# From tensorflow/models/research/
# 每次调用TFModel的Object Detection API之前都要设置
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

安装测试

1
2
# if all tests is ok, the installation is no problem.
python object_detection/builders/model_builder_test.py

模型训练

数据准备

  1. 将label_map文件、训练用TFRecord文件、测试用TFRecord文件复制到tensorflow/models/research/object_detection/data文件夹下。
1
2
3
4
5
# 推荐的数据目录结构
+ data
- geometry.pbtxt
- geometry_test.record
- geometry_train.record
  1. 下载COCO预训练模型用于迁移学习
1
2
3
# From tensorflow/models/research/object-detection
wget http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_2018_01_28.tar.gz
tar -xvf ssd_mobilenet_v1_coco_2018_01_28.tar.gz
  1. 修改解压后模型文件夹中pipeline.config

解压ssd_mobilenet_v1_coco_2018_01_28模型后会看到一个 .config 文件,里面包含有模型的参数,训练的参数,评估的参数等。这里需要修改到的有,

  • 模型参数中的 num_classes,改成你的类别数,
  • 训练参数中的 fine_tune_checkpoint,采用迁移学习,这里路径的指向刚才下载的Pre-train模型,比如 ssd_mobilenet_v1_coco_11_06_2017/model.ckpt
  • train_input_reader 下面的 input_path,改成你的训练数据,例如 data/train.record。label_map_path,改成你的 pbtxt 文件路径,例如 data/object.pbtxt
  • eval_input_reader 下面的 input_path,也需要改成你的测试集,例如 data/test.record。同样,label_map_path,也改成你的 pbtxt 文件路径,例如 data/object.pbtxt
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
//pipeline.config修改示例
model {
ssd {
num_classes: 3
...
}
}
train_config {
...
fine_tune_checkpoint: "object_detection/ssd_mobilenet_v1_coco_2018_01_28/model.ckpt"
from_detection_checkpoint: true
num_steps: 50000
}
train_input_reader {
label_map_path: "object_detection/data/geometry.pbtxt"
tf_record_input_reader {
input_path: "object_detection/data/geometry_train.record"
}
}
eval_input_reader {
label_map_path: "object_detection/data/geometry.pbtxt"
shuffle: false
num_epochs: 1
num_readers: 1
tf_record_input_reader {
input_path: "object_detection/data/geometry_test.record"
}
sample_1_of_n_examples: 1
}

训练数据

在GPU上训练TFModel,与在CPU上训练TFModel相比,要快五倍左右,因此推荐在GPU上训练TFModel。

  1. 启动docker
1
2
# 启动docker,并使用-v参数将目录/home/$USER挂载到容器上
docker run --runtime=nvidia -v /home/$USER:/home/$USER -it tensorflow/tensorflow:latest-gpu-py3 bash
  1. 执行训练
1
2
3
4
# From tensorflow/models/research/
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim
# 开始训练
python object_detection/model_main.py --pipeline_config_path=object_detection/ssd_mobilenet_v1_coco_2018_01_28/pipeline.config --model_dir=object_detection/ssd_mobilenet_v1_coco_2018_01_28/saved_model/ --num_train_steps=50000 --alsologtostderr
  1. 使用tensorboard查看训练进度
1
2
# From tensorflow/models/research/
tensorboard --logdir=object_detection/ssd_mobilenet_v1_coco_2018_01_28/saved_model/

在CPU上训练只需执行第二步和第三步。

导出模型

1
2
# From tensorflow/models/research/
python object_detection/export_inference_graph.py --input_type=image_tensor --pipeline_config_path=object_detection/ssd_mobilenet_v1_coco_2018_01_28/pipeline.config --trained_checkpoint_prefix=object_detection/ssd_mobilenet_v1_coco_2018_01_28/saved_model/model.ckpt-50000 --output_directory=../../../../ssd_mobilenet_v1_coco_2018_01_28

运行完命令后模型就导出到 ssd_mobilenet_v1_coco_2018_01_28 文件夹中,其中的frozen_inference_graph.pb即是所需模型。 需要注意的是,参数中的 –trained_checkpoint_prefix 是需要指定到单个模型的,例如 model.ckpt-50000,这个50000就是训练了 50000 步后自动保存模型。

参考文献

  1. https://huangwang.github.io/2018/10/18/Debian-Linux下安装Docker的方法/, by jack huang
  2. https://www.tensorflow.org/install/docker?hl=zh-cn , by tensorflow.
  3. https://huangwang.github.io/2018/10/09/Virtualenv简易教程/ , by jack huang
  4. https://laddiexu.github.io/tech/2017/11/04/TF-ODYourData.html , by 菁菁者莪
  5. https://blog.csdn.net/xunan003/article/details/78720189?utm_source=blogxgwz2, by xunan003

Docker是一个开放源代码软件项目,让应用程序布署在软件容器下的工作可以自动化进行,借此在Linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制。

Docker与传统虚拟机如virtualbox、vmware相比,占用资源少,更加轻便,启动快,更适用于解决软件环境配置难题。

基本概念

  1. 镜像

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

  1. 容器

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

  1. 仓库

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

使用方法

操作镜像

获取镜像

Docker Hub 上有大量的高质量的镜像可以用,使用docker pull命令拉取镜像。

1
2
3
4
// 拉取镜像
$ docker pull ubuntu:16.04
// 以该镜像启动容器
$ docker run -it --rm ubuntu:16.04 bash

docker run 就是运行容器的命令,其参数含义如下:

  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • –rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。
  • ubuntu:16.04:这是指用 ubuntu:16.04 镜像为基础来启动容器。
  • bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash。

列出镜像

1
docker image ls

删除镜像

删除本地镜像格式如下:

1
docker image rm [选项] <镜像1> [<镜像2> ...]

以删除hello-world镜像为例:

1
docker image rm hello-world

操作容器

启动容器

1
2
3
4
// 新建并启动容器
docker run ubuntu:14.04 /bin/echo 'Hello world'
// 启动已终止容器
docker container start

后台运行

1
2
3
4
5
6
7
// 后台运行容器
$ docker run -d ubuntu:17.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"
// 通过 docker container ls 命令来查看容器信息
$ docker container ls

// 通过 docker container logs 命令获取容器的输出信息
$ docker container logs [container ID or NAMES]

终止容器

1
docker container stop

进入容器

在使用 -d 参数时,容器启动后会进入后台。

某些时候需要进入容器进行操作,包括使用 docker attach 命令或 docker exec 命令,推荐大家使用 docker exec 命令。

1
2
3
4
$ docker run -dit ubuntu
$ docker container ls
$ docker exec -i 69d1 bash
$ docker exec -it 69d1 bash

如果从这个 stdin 中 exit,不会导致容器的停止。这就是为什么推荐大家使用 docker exec 的原因。

删除容器

1
2
3
4
5
// 删除一个处于终止状态的容器
$ docker container rm trusting_newton

// 清理所有处于终止状态的容器
docker container prune

参考文献

  1. Docker 从入门到实践,by yeasy.
  2. Docker 入门教程 ,by 阮一峰
  3. Docker ,by wikipedia.
  4. Dockerfile 最佳实践,by showyoui.

Docker是一个开放源代码软件项目,让应用程序布署在软件容器下的工作可以自动化进行,借此在Linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制。

Docker利用Linux核心中的资源分离机制,例如cgroups,以及Linux核心名字空间(name space),来创建独立的软件容器(containers)。这可以在单一Linux实体下运作,避免启动一个虚拟机造成的额外负担。Linux核心对名字空间的支持完全隔离了工作环境中应用程序的视野,包括进程树、网上、用户ID与挂载文件系统,而核心的cgroup提供资源隔离,包括CPU、存储器、block I/O与网上。

下面即记录在Debian Linux下按照Docker社区版的方法。

前期准备

添加Docker的pgp key。

1
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -

配置Docker的Apt仓库。

1
echo 'deb https://download.docker.com/linux/debian stretch stable' | sudo tee /etc/apt/sources.list.d/docker.list

更新Apt仓库

1
sudo apt-get update

安装Docker

1
2
3
4
5
6
// 清除之前安装的Docker版本
apt-get remove docker docker-engine docker.io
// 在安装最新的Docker社区版
apt-get install docker-ce
// 测试docker
docker run hello-world

以非root用户管理docker

1
2
sudo groupadd docker
sudo usermod -aG docker $USER

参考文献

  1. https://zh.wikipedia.org/wiki/Docker ,by wikipedia.

TensorFlow™ 是一个开放源代码软件库,用于进行高性能数值计算。借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU、GPU、TPU)和设备(桌面设备、服务器集群、移动设备、边缘设备等)。TensorFlow™ 最初是由 Google Brain 团队(隶属于 Google 的 AI 部门)中的研究人员和工程师开发的,可为机器学习和深度学习提供强力支持,并且其灵活的数值计算核心广泛应用于许多其他科学领域。

tensorflow入门

tensorflow实现机器学习的基本步骤如下:

  1. 定义模型,建立数据流图
  2. 定义loss,并指定优化器
  3. 传入数据并进行训练
  4. 使用测试集进行评测

通用代码框架

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
import tensorflow as tf

# 初始化变量和模型参数,定义训练闭环中的运算

def inference(X):
# 计算推断模型在数据X上的输出,并将结果返回

def loss(X,Y):
# 依据训练数据X及其期望输出Y计算损失

def inputs():
# 读取或生成训练数据X及其期望输出Y

def train(total_loss):
# 依据计算的总损失训练或调整模型参数

def evaluate(sess,X,Y):
# 对训练得到的模型进行评估

# 在一个会话对象中启动数据流图,搭建流程
with tf.Session() as sess:
tf.initialize_all_variables().run()

X,Y=inputs()

total_loss=loss(X,Y)
train_op=train(total_loss)

coord=tf.train.Coordinator()
threads=tf.train.start_queue_runners(sess=sess,coord=coord)

# 实际的训练迭代次数
training_steps=1000
for step in range(training_steps):
sess.run([train_op])
# 出于调试和学习的目的,查看损失在训练过程中递减的情况
if step % 10 =0:
print "loss: ",sess.run([total_loss])

evaluate(sess,X,Y)

coord.request_stop()
coord.join(threads)
sess.close()

保存训练检查点

借助tf.train.Saver类可创建检查点文件,将数据流图中变量保存至其中。修改后框架如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 模型定义代码
# 创建一个Saver对象
saver=tf.train.Saver()

# 在会话对象中启动数据流图,搭建流程
with tf.Session() as sess:
# 模型设置

# 实际的训练闭环
for step in range(training_steps):
sess.run([train_op])

if step % 1000 ==0
# 将创建遵循命名模板为my-model-{step}的检查点文件,默认保存最近的5个文件
saver.save(sess,'my-model',global_step=step)

# 模型评估

saver.save(sess,'my-model',global_step=training_steps)
sess.close()

如果希望从检查点恢复,则使用tf.train.get_checkpoint_state方法验证检查点文件的存在,并使用tf.train.Saver.restore方法恢复变量值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
with tf.Session() as sess:
# 模型设置

initial_step=0

# 验证之前是否已经保存了检查点文件
ckpt=tf.train.get_checkpoint_state(os.path.dirname(__file__))
if ckpt and ckpt.model_checkpoint_path:
# 从检查点恢复模型参数
saver.restore(sess,ckpt.model_checkpoint_path)
initial_step=int(ckpt.model_checkpoint_path.rsplite('_',1)[1])

# 实际的训练闭环
for step in range(initial_step, training_steps):
...

参考文献

  1. TensorFlow指南,by tensorflow.
  2. 尝试理解 shape 的用法,by mcoder.
  3. Python中的列表(list),元组(Tuple),字典(Dict)和集合(Set),by liuyanfeier.
  4. 使用list和tuple,by liaoxuefeng.
  5. Python的reshape(-1,1),by lxlong89940101.
  6. numpy.array,by numpy.
  7. TensorFlow 官方文档中文版,by pythontab.
  8. numpy.array shape (R, 1) and (R,) 的区别,by 时间被海绵吃了2.
  9. tf.variable_scope中的reuse,by 超级无敌小小顺利.
  10. Tensorflow共享变量机制理解与应用,by BetterManPeter.
  11. tf.reduce_mean()函数解析(最清晰的解释),by 我是管小亮.
  12. 深度解析OPENAI-MADDPG,by 起点教程.
  13. diagonal Gaussian policies的一些理解,by Intuition.
  14. 强化学习随机策略之高斯似然数原理与代码实现,by 神奇的战士.
  15. 数学基础——浅谈似然,by shidata.
  16. gym中的discrete类、box类和multidiscrete类简介和使用,by iitter.
  17. OPENAI Baeslines 详解(零)综述,by zachary2wave.
  18. 强化学习Gym库学习实践(一),by 愣娃RC.
  19. Gym使用简介,by Lisnol.
  20. 左右互搏,self-play,《Emergent Complexity via Multi-Agent Competition》,by 王小惟 Weixun.
  21. 多智能体深度强化学习——MADDPG算法代码分析(tensorflow),by RavenRaaven.
  22. 多元高斯分布以及高斯分布微分熵,by 侠肝义胆陈浩天.
  23. tf.split 与 tf.squeeze 用法,by 应钟有微.
  24. 碎片化学习之数学(二):Categorical Distribution,by 李新春.
  25. Distribution is all you need:这里有12种做ML不可不知的分布,by 机器之心.
  26. tensorflow中axis理解非常重要,by 爱视觉.
  27. tensorflow中四种不同交叉熵函数tf.nn.softmax_cross_entropy_with_logits(),by iotstu.
  28. TF里几种loss和注意事项,by 崔权.
  29. Softmax函数和Sigmoid函数的区别与联系初识CV,by 初识CV.
  30. 损失函数|交叉熵损失函数,by 飞鱼Talk.
  31. tf.random_uniform的使用,by UESTC_C2_403.
  32. sparse_softmax_cross_entropy_with_logits与softmax_cross_entropy_with_logits,by 光彩照人.
  33. 关于LogSumExp,by Hurry Z.
  34. softmax 与 log sum exp,by 我要给主播生猴子.

Python的高效开发建立在大量常用库基础上,因此掌握常用的Python库十分必要。下面简单介绍Python的各类常用库。

常用标准库

  • os: 访问操作系统功能模块
  • sys: 访问一些环境变量和与 Python 解释器交互
  • datetime: 日期时间处理
  • collections: 高级数据结构,有序字典,队列等等
  • uuid: 生成 UUID 模块
  • random: 随机数生成模块
  • re: 正则表达式模块
  • json: JSON 处理模块
  • pdb: 单步调试模块

科学计算

  • scipy:基于Python的matlab实现,旨在实现matlab的所有功能。包含Numpy、Ipython、Pandas、Matplotlib、Sympy等常用库
  • numpy: 基于Python的科学计算第三方库,提供了矩阵,线性代数,傅立叶变换等等的解决方案
  • pandas: 支持表格等多维数据
  • matplotlib: 用Python实现的类matlab的第三方库,用以绘制一些高质量的数学二维图形

命令交互

  • ipython: 交互命令行,适合科学计算
  • jupyter: ipython notebook 的延伸,可以直接放在github上
  • argparse:(Python 标准库)用于命令项选项与参数解析的模块

爬虫相关

  • urllib: (Python 标准库),接受URL请求的相关模块
  • http: (Python 标准库),处理所有客户端–服务器http请求的具体细节
  • requests: 第三方库,人性化的HTTP请求库,比urllib更好用
  • pillow: 处理验证码
  • rsa: 处理加密问题
  • BeautifulSoup:解析html文档为用户提供需要抓取的数据
  • lxml: 是基于 libxml2 这一 XML 解析库的 Python 封装,解析速度比 Beautiful Soup 更快

环境管理

  • virtualenv:创建独立 Python 环境的工具
  • virtualenvwrapper:virtualenv 的一组扩展

包管理

  • pip:Python 包和依赖关系管理工具
  • conda:跨平台,Python 二进制包管理工具

并发和并行

  • threading:(Python 标准库)更高层的线程接口
  • multiprocessing:(Python 标准库) 基于进程的“线程”接口

日志

  • logging:(Python 标准库) 为 Python 提供日志功能。

兼容性

  • six:Python 2 和 3 的兼容性工具

计算机视觉

  • opencv

机器学习

  • tensorflow

参考文献

  1. Python 笔记四:Python的常用库收集, by brandonxiang

virtualenv是一个创建隔离python环境的工具,主要用于解决包冲突问题。

安装方法

1
sudo pip3 install virtualenv -i https://mirrors.aliyun.com/pypi/simple/

使用方法

创建项目的虚拟环境

1
2
$ cd my_project_folder
$ virtualenv venv #venv是虚拟环境名称

执行上述命令后,将生成一个与虚拟环境同名的文件夹,包含 Python 可执行文件和 pip 库的拷贝,可用于安装其他包。

但是默认情况下,虚拟环境中不会包含也无法使用系统环境的global site-packages。比如系统环境里安装了 requests 模块,在虚拟环境里import requests会提示ImportError。如果想使用系统环境的第三方软件包,可以在创建虚拟环境时使用参数–system-site-packages。如下所示:

1
virtualenv --system-site-packages venv

此外可以指定虚拟环境所使用的 Python 版本,但前提是系统中已经安装了该版本:

1
virtualenv -p /usr/bin/python2.7 venv

使用虚拟环境

启动虚拟环境:

1
2
3
cd venv
source bin/activate
python -V

退出虚拟环境:

1
deactivate

virtualenvwrapper

virtualenvwrapper是virtualenv 的扩展工具,提供了一系列命令行命令,可以方便地创建、删除、复制、切换不同的虚拟环境。同时,使用该扩展后,所有虚拟环境都会被放置在同一个目录下。

安装方法

1
pip3 install virtualenvwrapper

环境配置

在$home/.bashrc文件中添加如下几行代码:

1
2
3
4
5
# bash -f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true
if [ -f /usr/local/bin/virtualenvwrapper.sh ]; then
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
fi

使用方法

mkvirtualenv 也可以使用 virtualenv 的参数,比如 –python 来指定 Python 版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mkvirtualenv venv # 创建虚拟环境,虚拟环境目录都在 WORKON_HOME 里

lsvirtualenv -b # 列出虚拟环境

workon [虚拟环境名称] # 切换虚拟环境

lssitepackages # 查看环境里安装了哪些包

cdvirtualenv [子目录名] # 进入当前环境的目录

cpvirtualenv [source] [dest] # 复制虚拟环境

deactivate # 退出虚拟环境

rmvirtualenv [虚拟环境名称] # 删除虚拟环境

conda vs. pip vs. virtualenv

Conda是一个开源包管理系统和环境管理系统,用于安装多个版本的软件包及其依赖关系,并在它们之间轻松切换。 它适用于Linux,OS X和Windows,是为Python程序创建的,但可以打包和分发任何软件。

Pip是一个以Python计算机程序语言写成的软件包管理系统,用于安装和管理软件包。

它们直接的区别如下:

conda vs. pip vs. virtualenv

pip使用方法

1
2
3
4
# 导出python安装包环境
pip freeze > requirements.txt
# 导入requirements文件
pip install -r requirements.txt

参考文献

  1. 最全的Python虚拟环境使用方法,by Stevent.
  2. Pipenv:新一代Python项目环境与依赖管理工具,by 李辉.
  3. Python 修改 pip 源为国内源,by 花晓星辰.

最近需要用Blender建3D模型,试用了半天,将经验简单总结一下。

3D建模流程

  • 建立3D模型:通常在Blender的3D视图窗口对物体进行建模。
  • 拆分制作纹理:设置缝合边,再展开。打开U/V图像编辑器窗口即可看到拆分效果。导出图片后制作纹理。
  • 使用材质贴图:设置材质着色,添加纹理。

Blender快捷键

Blender快捷键很多,熟练使用可加速3D模型的建立。

3D视图窗口

字母键

  • A:全选、取消选择
  • Shift+A:增加物件,新建的物件会出现在准星的位置
  • B:框选,加Shift取消选择,按Esc退出选择
  • C:刷选,加Shift取消选择,按Esc退出选择
  • Shift+C:将游标设置到坐标系中心
  • Ctrl+Shift+C:为骨头添加约束
  • Shift+D:复制对象
  • E:挤出选中对象
  • Shift+E:编辑模式下,打开对称镜像挤出骨架
  • F:编辑模式下,在点的基础上构建边或面;在权重绘制模式下,设置笔刷大小
  • G:移动选中对象
  • Alt+G: 在Pose Mode下,按“Alt+G”骨架归位
  • H:隐藏对象(Hide)
  • Alt+H:显示对象
  • I:增加关键帧
  • Ctrl+I:物体模式下,反选所有未选择的物体
  • Shift+I:在Pose Mode下,选中骨架,再按“Shift+I”插入反关节
  • Ctrl+J: 在Pose Mode下,连接两个独立的骨架,以便在编辑模式下同时编辑;在Object Mode下,选择两个物件后合并
  • K: 切割,按“enter”键完成切割。按“k”键接着按住“ctrl”键移动到线框上可以自动定位到线的二分之一处。按“k”键接着按一下“c”键可以水平垂直或者45度进行切割。按“k”键接着按一下“z”键可以对物体一圈进行切割。
  • Ctrl+L:编辑模式下,选择一个点,在Ctrl+L将选择与点相连的连续表面
  • M:选中物体,按“M”键,再选择要将物体放置的图层。
  • N:打开物体属性
  • Ctrl+P:编辑模式下,设置多个骨头的父骨头;或者物体模式下,设置多个物体的父级。
  • Alt+P:物体模式下,取消物体的父子关系。
  • R: 旋转
  • Alt+R: 在Pose Mode下,按“Alt+R”骨架归位
  • Ctrl+R: 环切并滑动
  • S: 缩放
  • S+XYZ:沿XYZ轴方向缩放
  • Alt+S:法向缩放
  • T:打开左侧工具栏
  • U:编辑模式下按“U”,打开UV映射菜单,选择活动面再全选,然后UV展开
  • Ctrl+U:存储为启动文件
  • W:快捷拓展命令栏
  • X:删除
  • Z:线框模式与实体模式之间切换
  • Shift+Z:视口着色切换到实时渲染模式
  • ]:在Pose模式下,选择主骨头,再按“]”可直接选择下一根骨头
  • Shift+]:在Pose模式下,选择主骨头,再按“Shift+]”可直接选择下一根骨头
  • Ctrl+Space:调出三维坐标系操纵物体
  • Ctrl+Tab:进行点、线、面的编辑模式
  • Ctrl+Alt+Q:切换四视图
  • Ctrl+向上箭头:最大化对应视图
  • Shift+空格键:放大视图
  • Tab:编辑模式和物体模式切换
  • Ctrl+句号.:仅变换原点

功能键

  • F12:计算结果(算图模式),如果是黑色的,需要把摄像机和光源放在同一个图层中,或者选择摄像机和光源的图层。

数字键

数字键主要用于视角切换

  • 1:前视图
  • 3:侧视图
  • 5:正交与透视之间切换
  • 7:俯视图

鼠标键

  • 右键:选择物体
  • shift+中键:平移
  • 滚轴/(Ctrl+中键拖拽):缩放

参考文献

  1. Blender常用快捷键,by JinunMeng.
  2. 如何系统的学习blender?,by zhihu.
  3. 贴图、纹理、材质的区别是什么?,by zhihu.
  4. 材质、贴图、纹理的区别,by MATU.
  5. 材质和纹理的区别,by zhuyong006.
  6. 一文看懂材质/纹理 Material, Texture, Shading, Shader 的区别,by kidult00.
  7. Blender 移动、旋转、缩放,by heavi.
  8. 数字人轻松学习Blender系列之七:坐标,by DIGITALMAN.
  9. 【转载】Blender 常用快捷键大全,by ShaderJoy.
0%