十步配置TeamViewer远程控制Pi – 支持内网穿透

使用TeamViewer远程控制Pi有如下好处:

  1. 可穿透局域网,延迟较低.
  2. 账号管理,不会遗忘连接.
  3. 操作友好,移动设备可管理.
  4. 无需显示器即可配置完成.

但是,我们怎样才能通过TeamViewer远程操作树莓派呢?首先注意确定的你的板子是Pi 3的.如果不确定,请参考文章:http://www.52pi.net/archives/454

然后确定自己系统版本比较新,我使用的是目前截稿为止的2017-06-21-raspbian-jessie.

剩下的,你需要一根网线,还有耐心啦.

第一步:拉取TeamViewer的安装包.

wget https://dl.tvcdn.de//download/linux/version_12x/teamviewer-host_12.0.78433_armhf.deb

第二步:尝试安装.

sudo dpkg -i teamviewer-host_12.0.78433_armhf.deb

第三步:虽然第二步失败了,但是我们目的是让系统知道他缺了什么软件包.这才有这一步,如果你已经成功,略过此步.

sudo apt-get -f install

第四步:我们重新开始安装,这次就能成功安装了.

sudo dpkg -i teamviewer-host_12.0.78433_armhf.deb

第五步:因为我们烧写的系统有图形界面,默认TeamViewer要在图形配置,除非你没有图形界面才能在命令行下配置,我们并没有显示器,所以先使用raspi-config配置到仅命令行模式.

sudo raspi-config

选择Boot Options – Desktop / CLI – Console AutoLogin

第六步:逐步退出raspi-config的配置,这会重启你的Pi.然后重启后登陆,运行下面命令开始配置:

sudo teamviewer setup

第七步:输入账号密码密码,如果还没有账号,那么你需要在你的电脑端注册一个账号了.

注册账号请点击电脑端此位置:

树莓派提示:

第八步:输入用户名和密码后,会询问是否加入树莓派到你的机器列表,我们当然选y.

如果此时提示你需要邮件验证,请进行邮件验证,然后重新登录,无需退出本程序.

第九步:此时提示我们成功加入到分组内了.同时,电脑的TeamViewer上也出现了设备了.

树莓派提示:

电脑提示:

第十步:还原为图形界面登录.运行raspi-config.

sudo raspi-config

选择Boot Options – Desktop / CLI – Desktop AutoLogin

完成:逐步退出raspi-config的配置,这会重启你的Pi.大功告成了.

此时你可以使用电脑版,移动端版TeamViewer测试连接.

电脑端测试图:

移动端测试图:

不知道大家注意到没,我手机访问使用的是移动网络,并且依然可以访问到内网的Pi,而我是没有给我的Pi分配公网IP的哦.

 

#Raspbian C应用编程#strlen 和 sizeof 的区别

上一次已经做了个CPU温度频率记录器,细心的同学如果打开文件一看,就哭晕了.

跟想象中好大差别啊:

为什么这么多^@啊,原来这是0x00的转义字符啊,因为我们上一节只用到了sizeof,所以不管buf多大,我们都写了1K数据进去.简直是浪费.把sizeof换成strlen,每次生成字符串前都清空buf.

这样每次写入的数量就心中有数了,strlen获取的是字符串有效长度,sizeof获取的是字符串的整个容器大小.

经过上述调整的代码,看起来就不违和了.

要想学习更多Linux C知识,多多关注本站吧,本站所有调试基于树莓派学习,现在入手买个套件,更方便你更进一步哦.

程序下载:

cpu_logger (3KB)

#Raspbian C应用编程#Linux 文件I/O – 系统温度主频记录器

UNIX/Linux 的一个基本哲学是”一切皆文件”.不仅普通的文件,甚至连各种字符设备、 块设备、套接字等都被当成文件对待,尽管它们的类型差异很大,但 UNIX/Linux 为它们提 供的操作界面却是相同的. Linux 把大部分系统资源当作文件并呈现给用户,用户只需按照文件 I/O 的方式,就能完成数据的输入输出. Linux 文件按其代表的具体对象,可大致分类为:

  1. 普通文件,即一般意义上的文件、磁盘文件;
  2. 设备文件,代表的是系统中一个具体的设备;
  3. 管道文件、 FIFO 文件,一种特殊文件,常用于进程间通信;
  4. 套接字( socket)文件,主要用在网络通信方面.

文件 I/O 的常用操作方法有”打开”、”关闭”、”读”和”写”等.只要是文件,所有文件都有前面两种方法.系统提供了文件 I/O API,以函数的形式提供给应用程序调用.打开文件对应的函数是 open(),读文件对应的函数是 read(),写文件对应的函数是 write(),关闭文件对应的函数是 close()

文件描述符 是进程中用来表示某个文件的一个变量, 文件描述符的作用,类似于在排队取号,业务员(进程)通过叫号(文件描述符)就能找到来搞事的人(文件)

大多数 Raspbian系统中,可通过命令”ulimit -n”查询到这个数值的大小,但注意,不是所有Linux都有这个指令.

文件描述符 012 在Linux上有特殊意义,我们暂时可以不去理解他.只知道他们比较特殊就行了,所以实际上树莓派只有最多7312个同时打开文件.(难道还不够?)

另外文件操作要涉及几个头文件,死记硬背.要用到哪个函数,就用哪个头文件,就是这样的.

#include<sys/types.h> /* 定义数据类型,如 ssize_t, off_t 等 */
#include <fcntl.h> /* 定义 open, creat 等函数原型,创建文件权限的符号常量 S_IRUSR 等 */
#include <unistd.h> /* 定义 read, write, close, lseek 等函数原型 */
#include <errno.h> /* 与全局变量 errno 相关的定义 */
#include <sys/ioctl.h> /* 定义 ioctl 函数原型 */

我们这就上Pi实践下,还是使用VS + Visual GDB神奇组合.就算你不懂Linux各种繁琐指令也能写出不错的程序.如果还不是特别了解,就参考下之前的文章吧.

下面演示的例子,先以可写方式打开当前目录下的hello.txt文件,如果该文件不存在,则创建文件,再往文件中写入一个字符串Hello, welcome to 52pi.net!,把操作结果输出到终端后,关闭文件. 接着再次以只读模式打开该文件,读取刚才写入的数据,并把结果输出到终端最后关闭该文件.

代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>

int main(int argc, char *argv [])
{
	char sz_str [] = "Hello, welcome to 52pi.net!";
	char sz_filename [] = "hello.txt";
	int fd = -1;
	int res = 0;
	char buf[128] = {0x00};
	fd = open(sz_filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
	if (fd < 0)
	{
		printf("Open file %s failed,errno = %d.\n", sz_filename, errno);
		return -1;
	}
	
	res = write(fd, sz_str, sizeof(sz_str));
	printf("write %d bytes to %s \n", res, sz_filename);
	fsync(fd);
	close(fd);
	
	fd = open(sz_filename, O_RDONLY);
	if (fd < 0)
	{
		printf("Open file %s failed,errno = %d.\n", sz_filename, errno);
		return -1;		
	}
	
	res = read(fd, buf, sizeof(buf));
	buf[res] = '\0';
	printf("read %d bytes from file %s ,data = %s \n", res, sz_filename, buf);
	close(fd);
	
	return 0;
	
}

测试结果:

那么刚才代码里面的O_WRONLY都是什么定义呢,我们可以右键,转到定义去查看一下.


当然也可以看我解释:

  • O_RDONLY 以只读方式打开文件
  • O_WRONLY 以只写方式打开文件
  • O_RDWR 以可读写方式打开文件. 上述三种旗标是互斥的, 也就是不可同时使用, 但可与下列的旗标利用OR(|)运算符组合.
  • O_CREAT 若欲打开的文件不存在则自动建立该文件.
  • O_EXCL 如果O_CREAT 也被设置, 此指令会去检查文件是否存在. 文件若不存在则建立该文件, 否则将导致打开文件错误. 此外, 若O_CREAT 与O_EXCL 同时设置, 并且欲打开的文件为符号连接, 则会打开文件失败.
  • O_NOCTTY 如果欲打开的文件为终端机设备时, 则不会将该终端机当成进程控制终端机.
  • O_TRUNC 若文件存在并且以可写的方式打开时, 此旗标会令文件长度清为0, 而原来存于该文件的资料也会消失.
  • O_APPEND 当读写文件时会从文件尾开始移动, 也就是所写入的数据会以附加的方式加入到文件后面.
  • O_NONBLOCK 以不可阻断的方式打开文件, 也就是无论有无数据读取或等待, 都会立即返回进程之中.
  • O_NDELAY 同O_NONBLOCK.
  • O_SYNC 以同步的方式打开文件.
  • O_NOFOLLOW 如果参数pathname 所指的文件为一符号连接, 则会令打开文件失败.
  • O_DIRECTORY 如果参数pathname 所指的文件并非为一目录, 则会令打开文件失败.(Linux特有)

而第二项权限意思是这样的:

  • S_IRWXU00700 权限, 代表该文件所有者具有可读、可写及可执行的权限.
  • S_IRUSR 或S_IREAD, 00400 权限, 代表该文件所有者具有可读取的权限.
  • S_IWUSR 或S_IWRITE, 00200 权限, 代表该文件所有者具有可写入的权限.
  • S_IXUSR 或S_IEXEC, 00100 权限, 代表该文件所有者具有可执行的权限.
  • S_IRWXG 00070 权限, 代表该文件用户组具有可读、可写及可执行的权限.
  • S_IRGRP 00040 权限, 代表该文件用户组具有可读的权限.
  • S_IWGRP 00020 权限, 代表该文件用户组具有可写入的权限.
  • S_IXGRP 00010 权限, 代表该文件用户组具有可执行的权限.
  • S_IRWXO 00007 权限, 代表其他用户具有可读、可写及可执行的权限.
  • S_IROTH 00004 权限, 代表其他用户具有可读的权限
  • S_IWOTH 00002 权限, 代表其他用户具有可写入的权限.
  • S_IXOTH 00001 权限, 代表其他用户具有可执行的权限.

如果不指定,权限就是000了,000代表谁都对这个文件没办法.

从上述我们已经了解到文件基本读写,那么现在开始实践,已知Raspbian系统的核心0的主频是存在/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq文件,而CPU温度是存在于/sys/class/thermal/thermal_zone0/temp文件.我们读取这两个文件,定时写入到一个文件里面做记录.

所以,记录工程应该长这个样子.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>

#include <time.h>


int main(int argc, char *argv [])
{
	int cpu_freq_fd = -1;
	int cpu_temp_fd = -1;
	int cpu_logger_fd = -1;	
	
	char freq_buf[128] = {0x00};
	char temp_buf[128] = {0x00};
	char log_buf[1024] = {0x00};
	
	time_t rawtime; 
	struct tm * timeinfo; 
	
	cpu_freq_fd = open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", O_RDONLY);
	cpu_temp_fd = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);	
	cpu_logger_fd = open("cpu.log", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
	
	while (1)
	{
		lseek(cpu_freq_fd, 0, SEEK_SET); /* 回到文件的开始 */
		read(cpu_freq_fd, freq_buf, sizeof(freq_buf)); /* 读取文件 */
		
		lseek(cpu_temp_fd, 0, SEEK_SET); 
		read(cpu_temp_fd, temp_buf, sizeof(temp_buf)); 
		
		time(&rawtime); 
		timeinfo = localtime(&rawtime); 
		
		char *now_time = asctime(timeinfo);
		now_time[strlen(now_time) - 1] = 0;
		
		sprintf(log_buf,"%s - CPU = %d MHz - Temp = %d degC\n", now_time, atoi(freq_buf) / 1000, atoi(temp_buf) / 1000);		
		
		write(cpu_logger_fd, log_buf, sizeof(log_buf));
		fsync(cpu_logger_fd);
		
		sleep(1);
	}
	
	close(cpu_freq_fd);
	close(cpu_temp_fd);	
	close(cpu_logger_fd);		
	
	return 0;
	
}

执行效果,是不是很棒,这样就有一个监控程序了.通过程序不难看出,就是不断写cpu.log文件.然后休眠.

此处用到的两个工程:

cpu_temp_logger

file_wr

Visual Studio + VisualGDB 远程调试树莓派

想必很多人都知道地表最强IDE VS,超级补全非常靠谱,如何结合VisualGDB,还能调试树莓派呢.Visual GDB的下载地址:

http://visualgdb.com/download/

可以足足试用30天,试用结束后可以寻求网友帮助或者购买软件.本站是不提供破解下载的哦.

软件原材料:

  1. Visual Studio 2017 社区版(更高版本也可以)
  2. VisualGDB 5.2r8(更高版本也可以)
  3. 树莓派需要开启SSH登陆

硬件原材料:

  1. 树莓派
  2. 跑着Raspbian系统的TF卡(同类系统也可以)

首先打开VS,然后点击文件 – 新建项目 – VisualGDB – Linux Project Wizard.并选择一个英文路径和文件名保存工程.

我们使用微软编译器,并选择C语言.

选择新建一个连接:

依次如图填写主机IP,用户名,密码(Raspbian的默认用户名是pi,密码raspberry):

第一次设置连接会弹出如下提示,直接按Save保存好通信的”钥匙”.

编译器选择,我们可以选GCC,GCC比较通用,然后接着下一步.

等待项目创建:

如果没有出现上图的创建项目的过程,检查下SSH是否已经打开,IP和密码是否正确.如果出现下图的错误,请直接点击OK修复.此错误通常出现在新的Raspbian系统上.

如果以上问题都解决了,就可以点击完成Finish了.

首次会从树莓派上复制部分文件到电脑,这样是为了一些代码补全和调试方便.

当工程创建完毕后,双击右侧的c文件,打开源码显示,如图.

并在右侧return 0的位置单机左键,新增一个红点,这个红点意思是断点,程序执行到这里,就等我们继续发令才能继续运行.

点击上面的VisualGDB Debugger开始编译并下载到板子测试.

这里可以看得到编译过程:

可见程序已经执行并输出Hello World.并且停在红点位置了.

使用VS进行调试最大的优点是实时观察变量,内存等,并且支持断点调试,还不用去学习vim怎么去使用.更多功能还等着大家去探索.

让树莓派USB口支持大电流

让树莓派USB支持大电流才可以让树莓派挂移动硬盘,有两种方法,第一种使用树莓派自身USB,加载特定参数,另一种使用我们研发的一个有源HUB方案.

使用树莓派自身的扩大电流方案优点:

  1. 不用额外购买USB HUB
  2. 不插HDMI时候可以安全获得更大电流提供.
  3. 只需要与以太网共享带宽.

使用树莓派自身的扩大电流方案缺点:

  1. 失去保修
  2. 最大只能提供1.2A电流(默认600mA)
  3. 过流容易导致树莓派彻底损坏,如核心电压变低,严重的导致主芯片损坏.
  4. 不能用于Pi Zero.因为Pi Zero默认没做电流调节,直接限制在600mA了.

使用我们的有源HUB方案优点:

  1. 不失去保修
  2. 能提供最大1.8A的电流输出
  3. 不会损坏树莓派
  4. 不管是否使用HDMI,均不影响使用.
  5. 更多USB口可以使用.

使用我们的有源HUB方案缺点:

  1. 设备更多,共享带宽更少,通常在连接多个移动硬盘时尤为明显.
  2. 需要购置有源HUB.

我们推荐使用第二种方案,但是现在先介绍下第一种方案的实现方式和原理.

因为树莓派的USB电流大小由USB电流保护芯片控制,所以通过旁路USB电流保护芯片就可以实现更大电流,由于电源芯片限制,最大电流为1.2A.具体方法也非常简单.添加下图三行就可以了.

max_usb_current=1
current_limit_override=0x5A000020
avoid_warnings=2

再次启动Pi,已经可以支持更大电流了.可见,电流已经接近1.2A的输出能力了.

但是如果要更大怎么办,直接使用我们的有源HUB方案,无需修改配置文件,直接使用.电流可以直接到达1.8A.使用有源HUB提供大电流的话,不需要修改树莓派配置(仅限2017-04-10以后的镜像)

完全抛弃TF卡,从USB启动树莓派.

从USB启动树莓派有很多好处,比如说可以直接硬盘Boot,是不是听起来很新鲜,其实官方已经为了U盘启动做了不少准备了.

硬件原材料方面:

  1. 树莓派3,必须是4月10号以后的批次,如果不放心可以到我们商城咨询.
  2. 靠谱的电源一个,USB启动失败大多数是电源问题.
  3. TF卡一张,至少8G,配置阶段要用呢.
  4. 8G或者以上U盘/移动硬盘,带移动硬盘要注意电源问题,我们店里有实测过的电源,能带的动普通的笔记本硬盘.

软件原材料方面:

  1. 4月10号以后的系统镜像.不知道请猛戳 http://www.52pi.net/?p=454 检查.
  2. 认真 + 耐心 + 信心.

好了,我觉得大家都知道怎么去烧写系统到TF卡了,但是不要马上插上去启动.打开如图所示文件,加入以下内容.(注意空格哦~)

program_usb_boot_mode=1

然后保存,启动Pi,默数60秒后直接拔掉电源就行.此时可以取出你的TF卡.然后把系统镜像,直接烧写到U盘/移动硬盘内.对,就是把U盘/移动硬盘当成TF卡了.

然后插到树莓派上启动吧,特别注意:从USB启动有5秒的启动延迟,这个官方称为failsafe boot.

运行df -h指令,观察此处已经称为sda1了,证明是USB启动的.

想恢复TF卡启动怎么办?TF卡总是第一启动顺序的,只要TF卡上有系统,就会从TF卡启动~

更多干货,请持续关注树莓派中文站~

Raspbian 有多少个版本?

Raspbian究竟有多少个版本呢,答案是总共有6个版本,其中2个是公开版本,4个是非公开版本.

六个版本,依次增加功能:

1)最小化启动:这其实只是一个引导系统.树莓派专用的一些软件(闭源)会在这个包提供,但是这个系统并不能直接启动.

2)真正最小系统,这就是一个最小最小的系统,只有基础功能,没有任何额外添加.

3)(公开发布)轻量系统,也就是Raspbian-Lite,官方发布的Raspbian-Lite也就是这个系统.

4)基本桌面环境,只有桌面环境但是没有相对应的一些软件.适合于只要桌面但是不需要任何额外软件的用户.

5)用户友好的桌面环境,这个已经非常接近官方发布的系统了,他对用户友好,对新手来说也很方便.并且,这个系统限定在4G卡也可以使用.

6)(公开发布)完整系统,这个就是官方发布Raspbian,也是我们最常用的,他加入了Mathematica软件,其他跟第五个系统是一样的.

制作这些系统可以通过官方Git工具制作,至于公开发布的系统,直接下载就可以了.

https://github.com/RPi-Distro/pi-gen

当然,如果不知道怎么生成其他系统,可以持续关注树莓派中文站,我们将持续有新资料发布,包括这些系统哦.

如何确认自己的Pi版本和系统日期

很多小伙伴不知道自己的Pi的版本和系统日期,然后在使用我们的教程时候发现各种问题,下面我就教三招简单识别方法.

1)使用gpio readall命令,如图就是Pi 3版本了.此方法可以简单识别出自己板子型号.如果没有这个指令,那么你需要更新你的操作系统了.

2)使用cat /etc/rpi-issue命令,如图就是使用6月21日的镜像.此也是发稿为止最新的系统.

3)使用vcgencmd version命令,如图我使用的是7月3号的系统固件版本.

如何核对版本和板子型号,依然教程没有反应,那么就得检查下是否有输入错误,如果确认无误,就到QQ群里讨论讨论吧.

 

在树莓派上学习命令行-零

本文翻译参考自MagPi系列文章Conquer the Command Line。
旨在带领新手更好更快地学会在树莓派上的命令行和终端的使用。

不要慌张

首先终端不是一种到过去的退化,反而它是一种高效而有力的使用树莓派的方法。
假如你的树莓派没有设置开机直接进入图形化界面的话,开机进入的就是终端,当你登陆之后输入startx进入图形界面,然后按住ALT+CTRL加上F1就能发现这个终端还是开着的,按住ALT加上从F2F6都会有一个虚拟的终端等着你去登陆,而且任何时候你都能进入并使用这些终端。

按下ALT+F7,就会回到图形化界面,有鼠标、有菜单,在图形化界面也有终端可以使用,他们一般被称为终端模拟器(term或者xterm),你应该也听很多人说过shell或者Bash,现在不用担心这个,后面就会提到。现在只要在上面的任务栏单机这个黑色显示器样子的图标,或者通过菜单Accessories>Terminal,终端模拟器就打开了。

 

 

 

查看文件目录

你肯定已经习惯了在Windows中用串口看各种文件和目录,现在把那些图标都抛到脑后,注意这些文件或者文件夹的名字,在终端中输入ls并回车,在刚刚安装好的干净的树莓派系统中,你会看到两个目录:python_gamesDesktop,输入ls python_games,就会看到下面这个图这样的输出。

ls这样的命令其实一点都不神秘,但是他们会显得很简洁,是一些英文的缩写,比如ls就是list的缩写。

 

文件路径

你可以列出系统中的任何地方的文件或者目录,只要你在ls命令后面加上路径参数,而路径这个东西呢,它还是层次化的一个东西,比如在Windows系统中,路径从我的电脑开始,而在树莓派上,路径从/开始,被叫做根目录(root),把你的系统看作一课树状的结构的话,/确实是树的根部,现在我们再试试输入ls /,发现反馈的是一堆很奇怪的单词,比如binbin是binary的缩写,这个目录里面放的全是可执行二进制文件(输入ls /bin就可以看一些细节了),同样的ls /dev就能查看树莓派上的硬件设备有哪些,尝试一下ls /home,会看到返回的是pi,这个pi就是登录中的你自己,你如果改个名字,这个pi文件夹也会相应的改变。

通过pwd命令,可以查看当前终端所在的目录,pwd也就是present working directory。

~是什么

对于所有的登录的用户,他们的home目录都被简写成~,除了~,Linux还保留着两个类似的目录,一个是.一个是..,他们在每个目录中都有,在每个目录都不太一样,如果你使用ls -a,就会在返回中看到他们的存在,其中.代表着当前目录,假如你在/home/pi目录里面,.就是/home/pi,而..代表的就是上一级目录,就是/home目录。

切换目录

我们现在学会了在一个目录下面通过ls查看这个目录中的文件,而通过cd命令,我们就能切换当前所在的目录(change directory),无论当前你在哪个目录,输入cd /home/pi,就会切换到/home/pi这个目录;除了常规的路径,我们也能在其中加入上面提到的~...,假如当前目录是/var/www/html,那么我们输入cd .,就会切换到/var/www目录,如果输入..,就会切换到/目录,同样的,无论你在哪个目录,假如你输入cd ~,都会切换到/home/pi这个目录。

FAQ

查看某个命令的用法

在一个命令之后可以加上一些参数来得到一些附加的功能,比如对于ls命令,我们在后面加上-l或者-a都会得到不同的更加详细的反馈,而且我们可以通过man加命令来得到这个命令的所有用法解释,比如man ls

按下回车键

每当你输完一个命令,都得在这一行的最后按下回车告诉终端这个命令写完了,需要执行。

树莓派抓拍猫咪不良行为

来自52Pi社区的hotgarlic投稿~欢迎广大网友投稿至管理员

Hi, 树莓Pi的创客们,大家好。

今天跟大家分享一下一个很实用的例子,如果你已经玩过我的上一个入门教程,觉得不过瘾,那么就来试试今天的项目。

这次是用Pi制作智能摄像头,监视我家的猫咪,当它在台盆里喝水时就会被摄像头拍下来。当我们人的手或其他东西在台盆上时,摄像头则视而不见。因此要用深度学习技术,让摄像头能够将猫和其他东西区分出来。这里要在keras框架中运行inceptionV3模型,用到finetune技术。

技术介绍

InceptionV3

这是Google设计的深度学习网络框架,由很多层卷积层和一个分类器(全连接神经网络)组成。卷积层是核心,他负责从图片中提取特征,比如边缘,颜色,几何形状等等,还有人的五官,汽车的轮子等等,前一种叫浅特征,后一种叫深特征。而分类器,只做一些是非判断。所以卷积层相当于人类的感知,分类器则是纯粹的计算器。

这个网络特性优异,可以区分1000种类别的图片。因为他卷积层有很多,并且用数万张图片进行训练,从而学到了很多特征。特征被存放在权重文         件中,我们要用他来做摄像头程序。

finetune

inceptionV3的类别其实已经包含了猫。但是,我家的田园土猫,经常被识别成法国斗牛犬(图1),有时还会蹦出一些稀奇古怪的狗的名字(图2)。为了能让inceptionV3认出我家的猫,我必须让inceptionV3多识别几次,记录下它输出的一些奇特类别,然后把它们转换成猫咪类别。但有时猫咪站在台盆上,inceptionV3会输出浴缸,可能是台盆比猫清晰。要是每次这样也道倒算了,问题是台盆空着时,他也认成浴缸(图3),这就很麻烦了。

你可以到basin_cat/full_test/中运行recognize.ipynb,他会把我洗手的图认成皮搋子(图4)。

所以,最好能够训练一个自己的深度网络。但是训练卷积层需要昂贵的硬件设备和几周的时间,好在有了finetune技术。

finetune(图6)。就是不全部借用整个网络,而只是借用卷积层框架和它学到的特征,至于分类器,你必须重新设计,包括给出你自己的类别个数,当然训练用的图片也应该是你自己的。在训练过程中,卷积层的参数不会被修改,但是分类器的参数会改变,直到这个分类器能够分对图片。因为从全部模型做的识别中看出,卷积层学到的特征都还靠谱,他至少知道猫咪是个四条腿的动物,所以这些特征可以拿来利用。

教程

硬件

Pi3B+picamera2+Pi显示器(最好5寸以上),系统:Raspbian Jessie with PIXEL(2017-03-02)

PC/笔记本,系统:Ubuntu 14.04

软件包的安装

我希望你已经对python和Linux比较熟悉,知道如何安装缺少的包,熟悉从GitHub克隆安装软件包。然后在Pi和PC上都安装好下面的包。过程可能比较麻烦,有问题可以联系我hotgarlic@163.com

首先运行:

$sudo apt-update    #系统更新

$sudo apt-upgrade   #系统升级

$python3 get-pip.py  #安装python软件包安装器pip3,在basin_cat文件夹中

tensorflow

他是keras的后台程序。

  • Pi上安装:参考这里,选用第一种pip安装方式,以及python3对应的包。本教程所用

的代码,python包,和包的安装方式也都是针对python3的。

  • PC上安装:具体参考这里,如果打不开,请百度禾斗学上网。
$sudo apt-get install python-pip python-dev

$pip3 install tensorflow

Keras

$git clone https://github.com/fchollet/keras.git

$cd yourfloder/keras

$sudo python3 setup.py install

他操作起来比tensorflow简单许多,值得多多学习,其包含了很多例子和优秀的模型,甚至你可以在他的仓库里找到alpha go的相关算法,这是现在很多人工智能的开源项目里面第二大开发平台,第一就是比较难用的他的后台tensorflow。

jupyter notebook

$sudo pip3 install jupyter

$jupyter notebook     #进入jupyter界面

他是一个非常简洁易用的IDE,适合调试代码,现在越来越多的教程开始使用这个平台。具体用法很简单,这里就不细说了,请百度。

 

h5py

$sudo apt-get install python3-h5py

是用来存取训练分类器权重的软件包。

 

skimage,imageio

$sudo pip3 install -U scikit-image

$sudo pip3 install imageio

他们都是图片处理包。其中Imageio可以将mp4转换成图片。

 

Matplotlib

$python -m pip install -U pip setuptools

$python -m pip install matplotlib

这是可以在IDE中查看图片的工具包,可以不用安装,特别是不需要在Pi上安装。

 

gpac

$sudo apt-get install gpac

$MP4Box -add path/file.264 path/file.mp4    #格式转换命令

只需Pi上安装的包,可以将h264视频转换成MP4格式。

 

操作流程

  • 将整个basin_cat文件夹复制到你的PC上。
  • 打开jupyter,在jupyter中打开ipynb,单步运行代码。
  • 先运行*和2.1之间的代码。之后sample文件夹里会多许多图片,请把图片中没有人,没有猫出现的图片放到basin_cat/label_2/sample中。

  • 再运行其余代码:

将分好类的图片进行扩增

加载inceptionV3模型及其学到的特征

让inceptionV3转换所有扩增好的图片

将inceptionV3转换好的数据作为分类器的训练数据

建立分类器模型

训练分类器

  • 最后h5生成,里面是权重参数,在train.ipynb同文件夹。

 

将ipynb和trial_0.h5一起复制到Pi的同一个文件夹中。

  • 打开jupyter,在jupyter中打开ipynb,单步运行代码。
  • 先是一段预览摄像头的代码,会在屏幕上显示摄像头拍到的图像,你有10秒中调整摄

像头的位置。

  • 然后是加载inceptionV3模型及权重、建立分类器模型的代码。注意这里的分类器一

定要和train.ipynb中一致!

  • 最后是主程序,它循环不断得抓取图片,然后进行识别,如果识别到0类图片,也就是猫咪在台盆里喝水的图,那么将会把这个图片保存在硬盘中,在monitor.ipynb所在的文件夹。逮住猫咪喝水的图片是这样的(图5)。

 

说明

  • random文件夹,是用来存放扩增图片的。扩增图片是从原始的图片中产生的,经过

了随机的几何变形和明暗变化后,原先的图片就可以成倍的增长,可以在样本不多的情况下让模型训练得更好。

  • 你可以拍摄mp4,并存放到sample文件夹,注意要用mp4, 1.mp4, 2.mp4 …等等作

为文件名。

  • 你也可以增加类别,先新建一个label_n文件夹,里面也要保含random和sample

文件夹。同时也要到train.ipynb中修改相应的代码。具体怎么改,请看代码里面的comment,这里就不细说了。当然,你最好也改一下分类器的模型和类别的个数。

  • 如何改进识别的准确度

我在第一次试运行中发现,虽然Pi可以捕捉到猫咪跳上台盆的证据,但有时也会误判。比如Pi会把台盆上的黑裤子当成猫咪。这是因为负样本(不是猫咪的图片)没有包含了黑色裤子的图片。

在这种情况下,从inceptionV3中获得的转换后数据,虽然包含了很多关于猫咪的深度特征,但分类器会故意忽略掉一些。

黑色裤子并不像猫咪那样有两个尖尖的耳朵(深度特征)。当缺乏黑裤子这样的训练样本时,分类器就只会根据颜色(浅特征)来分类。因为对分类器来说,只要看看图片里那块地方颜色是不是黑的,占了多大地方,连续度怎么样,就足以做出正确的判断了。

 

能否充分调动那些特征,使得分类器在判断时采纳这些信息,就取决于你能否给出足够数量的具有迷惑性的数据。

另外,将猫咪拖到其他背景中采集图片,也可以迫使分类器多多参考深度特征进行判断。

所以,你就要有意无意得对Pi进行干扰,让它拍下一些误判的图片,然后把这些图片加入到非猫咪图片的样本中去,再按照流程重新训练一遍。这里给出的代码也已经使得工作简化了许多,而且那些误判的图片并不会很多。

待完善

我还没有制作驱赶猫咪的机构,比如声光报警,喷水,来吓唬猫咪。希望有兴趣的并且同样讨厌猫咪不良行为的创客可以帮我完成。我并不擅长这些硬件方面的知识。

因为我用的是可见光摄像头,而不是红外摄像头,所以光线太暗就会导致误判,因

为很多细节的特征会被淹没。所以我就把昏暗的图片归类到了非猫咪类中,希望猫咪不会发现其中的漏洞。有兴趣的创客可以再加一个红外传感器来辅助一下。

题外话

也许你会认为,图片越多越准确,算什么智能。确实,现在有很多人提出这一的质疑。但是如果没有深度神经网络,卷积这样的算法,即便你拥有所有的图片,你都很难把这些图片抽象成可计算的特征,而现在的深度网络最成功的地方,就是自动提取特征,而且是深层次的特征。相比人工对特征参数化,就已经进步了不少。当然,还远远没有达到理想中的智能的目标。