存档8月 2020

PCA9685舵机控制板

https://github.com/adafruit/Adafruit_Python_PCA9685

PCA9685 c++ WiringPi https://www.raspberrypi.org/forums/viewtopic.php?t=67618

https://www.jianshu.com/p/782058c93a7a
https://www.jianshu.com/p/b2a6306e583d?from=timeline&isappinstalled=0
https://zhuanlan.zhihu.com/p/22805173

https://www.cnblogs.com/yjphhw/p/10649940.html
https://blog.csdn.net/qq_41559171/article/details/87950642
http://www.cirmall.com/bbs/thread-97290-1-1.html


假设舵机为50HZ的频率,脉宽为0.5ms~2.5ms,12位分辨率(4096级),相关计算如下:

PWM周期:1/50=0.02s=20ms=20000us

时间分辨率:200000/(2^{12})=4.88us

最大脉宽时间:2.5ms-0.5ms=2ms=2000us

最大脉宽时间可分成的份数:2000us/4.88us=410

0-180度的舵机,角度分辨率:180^{\circ}/410=0.439^{\circ}


如果在舵机控制中,采用内置晶振,取osc_clock=25000000,update_rate=50(舵机控制频率50Hz)

设置角度
60度对应的脉宽=0.5ms+(60/180)*(2.5ms-0.5ms)=1.1666ms
利用占空比=1.1666ms/20ms=off/4096,off=239,50hz对应周期20ms
setPWM(num,0,239);;;;当然也可以利用SERVO000和SERVO180计算

imutils

源码
https://github.com/jrosebr1/imutils
参考
https://www.jianshu.com/p/bb34ddf2a947
https://www.pythonf.cn/read/30985
图形矫正 http://www.mamicode.com/info-detail-2802340.html

C++

发展

C 面像过程 ->1979 C 带类的C->1983 C++面像对象OOP->C++98 STL标准库-> 2011 C++11 Boost库 -> 14->17->20 每三年一版
三大特性:封装 继承 多态
强大的抽象封装能力
高性能
低功耗
语法相对复杂,学习曲线较陡
注意开发规范,否则代码难维护
开发成本高

.cpp编译 -> .asm -> 链接.obj -> .exe
qt自带gcc windows
xocde glang
g++
源码.c -E预处理.i -S编译.s -c汇编.o gcc 链接 -o 指定输出文件名
一步完成 gcc -o a.exe a.c

教程

  1. https://www.runoob.com/cplusplus/cpp-tutorial.html
    char 1 -128~127|0~255
    shor int 2 -32768~32767|0-65535
    long int 4 -21247483648~2147483647|0~4294967295
    int 4 -21247483648~2147483647|0~4294967295
    float 4 3.4e+/-38
    double 8 1.7e+/-308
    long double 8 1.7e+/-308
    boolr 1 true/false
    wchart_t 2

C++ keywords: https://en.cppreference.com/w/cpp/keyword
定义常量 #define(宏替换) const(建议)
前缀0x十六进制 0八进制 L’x’宽字符 后缀U符号 L long
\转义字符 \ \’ \” \? \a 警报铃声 \b 退格键 \f 换页符 \n 换行符 \r 回车 \t 水平制表符 \v 垂直制表符 \ooo 一到三位的八进制数 \xhh… 一个或多个数字十六进制数

逻辑运算&& || ! 位运算 & ^ | ~ << >>(对有符号的数,尽可能不要使用右移运算)
sizeof(), Condition ? X:Y, , . , ->, Cast(不建议使用),&(取变量地址),*(指向变量)

补码(两种计算方式) 大小端

注释: // /* */

typedef struct{
short Sunday=0;
….
}Week;

默认成员权限公开的
struct A{
}
默认成员权限私有的
class Trace{
public:
virtual double Area() const=0; //多态,子类方法实现不一致时加virtual,const=0表示简单实现,虚的
}
typedef enum __COLOR{
RED,
}color;

union Score{
}
定义常量 #define const
声明 enum color{red,gree}; color color1;

注意结构体数据对齐问题32位CPU4字节
连续分配修改编译选项:
V C++: #pragma pack(n)
g++: attribute(aligned(n)) attribute(packed)

int arr[2] = {1,2}; arr[2] =5;int * p =arr;*(p+2)=5;
int len = sizeof(arr)/sizeof(arr[0]);
差一错误, (]左闭右开,
循环时尽可能满足”空间局部性”
新型数组vector(面向对象方式的动态数组)
字符串是以空字符(‘\0′)结束的字符数组,在声明时应预留一个额外的元素
双引号是字符串,单引号是一个字
char c1=0; ->0x00 char c2=’\0′; ->0x00 char c3=’0’;->0x30
UTF-8:1byte,兼容ASCII码,效率高,变长(不方便内部随机访问),无字节序问题
UTF-16:BE/LE 2bytes 定长(不方便内部随机访问),有字节序问题
UTF-32:BE/LE 4bytes 定长(不方便内部随机访问),有字节序问题
windows的文件可能有BOM,在其它平台使用可去掉

指针表示方法T,存贮地址,间接访问值的操作t,指针自身也有地址t,&t
char ch=’a’; char* cp=&ch;
表达式 左值 右值
&ch 非法 ch的地址
*cp ch的地址 ch的值=a
*cp+1 非法 ch的值+1=b
*(cp+1) ch的地址+1 ch的地址+1的值 注意内存溢出

char s[] = ‘hello’; //数组s不可变,s[index]的值可以变
char* P1 = s;
char* p= “hello”; //指针p可变,p[index]的值是否可变取决于指区间的存储区域是否可变
float* P=&F;
指针指向的内容P = 内容F <- 内容地址&F
int
a[4];批针的数组,数组中的每个内容是指针
int(b)[4]; 数组的指针,指针指向的是一个数组
指向指针的指针 int** c=&P1;
指针确保初始化并赋值,小心意外发生
int
a = NULL;不指向任何东西时的状态,指针不用时置NULL,使用前先判断是否为NULL,nullptr(新)
定义函数指针: typedef void(*FuncPtr)(); FuncPtr funcPtr;

const 常量,修饰不充许修改,先看左侧最近的部分,没有则看右侧
char const* s; const char *; 内容不可变
char* const s; 指针不可变
char const* const s; 指什及内容都不可变

全局初始化区GVAR
全局末初始化区bss
代码区text
堆 heap-队列 先进先出 ,整个程序范围内new,malloc建立,注意delete,free释放,
栈 stack 先进后出,函数体内,语句块{},windows默认大小1M,linux8/10M,ulimit -s查看

内存分配 地址低–>高
代码–>数据(GVAR–>常量–>BSS–> 堆cd )–> 空闲内存 <–栈cc <–系统保留

资源管理方案RAII,依托栈和析构函数管理所有资源,智能指针代表std:auto_ptr(C++11废弃,17删除),销毁时管理的对象也自动deldete,会发生所有权转移
unique_ptr(局限较大),专属所有权,不支持复制和赋值,可以使用std::move()进行控制权的转移
auto w=std:make_unique< int >(10); *(w.get());
auto i = unique_ptr< int>(new int(10));
boost:shared_ptr,引用计数共享一个对象,引用计数为0时没有被使用,可以进行析构销毁,防止循环引用
weak_ptr,观察者模式与shared_ptr共同工作,只对shared_ptr进行引用,不计数,shared_ptr销毁时也一同销毁.

引用是一种特殊的指针,不充许修改的指针,int x=1;int& rx=x;相当于小名,别名

string.h 字符串常用的操作,尽量使用安全的API
底层操作有风险时在预处理器定义#define _CRT_SECURE_NO_WARNINGS,关闭安全警告C4996
strlen(s) 返回字符串的长度,不包含’\0′
strlen_s()
strcmp(s1,s2) 相同返回0,s1<s2返回小于0,否则大于0,自左向右以ASCII值比较
strcpy(s1,s2) 字符串s2拷贝复制到s1,注意s1空间长度
strcpy_s(s1,STR_LEN_NUM,s2)
strnpy(s1,s2,n)字符串s2前n个字符拷贝复制到s1,注意s1空间长度
strnpy_s(s1,STR_LEN_NUM,s2,n)
strcat(s1,s2) 字符串s2拼接到s1,注意s1空间长度
strcat_s(s1,STR_LEN_NUM,s2)
strchr(s1,ch) 查找s1中字符ch的第一次出现位置
strstr(s1,s2) 查找s1中字符串s2的第一次出现位置

string(新)namespace std 对性能要求不是特别高的可以使用
string s; string s=”hello”; string s (“hello”); string s= string(“hello”);
s.length() s.size() s.capacity() == != > >= < <=(比较原则同老版)
转为C风格的字符串const char* c_str = s.c_str();
随机访问某个字符 s[0] == “h”;
字符拷贝 string s2 = s;
连接 +, += string s3 = s+s2; s += s2;

if(p !=NULL){
….
}else if(…){
….
}else{
….
}

switch(){
case: xxx:
{…
break;}
default:
break;
}
while(..){…}
do{…}while(..);
for (…;..;..){…}

重载时函数另一种指针方式调用,每个函数都有一个入口地址
int(p)(int); 定义指针函数,与test函数相对应,数据类型(指针变量名)(参数表)
p=test; 指向test函数
int result = p(1); 调用test函数
注意:int
p(int); //是函数,返回的是一个指针

命名空间
namespace coust{
int test(int);
}
using namespace coust
coust::test(1)

VC++ 调作约定设置影响传参(默认/Gd)
优化-内联函数的扩展->/Ob1
inline int Xxxx(){} 内联过于复杂可能失效

传统的 printf,scanf,getch,gets..坑多可移植性差,不可编程
C++I/O流,可编程,简化编程iostream.h,fstream.h
ios<--istream<--cin
                    <--ifstream
                    |<--iostream <--fstream
    <--ostream<--ofstream
                    <--cout,cerr,clog

streambuf<--strstreambuf
                <--filebuf

IO标准缓存模式:按块(文件),按行(\n),不缓存
#include <iostream> //流
#include <string.h> //使用字符串
#include <string> //使用新字符串
#include <assert> //断言
#include<vector> //动态数组
#include<list> //列表
#include<queue> //队列
#include<stack> //栈
#include<map> //map
#include<algorithm> //算法
#include<memory> //内存
#include <math.h> //数学
vector<int> vec={1,2};
vec.push_back(3);vec.capacity/size(容量/已存贮的个数)
vec.insert(--vec.end(),4);
vec.pop_back();vec.erase(vec.end()-1);

避免同一个文件被include多次
#ifndef _SOMEFILE_H
#define _SOMEFILE_H
…通过宏来防止,可移植性好,无法防止宏名重复,不易排错
#endif //_SOMEFILE_H

#pragma once 通过编译器来防止,易排错,可移植性不好

浅拷贝:只拷贝指针地址,易引发多次释放
深拷贝:拷贝指针指向重新分配堆内存,浪费空间,但不会导致多次释放
写时复制优化策略
引用计数
C++新标准的移动语义

void* NULL nullptr

//C定义
#define NULL ((void *) 0)
//C++定义
#ifndef NULL
    #ifdef _cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif
//C++11定义
nullptr->(void *)0 ,NULL ->0;

类型转换
隐式转换: double f = 1.0/2;
显式转换: (类型说明符)(表达式)
C类型转换时任意类型之间都可以转换,编译器无法判断其正确性,难于错误定位
C++:const_cast用于转换指针或引用,去掉类型的const属性
reinterpret_cast重新解释类型,很危险操作,不检查指向内容,也不检查指针类型本身,但要转换前后的类型所占用内存大小一致,否则引发编译错误
static_cast用于基本转换,有继承关系对象和类指针之间的转换,由程序员确保转换是安全的
dynamic_cast 只能用于含有虚函数的类,必须用在多态体系中,向下转换时如有非法情况对于指针返回NULL


编程思想

设计模式:面向对象可复用的常见23种,反模式,企业应用构架模式…
创建型:结构型:行为型
单列模式-思路有一个私有构造函数,无法通过new直接实例化,包含一个静态私有成员变量instance和静态公有方法instance(),将构造与析构私有化
观察者模式-订阅,解耦
适配器模式(Adapter)-1使用多重继承,接口继承方式.2组合的方式

泛型编程思想
更加直接抽象,静态期多态,将算法 与特定类型,结构剥离,尽可能代码复用 template


STL
空间配制器allocator
容器 序列式string vector list deque 关联式map set multimap multiset
适配器stack queue priority_queue
仿函数greater less …
算法find swap reverse sort merge…
迭代器iterator const_iterator reverse_iterator const_reverse_iterator

for_each()
map<string,double> sts;
sts[“lim”]=99.9; //可修改值
sts.insert(pair<string,double>(“zs”,100.0));
sts.insert(map<string,double>::value_type(“lx”,96.8));
iter =sts.begin();
注意迭代器erase时失效问题,sts.erase(iter++);iter =sts.erase(iter);iter=sts.find(“zs”);sts.erase(iter); int n= sts.erase(‘”zs”);
sts.erase(sts.begin(),sts.end());


引入C
extern “C”{
#include “libavformat/avformat.h”
}

显性包函
#pragma comment(lib,”avformat.lib”)
附加目录
属性-常规:输入-附加依赖项


UI

  1. Duilib
  2. clayui
  3. libuiDK windows
  4. QT IDE->Qt Creator
    https://www.qt.io/
  5. wxWidgets库

网络
1. Linux下的Muduo

  1. BOOST的ASIO库和非boost库版的asio
    http://think-async.com/
    是一个异步IO库,封装了对Socket的常用操作,简化了基于socket程序的开发。支持跨平台。 注:要配置Boost库,还要熟悉Boost,还是麻烦;

  2. libev
    是一个C语言写的,只支持linux系统的库

  3. libuv
    linux下用libev实现,Windows下用IOCP实现;
  4. Libevent
    是一个C语言写的网络库, 官方主要支持的是类linux 操作系统, 最新的版本添加了对windows的IOCP的支持。由于IOCP是异步IO,与linux下的POLL模型,EPOLL模型,还有freebsd的KQUEUE等这些同步模型在用法上完全不一致,所以使用方法也不一样,就好比ACE中的Reactor和Proactor模式一样, 使用起来需要转变思路。如果对性能没有特别的要求, 那么使用libevent中的select模型来实现跨平台的操作, select模型可以横跨windows, linux, unix,solaris等系统。
  5. ACE库
    http://www.cs.wustl.edu/~schmidt/ACE.html
    是一个大型的中间件产品,代码20万行左右,过于宏大,一堆的设计模式,架构了一层又一层,使用的时候, 要根据情况,看你从那一层来进行使用。支持跨平台。注:除非特别需要,否则不建议;
  6. Qt有nerwork

  7. POCO
    POCO C++ Libraries 提供一套 C++ 的类库用以开发基于网络的可移植的应用程序,功能涉及线程、线程同步、文件系统访问、流操作、共享库和类加载、套接字以及网络协议包括:HTTP、 FTP、SMTP 等;其本身还包含一个 HTTP 服务器,提供 XML 的解析和 SQL 数据库的访问接口。POCO库的模块化、高效的设计及实现使得POCO特别适合嵌入式开发。在嵌入式开发领域,由于C++既适合底层(设备I/O、中断处理等)和高层面向对象开发,越来越流行。
    http://pocoproject.org/

  8. libcurl
    libcurl是免费的轻量级的客户端网络库,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet, TFTP. 支持SSL, HTTP POST, HTTP PUT, FTP上传, HTTP form上传,代理,cookies, 用户名与密码认证。
    如果你开发的是客户端,libcurl是一个不错的选择。
    http://curl.haxx.se/libcurl/

  9. c++ sockets library
    封装了sockets C API的C++类库。支持SSL, IPv6, tcp 和 udp sockets, sctp sockets, http协议, 高度可定制的错误处理。
    http://www.alhem.net/Sockets/

  10. C++ Socket Class for Windows ,http://www.adp-gmbh.ch/win/misc/sockets.html;
    注:这个文章的文件不可以下载自己复制 保存 h 和 cpp文件;
    觉得很不错,也很简单,例子很明了; 不过有一个小小的缺点,只收发字符串,而且接收函数中的判断也有点不好;如果要用这个库传输文件等数据,需要 自己重载 收发函数,不过也很简单;

  11. SimpleSockets,
    http://sockets.carrierlabs.com/index.html
    跨平台,支持 TCP ,UDP;注:这个编译简单而且用起来也简单

Halcon

Halcon:机器视觉行业里知名的商业视觉库,非开源的,在国内市场份额处于第一,其提供了1500个多个API算子供开发人员使用,有些编程基础的都可以轻松的入门,其调试也是很方便的,断点单步运行,图像变化随时可以看到。Halcon算子可以被C++,VB,C#,Delphi等开发语言调用,同时算子也提供COM版,原则上,支持COM的所有语言都是可以调用Halcon算子的,所以其开发灵活性和调试方便性深受广大开发者喜欢。

Raspberry 4b

  1. 默认用户密码
    pi raspberry

  2. 查看版本等信息
    pinout
    cat /proc/cpuinfo
    cat /proc/device-tree/model

  3. 开启ssh
    根目录放置空文件ssh

  4. 开机接入无线

country=CN
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="ssid"
    psk="pwd"
    priority=99
}
  1. 系统配制
    sudo raspi-config

    1. 开启VNC
      5 Ingerfacing Options -> P3 VNC
    2. 设置屏幕
      7 Advanced Options -> A5 Resolution
      vncserver -geometry 1920×1080
      vncserver-virtual -geometry 1920×1080 :1
  2. 软件安装
    1. 更新源
      sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
      sudo cp /etc/apt/sources.list.d/raspi.list /etc/apt/sources.list.d/raspi.list.bak
      sudo nano /etc/apt/sources.list
      deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi
      sudo nano /etc/apt/sources.list.d/raspi.list
      deb http://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian/ stretch main ui
      Ctrl+O」进行保存,然后回车,「Ctrl+X」退出
      sudo apt-get update
      sudo apt-get upgrade
    2. wiringPi for c gpio
      sudo apt-get install wiringpi
      4B源码安装:
      wget https://project-downloads.drogon.net/wiringpi-latest.deb
      sudo dpkg -i wiringpi-latest.deb
      gpio -v
    3. PRi.GPIO for python gpio 默认已安装
      sudo apt-get install python-dev
    4. 拼音输入法
      sudo apt-get install scim-pinyin
      sudo apt-get install fcitx fcitx-googlepinyin fcitx-module-cloudpinyin fcitx-sunpinyin fcitx-table-wubi
      启用 fcitx
    5. Berryconda 来替代 Miniconda
      下载 https://github.com/jjhelmus/berryconda
      bash /path/Berryconda3-2.0.0-Linux-armv7l.sh
      conda config –add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
      conda config –add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
      conda config –set show_channel_urls yes
      conda update conda
      conda –version
      python –version
  3. Miniconda python v3.4
    wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-armv7l.sh
    https://docs.conda.io/en/latest/miniconda.html
  4. 建Python虚拟环境 virtualenv 和 virtualenvwrapper
    sudo pip3 install virtualenv virtualenvwrapper
    sudo nano ~/.bashrc
    #virtualenv and virtualenvwrapper 添加内容
    export WORKON_HOME=$HOME/.virtualenvs
    export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
    source /usr/local/bin/virtualenvwrapper.sh
    source ~/.bashrc
    mkvirtualenv py3 -p python3
    workon py3
    pip3 install opencv-contrib-python –upgrade

wiringpi

查看针脚 gpio readall
#include <wiringPi.h>
#include <softPwm.h>
https://www.cnblogs.com/lulipro/p/5992172.html

相机镜头

定焦镜头

  1. 广角镜头:一般低于35mm的镜头为广角镜头,低于28mm的为超广角镜头。广角镜头视角广,纵深感强,景物会有变形,比较适合拍摄较大场景的照片,如建筑、集会等。
  2. 中焦镜头:一般在36mm到134mm的镜头为中焦镜头。中焦镜头比较接近人正常的视角和透视感,景物变形小,适合拍摄人像、风景、旅游纪念照等。
  3. 长焦镜头:一般高于135mm以上的镜头为长焦镜头,也被称为远摄镜头。其中,大于300mm以上的为超长焦镜头。长焦镜头视角小,透视感弱,景物变形小,适合拍摄无法接近的事物,如野生动物、舞台等,也可以利用长焦镜头虚化背景的作用,拍摄人像。

变焦镜头


增倍镜

增倍镜是能够增大相机光学变焦倍数的镜头。如果光学变焦倍数不够,我们可以在镜头前加一增倍镜,其计算方法是这样的,一个2倍的增倍镜,套在一个原来有4倍光学变焦的数码相机上,那么这台数码相机的光学变焦倍数由原来4倍变为8倍,即以增距镜的倍数和光学变焦倍数相乘所得。但是会降低相对应的有效光圈,如2倍增倍镜就会降低相当于2级的有效光圈。但多数对应的镜头仍能完成自动对焦下的拍摄。


传感器

CCD尺寸一般用英寸来表示,1/2就是二分之一英寸,是对角线尺寸。靶面尺寸就是CCD尺寸,数码传感器CCD的尺寸,一英寸换算成毫米是16mm,而不是通常的25.4mm。一般长宽比为4:3

1/2英寸对角线就是8mm,按4:3的比率,长和宽就是6.4X4.8。数码相机的传感器也一样可以这样换算。理论上靶面尺寸越大越好,但是尺寸大跟配合的镜头也有很大关系,所以考虑到性价比,

现在主流的是1/3和1/4,1/3主要用在固定摄像机,1/4主要用在变倍摄像机上。还有1/2主要是用在工业上的,1/2靶面的用镜头都是非球面镜头。要不然看到的图像是有弧度的。

数码相机制造业界通用的规范是:
1 英寸大小=长12.8×宽9.6mm 对角线为16mm 的4:3 比例传感器所对应的面积。
1/2 英寸传感器的对角线就是1 英寸的一半,为8mm,
1/4 英寸就是1 英寸的1/4,对角线长度即为4mm。

CCD/CMOS尺寸越大,感光面积越大,成像效果越好。而相同尺寸的CCD/CMOS像素增加固然是件好事,但这也会导致单个像素的感光面积缩小,有曝光不足的可能。


选型

视野范围FOV
检测精度
工作距离WD
工业相机的分辨率
假设检测一个物体的表面划痕,要求拍摄的物体大小为108mm,要求的检测精度是0.01mm。首先假设我们要拍摄的视野范围在1210mm,那么相机的最低分辨率应该选择在:(12/0.01)(10/0.01)=12001000,约为120万像素的相机,也就是说一个像素对应一个检测的缺陷的话,那么最低分辨率必须不少于120万像素,但市面上常见的是130万像素的相机,因此一般而言是选用130万像素的相机。但实际问题是,如果一个像素对应一个缺陷的话,那么这样的系统一定会极不稳定,因为随便的一个干扰像素点都可能被误认为缺陷,所以我们为了提高系统的精准度和稳定性,最好取缺陷的面积在3到4个像素以上,这样我们选择的相机也就在130万乘3以上,即最低不能少于300万像素,通常采用300万像素的相机为最佳,还应该注意的是,H.264格式非常大。

通信接口:USB 2.0、USB 3.0、GigE、Camera Link、PoE以及VGA
–USB 2.0 :这种较便宜的系统需要通过电缆连接到摄像机(最长可以达到5米)。在理论传输量高达480mbps的情况下,该系统对于数据传输来说可能是不可靠的。现在已被USB 3.0取代
–USB 3.0:此接口与USB 2.0具有相似的功能,但具有更高和更可靠的传输量。
–CameraLink:此通信接口具有非常高的传输量(高达6 Gbits/s),非常适合高分辨率。价格较高。 电缆长度可以达到10米。
–GigE(或Giga以太网):这种比较便宜的通信接口的传输量高达1 Gbit/s,如果您需要较长的电缆长度(它可以达到100米),就可以选择这种接口。
–PoE(或以太网供电):它的传输量可达1 Gbit/s,其主要优点是可以在进行数据通信时为摄像机供电。
–VGA(视频图形阵列):VGA卡考虑到640×480的分辨率。它们可以传送多达256种颜色。这个接口开始消失了。

像传感器类型:
CCD
拍运动物体,首先CCD
CCD传感器价格较低。它们的优点是性价比非常高。但是,CCD传感器的检测光谱只对可见元素敏感。此外,它们的缺点是对炫光非常敏感,并且有许多寄生电子,这些电子随温度急剧增加。因此需要冷却CCD传感器以避免产生热噪音。
CMOS
在拍运动物体, CMOS采用帧爆光的可以代替CCD
CMOS传感器比CCD传感器的价格更昂贵,但具有很多优点。首先,与CCD传感器相比,它们的质量更高(尽管最新一代CCD传感器的技术使其更接近CMOS传感器)。更重要的是,它们适用于微光视觉。因此,弱光照水平不会造成任何问题。CMOS传感器的读取速度也比大多数CCD传感器高,而且更节能。
CMOS传感器与CCD传感器一样,并用于相同的应用(扫描仪、实验室、包装线监测等)。
FPA
FPA传感器的主要优点是其非常高的灵敏度和出色的图像质量。但是,图像分辨率不是很高(通常为320 x 240像素)。这种图像传感器非常大而且很昂贵,可以用于武器制导和检查摄像机,以及空间和医学成像。
微辐射热测量计
微辐射热计传感器仅用于热像仪,主要使用红外辐射。微辐射热计摄像机机重量轻,节能,可以实现非常快速的输出通信。也就是说,它们非常昂贵。此外,它们比冷却温度传感器敏感度低,因为像CCD传感器一样,寄生电子的数量随着温度的升高而增加。这可能会导致分辨率问题。但是,当前的技术倾向于解决这些问题,从而使微辐射热计传感器更加高效。
得益于其重量轻、体积小和低功耗,可以将微辐射热计传感器安装在施工头盔或便携式设备上。

色彩:
黑白:一般黑白
彩色:与图像颜色有关

帧率
根据要检测的速度,选择相机的帧率一定要大于或等于检测速度,就是你处理图像的时间一定要快,一定要在相机的曝光和传输的时间内完成。

面阵,线阵
在速度快,精度高,面阵达不到的情况下用线阵

光源

  1. 条形光源特点:
    1. LED均成直线或其组合排列,照度高,光源指向性强,照明效果也符合直线型规律或其叠加。
    2. 采用特殊光学透镜,有效改变LED照射角度。
    3. 采用标准模具成型、拼接安装,结构稳定
    4. 可选漫射版导光,光线均匀。
    5. 尺寸、颜色可以根据实际需求定制。
    6. 条光照射宽度最好大于检测的距离,否则可能会照射距离远造成亮度差,或者是距离近而幅射面积不够;
    7. 条光长度能够照明所需打亮的位置即可,无须太长造成安装不便,同时也增加成本,一般情况下,光源的安装高度会影响到所选用条光的长度,高度越高,光源长度要求越长,否则图像两侧亮度传经比中间暗;
    8. 如果照明目标是高反光物体,最好加上漫射板,如果是黑色等暗色不反光产品,也可以拆掉漫射板以提高亮度。
    9. 应用场合:可用于电子元件识别与缺陷检测;文字、形状识别等;

环形光源分为垂直照射环形光源,角度照射环形光源,低角度环形光源,无影环形光源。
1. 了解光源安装距离,过滤掉某些角度光源;例如要求光源安装尺寸高,就可以过滤掉大角度光源,选择用小角度光源,同样,安装高度越高,要求光源的直径越大;
1. 目标面积小,且主要特性在表面中间,可选择小尺寸0角度或小角度光源;
1. 目标需要表现的特征如果在边缘,可选择90度角环光,或大尺寸高角度环形光;
1. 检测表面划伤,可选择90度角环光,尽量选择波长短的光源。

  1. 垂直照射环形光源的特点:
    1. 用高亮度LED高密度安装,提供红、绿、蓝、白、红外、紫外等颜色;
    2. 照明面积较大,光照均匀性好,适用于较大面积照明;
    3. 可用于底基和线路板定位、晶片部件的检查等。

角度照射环形光源的特点:
1. 用超高亮度LED高密度安装,提供红、绿、蓝、白、红外、紫外等颜色;
1. 在一定工作距离下,光束集中亮度高,均匀性好,照射面积相对较小;
1. 用于塑胶容器检查、工件螺孔定位、标签检测、管脚、集成电路印子检测等类似用途。
1. 用于文字形状识别和缺陷检测。

低角度环形光源的特点:
1. 用超高亮度LED进行水平照射,提供红、绿、蓝、白、红外、紫外等颜色;
1. 低角度照射光照明对表面凹凸表现力强,特别适用于晶片或者玻璃底基上的伤痕检测,刻印文字的读取、工件边缘轮廓抽取、划痕检测等。

无影环形光源的特点:
1. 使用超高亮度LED进行光线垂直照射,提供红、绿、蓝、白、红外、紫外等颜色;
1. 漫反射二次光源,光照均匀,无影效果,对镜面反射体如晶片或玻璃基底上的伤痕检测,金属表面检测效果突出。

背光源的特点:
1. 选择背光源时,根据物体的大小选择合适大小的背光源,以免增加成本造成浪费
1. 背光源四周一条由于的外壳遮挡,因此其亮度会低于中间部位,因此,选择背光源时,尽量不要使目标正好位于背光源边缘;
1. 背光源一般在检测轮廓时,可以尽量使用波长短的光源,波长短的光源其衍射性弱,图像边缘不容易产生重影,对比度更高;
1. 背光源与目标之间的距离可以通过调整来达到最佳的效果,并非离得越近效果越好,也非越远越好;
1. 检测液位可以将背光源侧立使用;
1. 圆轴类的产品,螺旋状的产品尽量使用平行背光源。
1. 使用超高亮度LED进行正面垂直照射,提供红、绿、蓝、白、红外、紫外等颜色;
1. 经过特殊导光材料优化光路,平行性好;
1. 适合外观检测,或者尺寸测量;
1. 可安装于底部背光源和侧部背光源表面;

同轴光源的特点:
1. 采用特殊照明设计,达到高均匀性;
1. 特殊导热材料,散热好,稳定性高;
1. 使用分镜头,提供优质光学效果;
1. 选择同轴光时主要看其发光面积,根据目标的大小来选择合适发光面积的同轴光;
1. 同轴光的发光面积最好比目标尺寸大1.5~2倍左右,因为同轴光的光路设计是让光路通过一片45度半反半透镜改变,光源靠近灯板的地方会比远离灯板的亮度高,因此,尽量选择大一点的发光面避免光线左右不均匀;
1. 同轴光在安装时尽量不要离目标太高,越高,要求选用的同轴光越大,才能保证才均匀性。
1. 广泛用于半导体、PCB板、以及金属零件的表面成像检测,具有很好的均匀性,对光洁表面上的异常特征成像突出,表现力好。

平行同轴光
1. 平行同轴光光路设计独特,主要适用于检测各种划痕;
1. 平行同轴光与同轴光表现的牲点不一样,不能替代同轴光使用;
1. 平行同轴光检测划伤之类的产品,尽量不要选择波长长的光源。

点光源的特点:
1. 使用大功率LED,颜色可选,体积小,发光强度高;
1. 可组合使用做重点照明或者补光照明;
1. 光钎卤素灯的替代品,可配合同轴镜头代替同轴光使用。


各种颜色的光源适用场景介绍:

1. 白色光源(W)
白色光源通常用色温来界定,色温高的颜色偏蓝色(冷色,色温>5000K),色温低的颜色偏红(暖色,色温<3300K),界于3300与5000K之间称之为中间色,白色光源适用性广,亮度高,特别是拍摄彩色图像时使用更多。

  1. 蓝色光源(B)
    蓝色光源波光为430-480之间,适用产品:银色背景产品(如钣金,车加工件等)、薄膜上金属印刷品。

  2. 红色光源(R)
    红色光源的波长通常在600-720之间,其波长比较长,可以透过一些比较暗的物体,例如底材黑色的透明软板孔位定位、绿色线路板线路线路检测,透光膜厚度检测等,采用红色光源更能提高对比度。

  3. 绿色光源(G)
    绿色光源波长510-530,界于红色与蓝色之间,主要针对产品:红色背景产品,银色背景产品(如钣金,车加工件等)。

  4. 红外光(IR)
    红外光的波长一般为780-1400,大多采用940波长的红外光,红外光属于不可见光,其透过力强。一般LCD屏检测、视频监控行业应用比较普遍。

  5. 紫外光(UV)
    紫外光的波长一般为190-400,我司主要采用385波长的紫外光,其波长短,穿透力强,主要应用于证件检测、触摸屏ITO检测、布料表面破损、点胶溢胶检测等方面,金属表面划痕检测等。

常见的打光方式有以下几种:前面打光法;背面打光法;结构光打光法;混合多方式照明;特殊式打光法。
1. 光源垂直照射
特点:照射面积大、光照均匀性好、适用于较大面积照明。可用于基底和线路板定位、晶片部件检查等(0角度环光、面光源)。
1. 角度照射
特点:在一定工作距离下,光束集中、亮度高、均匀性好、照射面积相对较小。常用于液晶校正、塑胶容器检查、工件螺孔定位、标签检查、管脚检查、集成电路印字检查等(30、45、60、75等角度环光)。注意观察光源的角度。
1. 低角度照射
特点:对表面凹凸表现力强。适用于晶片或玻璃基片上的伤痕检查(90度环光
)。
1. 背光照射
特点:发光面是一个漫射面,均匀性好。可用于镜面反射材料,如晶片或玻璃基底上的伤痕检测;LCD检测;微小电子元件尺寸、形状,靶标测试。(背光源、平行背光源)。
1. 多角度照射
特点:RGB三种不同颜色不同角度光照,可以实现焊点的三维信息的提取。适用于组装机板的焊锡部份、球形或半圆形物体、其它奇怪形状物体、接脚头(AOI光源)。
1. 同轴光照明
特点:类似于平行光的应用,光源前面带漫反射板,形成二次光源,光线主要趋于平行。用于半导体、PCB板、以及金属零件的表面成像检测,微小元件的外形、尺寸测量。(同轴光源,平行同轴光源)

scikit-learn机器学习

from sklearn import metrics

评分函数评估模型性能

对分类器评分
1. metrics.accuracy_score(y_true,y_pred) 准确率
1. metrics.precision_score(y_true,y_pred) 精确率
1. metrics.recall_score(y_true,y_pred) 召回率(敏感率)

对回归器评分
1. metrics.mean_squared_error(y_true,y_pred) 均方差
1. metrics.explained_variance_score(y_true,y_pred) 可释方差
1. metrics.r2_score(y_true,y_pred) R方值


k-NN算法

k邻近算法 一个数据点很可能与它邻近的点属于同类

# 1. 生成训练数据
train_data, labels = generate_data(11)
# 分离标签数据
blue = train_data[labels.ravel() == 0]
red = train_data[labels.ravel() == 1]
# 画出所有点
plot_data(blue, red)

# 2. 训练分类器
# 创建分类器
knn = cv2.ml.KNearest_create()
# 传入训练数据 成功返回True
knn.train(train_data, cv2.ml.ROW_SAMPLE, labels)

# 3. 预测新数据点的类别
# 生成新的点
newcomer, _ = generate_data(1)
# 绘制新的点
plt.plot(newcomer[0, 0], newcomer[0, 1], 'go', markersize=14)
plt.show()
# 根据最近邻数据点的标签预测新数据点的标签
ret, results, neighbor, dist = knn.findNearest(newcomer, k=3)
print('Predicted label: \t', results)
print('Neighbor label: \t', neighbor)
print('Distance to Neighbor: ', dist)

回归模型预测连续后果

  1. 线性回归, 通过特征的线性组合描述目标变量 如房价预测
    linreg = linear_model.LinearRegression()
    正侧化-降低过拟合过程,
    L1-Lasso回归 linreg = linear_model.Lasso()
    L2-ridge回归 linreg = linear_model.Ridge() /linear_model.RidgeRegression()
  2. 逻辑回归 用于目标的分类模型,把任意输入的实值x转为0~1区间的一个预测值,比如判定物品的种类
    linreg = cv2.ml.LogisticRegression_create()

特征工程

特征选择,特征提取

  1. 数据预处理
    数据格式化,数据清理,数据采样

    1. 特征标准化
      每个点减去所有数据的平均值再除以方差
      x_scaled = preprocessing.scale(x)
      x_scaled.mean(axis=0) 每行均值近似为0 x_scaled.std(axis=0) 每行方差为1
    2. 特征归一化
      L1范数(曼哈顿距离) l1=preprocessing.normalize(X,norm=’l1′)
      L2范数(欧氏距离) l2=preprocessing.normalize(X,norm=’l2′)
    3. 特征缩放在一定范围,一般0~1内
      min_max_scaler = preprocessing.MinMaxScaler() or MinMaxScaler(feature_range(-10,10))
      X_min_max = min_max_scaler.fit_transform(x)
    4. 特征二值化
      binarizer = preprocessing.Binarizer(threshold=0.5)
    5. 缺失数据处理
      mean将nan值换为指定坐标元素的平均值,默认axis=0
      median将nan值换为指定坐标元素的中值,默认axis=0
      most_frequest将nan值换为指定坐标元素中出现频率最高值,默认axis=0
      imp = preprocessing.Imputer(strategy=’mean’)
      x2= imp.fit_transform(x)
  2. 理解降维
    1. 主要成分分析PCA
      特征向量x和y组合成一个特征矩阵X
      x=np.vstack((x,y)).T
      矩阵X上计算PCA,mu投影前减去的平均值eig协方差矩阵的特征向量
      mu, eig = cv2.PCACompute(X,np.array([]))
      旋转投影数据
      x2=cv2.PACAProject(X,mu,eig)
    2. 独立成分分析ICA
      ica=decomposition.FastICA()
      x2=ica.fit_transform(x)
    3. 非负矩阵分解NMF
      nmf = decomposition.NMF()
      x2=nmf.fit_transform(x)
  3. 类别变量表示 类别特征(离散特征)
    独热编码 form sklearn.feature_extraction import DictVectorizer
    vec = DictVectorizer(aparse=False,dtype=int) or aparse=True稀疏矩阵紧凑表示
    vec.fit_transform(data)
    查看特征的顺序表
    vec.get_feature_names()
    某些算法如决策树,本身可以处理类别特征,不再需要使用独热编码

  4. 文本特征表示

    1. 单词计数 缺点:频繁出现的单词赋予过大权重
      form sklearn.feature_extraction.text import CountVectorizer
      vec = CountVectorizer()
      x = vec.fit_transform(data) 将特征矩X保存为一个稀疏矩阵
      x.toarray() 稀疏矩阵转换为常规数组
      vec.get_feature_names() 查看特征名字
      1.词频-逆文档频率TF-IDF 衡量单词在整个数据中出现的频率计算权重
      form sklearn.feature_extraction.text import TfidfVectorizer
      vec = TfidfVectorizer()
      x = vec.fit_transform(data) 将特征矩X保存为一个稀疏矩阵
      x.toarray() 稀疏矩阵转换为常规数组
  5. 图像表示
    1.使用色彩空间

    1. RGB,openCV中是BGR
      img_rgb=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
    2. HSV / HLS /LAB / YUV
      cv2.COLOR_BGR2HSV …

    2.图像角点检测

    1. Harris角点检测(仅灰度图像) corners=cv2.cornerHarris(img_gray,blockSize,Ksize,k)
    2. Shi-Tomasi角点检测 cv2.goodFeaturesToTrack

    3.尺度不度特征变换SIFT
    sift = cv2.xfeatures2d.SIFT_create()

    1. kp = sift.detect(img_bgr) 关键点
      关键点可视化
      img_kp = np.zeros_like(img_bgr)
      img_kp = cv2.drawkeypoints(img_rgb,kp,img_kp,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
      plt.show()
      计算关键点的特征值
      kp,des=sift.compute(img_bgr,kp) des的每个关键点有128个特征值
    2. 一步检测关键点并计算出特征描述符
      kp2,des2=sift.detectAndCompute(img_bgr,None)
      可以比较des与des2是否相等 print(np.allclose(des,des2))

    4.加速键状特征SURF
    与SIFT一样使用,且商业使用需要授权,比SIFT能得到更多特征,速度更快
    surf = cv2.xfeatures2d.SURF_create()

    5.cv2.ORB 开源代替SIFT,SURF方案
    使用FAST关键点检测子和BRIEF描述符


决策树

决策树是一个简单有效的监督学习算法
1. 数据预处理
得到训练集和测试集
1. 构建决策树
dtree=cv2.ml.dtree_create()
1. 训练决策树
dtree.train=(X_train,cv2.ml.ROW_SAMPLE,y_train)
1. 预测新数据点标签类别
y_pred=dtree.predict(x_test)
1. 检测算法性能-准确率
metrics.accuracy_score(y_test,dtree.predict(X_test)) 测试样本
metrics.accuracy_score(y_train,dtree.predict(X_train)) 训练数据

  1. 可视化训练决策树
    from sklearn import tree
    构造一个空的决策树
    dtc = tree.DecisionTreeClassifier(class_weigth=None,criterion=’gini’ ,max_depth=None,max_features=None,max_leaf_nodes=None,min_impurity_split=1e-07,min_samples_leaf=1,min_samples_split=2,min_weight_fraction_leaf=0.0,presort=False,random_state=None,splitter=’best’)
    fit训练决策树
    dtc.fit(X_train,y_train)
    DecisionTreeClassifier()
    测试准确率
    dtc.score(X_train,y_train)
    dtc.score(X_test,y_test)
    生成决策树文件.Pdf
    $conda install graphviz
    with open(‘tree.dot’,’w’): f=tree.export_graphviz(clf,out_file=f)
    $dot -Tpng tree.dot -o tree.png
    特征重要性评分
    dtc.feature_importances_
    决策规则
    criterion=’gini’ 基尼不纯度,目标是最小化分类错误的概率
    criterion=’entropy’ 信息增益,计算熵,选最低的,完美为0
    控制树的复杂度,避免过拟合,使用预剪枝和后剪枝
    max_depth控制最大深度
    max_leaf_nodes 最多叶结点数量
    min_samples_split 最小数据点数量持续对决策树进行分割
    更复杂的场景使用随机森林

线性回归不能使用gini,entropy,作为代替mse方差缩减,计算真实值和预测值的均方误差 mae计算真实值和预测值的平均绝对值差


支持向量机 SVM

是一种二分化模型,把无法线性分隔的数据映射到高维空间后再找到分类器最优的线性分类器,是一种基于关键点的分类算法,支持向量是离分类器最近的那些点.机器是指分类器,离分类器最近的点到分类器的距离称为间隔,希望间隔尽可能大,就会更准确,也称最大边缘分类器
1. opencv
生成用于后续训练的空分类器模型
svm = cv2.ml.SVM_create()
训练结果 = svm.train(训练数据,训练数据排列格式,训练数据的标签)
训练数据排列格式 cv2.ml.ROW_SAMPLE 按行 cv2.ml.COL_SAMPLE 按列
(返回值,返回结果) = svm.predict(测试数据)
参数调整:setType()设置类别 setKernel()设置核类型 setC()设置支持向量机的参数C(惩罚系数,对误差的宽容度,默认0)
1. sk-learn库
生成可以控制大小和复杂度的随机数据集
make_classification生成随机的n类分类问题,make_regression随机的回归问题,
X, y = datasets.make_classification(n_samples=100, n_features=2,n_redundant=0, n_classes=2,random_state=7816)
方向梯度直方图HOG,是一个图像的特征描述符,常用于人物人类,基本思想对像的局部形状和外观可以使用边缘方向的分布来表示,特别适合纹理丰富的数据.
hog = cv2.HOGDescriptor(win_size, block_size, block_stride, cell_size, num_bins)
调用hog.compute构建样本
X_pos.append(hog.compute(img, (64, 64)))

  1. LIBSVM

贝叶斯学习

一个事件的发生概率可以基于条件的先验知识进行估计,可以用于数据分类,分类正确概率估计.
判别模型,生成模型

# 使用正态贝叶斯分类器
model_norm = cv2.ml.NormalBayesClassifier_create()
# 训练
model_norm.train(X_train, cv2.ml.ROW_SAMPLE, y_train)
# 预测测试
_, y_pred = model_norm.predict(X_test)
# 预测测试评分
print(metrics.accuracy_score(y_test, y_pred))

# 使用朴素贝叶斯分类器
model_naive = naive_bayes.GaussianNB()
# 训练分类器
model_naive.fit(X_train, y_train)
GaussianNB(priors=None)
# 对分类器打分
print('GaussianNB score:', model_naive.score(X_test, y_test))
# 显示决策边界
plot_decision_boundary(model_norm, X, y)
plt.show()
# 预测测试数据,返回y_proba真正概率
yprob = model_naive.predict_proba(X_test)
print(yprob.round(2))

# 使用完整数据训练,需要更复杂的方法,sklearn中的朴素贝叶斯分类器可以处理稀疏矩阵
model_naive = naive_bayes.MultinomialNB()
model_naive.fit(X_train, y_train)

# 使用n-gram提升结果,考虑单词的顺序,但对于更长的文本无法有效的评估权重
counts = feature_extraction.text.CountVectorizer(ngram_range=(1, 2))
X = counts.fit_transform(data['text'].values)
# 分隔
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.2, random_state=42)
# 训练数据
model_naive = naive_bayes.MultinomialNB()
model_naive.fit(X_train, y_train)
MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)

# 使用TD-IDF提升结果 词频-逆文档频率
tfidf = feature_extraction.text.TfidfTransformer()
X_new = tfidf.fit_transform(X)
X_train, X_test, y_train, y_test = ms.train_test_split(X_new, y, test_size=0.2, random_state=42)
model_naive = naive_bayes.MultinomialNB()
model_naive.fit(X_train, y_train)

非监督学习

降维,因子分析,聚类分析,评估方式使用手动检查,可以作为预处理或特征提取的步骤.
retval,bestLabels,centers = cv2.kmeans(data,K,bestLables,criteria,attempts,flags)
retval 距离值,返回每个点到相应中心距离的平方和,较高紧凑度表明所有点更靠近它们的聚类中心
bestLabels 各个数据点的最终分类标签(索引)
centers 每个分类的中心点数据
data 待处理的数据集合,np.float32类型,每个特征单独一列中
K 要分出簇的个数,常见2,表示2分类
bestLables 各个数据点的最终分类标签(索引),实际中设为None
criteria 算法迭代的终止条件,达到最大循环数目和指定精度阀值时终止,由3个参数构成type,max_iter,eps
type: cv2.TEEM_CRITERIA_EPS 精度满足 MAX_ITER 迭代次数超过阀值max_iter时停止 _EPS+MAX_ITER两个任意一个满足停止
max_iter 最大迭代次数
eps 精确度的阀值
attempts 使用不用的初始值多次(attempts次)偿试
flags 选择初始中心点的方法,主要有3种cv2.KMEANS_RANDOM_CENTERS 随机 cv2.KMEANS_PP_CENTERS基于中心算法 cv2.KMEANS_USE_INITIAL_LABELS 使用用户输入的数据作为第一次分类的中心点,需要多次偿试时后续使用随机或半随机值作为第一次分类中心点

迭代方法,k均值聚类期望最大化 , 高斯混合模型GMM

局限性
无法保证全局最优解(常常让算法在多个初始状态运行)
必须知道聚类个数(肘部法则,轮廓分析,高斯混合模型GMM使用贝叶斯信息准则获得正确数量,具有噪声的基于密度聚类DBSCAN,邻近传播算法)
决策边界是线性的(sklearn谱聚类SpectralClustering)
处理大数据时非常慢(sklearn谱聚类cluster.MiniBatchKMeans)

应用
压缩色彩空间 虽丢失一些细节,介仍可以清楚被识别,另一个方法使用双边滤波器
进行图像分类
字类识别
组织成层次树(c++API 快速最近邻逼近搜索函数cv::flann:hierarchicalClustering sklern自行实现cluster.AgglomerativeClustering)

# 创建4个不同的聚类,一共300个数据点
X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=1.0, random_state=10)
# 算法迭代的终止条件
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
# 选择初始中心点的方法
flags = cv2.KMEANS_RANDOM_CENTERS
# 聚类分析 指定聚类4,算法初始随机选择尝试次数10
compactness, labels, centers = cv2.kmeans(X.astype(np.float32), 4, None, criteria, 10, flags)

深度学习

人工神经网络 Google-DeepMind Facebook-DeepFace, Keras
McCulloch-Pitts神经元:本质上是一个线性的二元分类器,一般需要训练数据,代价函数,学习规则
感知器:只有当数据是线性可分,且学习率足够小的情况下,感知学习规则才可以保证收敛于最优解
把感知器应用到线性不可分的数据上时,测试结果失败,不存在一条直线可以完美分割
多层感知器MLP,万能逼近特性,给它足够的神经元和层,基本上可以学习任意的输入-输出函数
梯度下降:陷入局部最小值,解决方法可以添加噪声
使用反向传播训练多层感知器,用于估计神经网络中代价函数梯度, 链式法则

# 创建MLP分类器
mlp = cv2.ml.ANN_MLP_create()
# 第一层两个神经元
n_input = 2
# 单个隐藏层8个神经元
n_hidden = 8
# 最后一层两个神经元
n_output = 2
mlp.setLayerSizes(np.array([n_input, n_hidden, n_output]))

# 定制MLP分类器
# 定义网络中每个神经元的激活函数,可以使用自定或openCV
mlp.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM, 2.5, 1.0)
# 定义一个合适的训练方法
mlp.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)
# 设置训练过程的终止条件
term_mode = cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS
term_max_iter = 300
term_eps = 0.01
mlp.setTermCriteria((term_mode, term_max_iter, term_eps))

# openCV提供激活函数
# cv2.ml.ANN_MLP_IDENTITY 线性激活函数f(x)=x
# cv2.ml.ANN_MLP_SIGMOID_SYM 对称的sigmoid双曲正切
# cv2.ml.ANN_GAUSSIAN 高斯函数 贝尔曲线

# 训练方法
# cv2.ml.ANN_MLP_BACKPROP 反向传播算法,通过mlp.setBackpropMomentumScale 和 mlp.setBackpropWeightScale设置额外的比例因子
# cv2.ml.ANN_MLP_RPROP Rprop算法 通过mlp.setRpropDW0, mlp.setRpropDWMax, mlp.setRpropDWMin, mlp.setRpropDWMinus,  \
#                              mlp.setRpropDWPlus设置额外的参数

# 训练MLP分类器
mlp.train(X, cv2.ml.ROW_SAMPLE, y)
# 预测目标标签
_, y_hat = mlp.predict(X)
# 测量准确率
print(accuracy_score(y_hat.round(), y))


深度学习,人工神经网络开源学习框架
谷歌 TensorFlow
微软 Cognitive Toolkit CNTK
加州大学伯克利分校 Caffe
蒙特利尔大学 Theano
Torch 基于Lua编程语言
Keras 定位一个接口


不同的算法组合

装袋方法(Bagging)
提升方法(Boosting)
随机森林(Random Forest)
自适应提升(AdaBoost)

合适的模型

选择正确的模型就是在偏差和方差之间找一个平衡

交叉验证
常用k折交叉验证,k是用户指定的数字(一般5或10),数据被分成大小差不多相等的k个部分,叫作折,使用k-1折用于训练,另一折用于测试,过程重复进行k次迭代,每次选择不同的折进行测试.
比把数据集分割为训练集和测试集更加稳定和全面

留一法交叉验证

自举
通过使用替代的方法来抽取样本

评估结果’
T检验 两个数据样本是否来自于相同的平均值或者期望值的潜在分布,返回参数p来接受或者驳回一个虚假设,p在0~1内,p=0.05表示这个虚假设仅在100次中正确5次
配对卡方检验 可以用在对对的数据上,来确定两个样本之间是否有任何差异

数据分类:
训练集: 用于构建模型
验证集: 用于选择模型的参数
测试集: 用于评估最终模型的性能

网格搜索结合交叉验证 GridSearchCV
网格搜索嵌套交叉验证
F值(计算精准率和召回率的调和平均值) 公式 2(精准率X召回率)/(精准率+召回率)
设置作业点 PR曲线工具
回归指标:
1. 均方误差 sklearn.metrics.mean_squared_error
1. 可释方差sklearn.metrics.explained_variance_score
1. R2值 sklearn.metrics.r2_score 大部分应用,使用默认的R2就够了
管道 Pipeline


如何解决问题

  1. 问题分类
    1. 按输入分类: 数据已标记,监督学习,通过环境交互来优化,强化学习,没有被标记,非监督学习
    2. 按输出分类: 输出的是数字,回归问题,输出是一个类,分类问题
  2. 找到可用的算法
    可参见速查表 http://aka.ms/MLCheatSheet
  3. 原型构建(实现所有适用的算法)
    1. 使用最少的特征工程,临时应急地实现多个算法
    2. 理想情况下,可以设置一个机器学习管道,使用一组精心准备的指标评测
    3. 特征工程 很重要
    4. 优化超参数

构建自己的估计器

  1. ClassifierMixin if you are writing a classifier (will provide a basic score method) 写一个分类器时
  2. RegressorMixin if you are writing a regressor (will provide a basic score method) 写一个回归器时
  3. ClusterMixin if you are writing a clustering algorithm (will provide a basic fit_predict method) 写一个聚类算法时
  4. TransformerMixin if you are writing a transformer (will provide a basic fit_predict method) 写一个转换器时

    importing BaseEstimator and ClassifierMixin
    class MyClassifier(BaseEstimator, ClassifierMixin):

常用数据集

  1. scikit-learn 内置数据样集
  2. scikit-learn 外部服务载入 mldata.org 参考http://scikit-learn.org/stable/datasets/index.html
  3. Kaggle http://www.kaggle.com 经常比赛,提供一个特定要优化的指标
  4. OpenML http://www.openml.org
  5. 加州大学欧文分校 http://archive.ics.uci.edu/ml/index.php

pysimplegui

https://pysimplegui.readthedocs.io/en/latest/

pip install pysimplegui
pip3 install pysimplegui

sudo apt-get install python3-tk


import PySimpleGUI as sg
print(sg)
print(sg.version)

Popup(args=*<1 or N object>,
    title=None,
    button_color=None,
    background_color=None,
    text_color=None,
    button_type=0,
    auto_close=False,
    auto_close_duration=None,
    custom_text=(None, None),
    non_blocking=False,
    icon=None,
    line_width=None,
    font=None,
    no_titlebar=False,
    grab_anywhere=False,
    keep_on_top=False,
    location=(None, None),
    any_key_closes=False,
    image=None,
    modal=True)

sg.popup('popup')  # Shows OK button
sg.popup_ok('popup_ok')  # Shows OK button
sg.popup_yes_no('popup_yes_no')  # Shows Yes and No buttons
sg.popup_cancel('popup_cancel')  # Shows Cancelled button
sg.popup_ok_cancel('popup_ok_cancel')  # Shows OK and Cancel buttons
sg.popup_error('popup_error')  # Shows red error button
sg.popup_timed('popup_timed')  # Automatically closes
sg.popup_auto_close('popup_auto_close')  # Same as PopupTimed

popup_scrolled(args=*<1 or N object>,
    title=None,
    button_color=None,
    background_color=None,
    text_color=None,
    yes_no=False,
    auto_close=False,
    auto_close_duration=None,
    size=(None, None),
    location=(None, None),
    non_blocking=False,
    no_titlebar=False,
    grab_anywhere=False,
    keep_on_top=False,
    font=None,
    image=None,
    modal=True)
sg.popup_scrolled(my_text)
sg.popup_scrolled(my_text, size=(80, None))

popup_no_wait(args=*<1 or N object>,
    title=None,
    button_type=0,
    button_color=None,
    background_color=None,
    text_color=None,
    auto_close=False,
    auto_close_duration=None,
    non_blocking=True,
    icon=None,
    line_width=None,
    font=None,
    no_titlebar=False,
    grab_anywhere=False,
    keep_on_top=False,
    location=(None, None),
    image=None,
    modal=False)

popup_get_text(message,
    title=None,
    default_text="",
    password_char="",
    size=(None, None),
    button_color=None,
    background_color=None,
    text_color=None,
    icon=None,
    font=None,
    no_titlebar=False,
    grab_anywhere=False,
    keep_on_top=False,
    location=(None, None),
    image=None,
    modal=True)
text = sg.popup_get_text('Title', 'Please input something')
sg.popup('Results', 'The value returned from PopupGetText', text)

popup_get_file(message,
    title=None,
    default_path="",
    default_extension="",
    save_as=False,
    multiple_files=False,
    file_types=(('ALL Files', '*.*'),),
    no_window=False,
    size=(None, None),
    button_color=None,
    background_color=None,
    text_color=None,
    icon=None,
    font=None,
    no_titlebar=False,
    grab_anywhere=False,
    keep_on_top=False,
    location=(None, None),
    initial_folder=None,
    image=None,
    modal=True)

popup_get_folder(message,
    title=None,
    default_path="",
    no_window=False,
    size=(None, None),
    button_color=None,
    background_color=None,
    text_color=None,
    icon=None,
    font=None,
    no_titlebar=False,
    grab_anywhere=False,
    keep_on_top=False,
    location=(None, None),
    initial_folder=None,
    image=None,
    modal=True)

popup_animated(image_source,
    message=None,
    background_color=None,
    text_color=None,
    font=None,
    no_titlebar=True,
    grab_anywhere=True,
    keep_on_top=True,
    location=(None, None),
    alpha_channel=None,
    time_between_frames=0,
    transparent_color=None,
    title="",
    icon=None)

one_line_progress_meter(title,
    current_value,
    max_value,
    key="OK for 1 meter",
    args=*<1 or N object>,
    orientation="v",
    bar_color=(None, None),
    button_color=None,
    size=(20, 20),
    border_width=None,
    grab_anywhere=False,
    no_titlebar=False)
for i in range(1,10000):
    sg.one_line_progress_meter('My Meter', i+1, 10000, 'key','Optional message')

Debug Output(easy_print = Print = eprint)
for i in range(100):
    sg.Print(i)

sg.theme('Dark Blue 3')  # please make your windows colorful
layout = [ [sg.Text('Enter a Number')],
           [sg.Input()],
           [sg.OK()] ],
           [sg.InputText(), sg.FileBrowse()],
           [sg.Submit(), sg.Cancel()]]

window = sg.Window('Enter a number example', layout)
event, values = window.read()

使用菜单
# ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
            ['&Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
            ['&Help', '&About...'], ]
layout = [
    [sg.Menu(menu_def, tearoff=True)],

    # 定义右键菜单
    right_click_menu = ['Unused', ['Right::_Right_', '!&Click', '&Menu', 'E&xit', 'Properties']]
    # 定义布局
    layout = [[sg.Menu(menu_def, tearoff=False, pad=(20,1))],
               # 底部菜单
              [sg.ButtonMenu('ButtonMenu',key='-BMENU-', menu_def=menu_def[0])],]
    # 定义 Window
    window = sg.Window("Windows-like program",layout,
                       default_element_size=(12, 1),
                       grab_anywhere=True, # 非阻塞
                       right_click_menu=right_click_menu, # 添加右键菜单
                       default_button_element_size=(12, 1)
                      )
'Right::_Right_' 是指定该菜单的 Key 的方式。!禁用

Theme Name
There are 130 themes available. You can preview these themes by calling theme_previewer() which will create a LARGE window displaying all of the color themes available. Default is Dark Blue 3
Dark Color #
or
Light Color #
DarkAmber
    # print(sg.ListOfLookAndFeelValues())
    # ['SystemDefault', 'Reddit', 'Topanga', 'GreenTan', 'Dark', 'LightGreen', 'Dark2', 'Black', 'Tan', 'TanBlue',
    # 'DarkTanBlue', 'DarkAmber', 'DarkBlue', 'Reds', 'Green', 'BluePurple', 'Purple', 'BlueMono', 'GreenMono',
    # 'BrownBlue', 'BrightColors', 'NeutralBlue', 'Kayak', 'SandyBeach', 'TealMono']
sg.theme()窗口样式
sg.theme('BluePurple')
要查看您的PySimpleGUI版本的上述预览,请进行以下调用以生成所有可用主题的预览:
sg.theme_previewer()
如果您想在系统上看到一个窗口,如上面的主题预览屏幕截图,那么进行此调用,您将看到相同的窗口:
import PySimpleGUI as sg
sg.preview_all_look_and_feel_themes()
您还可以通过致电获取主题名称列表 theme_list
import PySimpleGUI as sg
theme_name_list = sg.theme_list()


Making your window modal
To make a Modal Wio=ndow you have 2 options.
    Set the moodel=True parameter in your Window calls.
    Call the method Window.make_modal() to chance a window from non-modal to modal. There is no modal to non-modal. Don't see the need for one. If one comes up, sure!
MPORTANT - Many of the Window methods require you to either call Window.read or Window.Finalize (or set finalize=True in your Window call) before you call the method. This is because these 2 calls are what actually creates the window using the underlying GUI Framework. Prior to one of those calls, the methods are likely to crash as they will not yet have their underlying widgets created.

"Elements" are the building blocks used to create windows. Some GUI APIs use the term "Widget" to describe these graphic elements.
    Text
    Single Line Input
    Buttons including these types:
        File Browse
        Folder Browse
        Calendar picker
        Date Chooser
        Read window
        Close window ("Button" & all shortcut buttons)
        Realtime
    Checkboxes
    Radio Buttons
    Listbox
    Slider
    Multi-line Text Input/Output
    Multi-line Text Output (not on tkinter version)
    Scroll-able Output
    Vertical Separator
    Progress Bar
    Option Menu
    Menu
    ButtonMenu
    Frame
    Column
    Graph
    Image
    Table
    Tree
    Tab, TabGroup
    StatusBar
    Pane
    Stretch (Qt only)
    Sizer (plain PySimpleGUI only)

Text Element | T == Txt == Text
Window.FindElement(key) shortened to Window[key]
window['-MULTILINE KEY-'].print('My variables are', a, b, c)     # Routed to your multiline element
Text Input Element | InputText == Input == In
Combo Element | Combo == InputCombo == DropDown == Drop
layout = [[sg.Listbox(values=['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(30, 6))]]
layout = [[sg.Slider(range=(1,500),default_value=222,size=(20,15),orientation='horizontal',font=('Helvetica', 12))]]
layout =  [[sg.Radio('My first Radio!', "RADIO1", default=True),sg.Radio('My second radio!', "RADIO1")]]
Checkbox Element | CBox == CB == Check
layout =  [[sg.Checkbox('My first Checkbox!', default=True), sg.Checkbox('My second Checkbox!')]]
layout =  [[sg.Spin([i for i in range(1,11)], initial_value=1), sg.Text('Volume level')]]
layout = [[sg.Image(r'C:\PySimpleGUI\Logos\PySimpleGUI_Logo_320.png')],]
Button Element
    Button= ReadButton = RButton = ReadFormButton (Use Button, others are old methods)
    CloseButton = CButton
    RealtimeButton
    DummyButton
    layout =  [[sg.Button('Ok'), sg.Button('Cancel')]] layout =  [[sg.Ok(), sg.Cancel()]]
Button Element Shortcuts
    OK
    Ok
    Submit
    Cancel
    Yes
    No
    Exit
    Quit
    Help
    Save
    SaveAs
    Open
Chooser" Buttons
These buttons are used to show dialog boxes that choose something like a filename, date, color, etc.. that are filled into an InputText Element (or some other "target".... see below regarding targets)
    CalendarButton
    ColorChooserButton
    FileBrowse
    FilesBrowse
    FileSaveAs
    FolderBrowse
he code for the entire window could be:
layout = [[sg.T('Source Folder')],
              [sg.In()],
              [sg.FolderBrowse(target=(-1, 0)), sg.OK()]]
or if using keys, then the code would be:
layout = [[sg.T('Source Folder')],
              [sg.In(key='input')],
              [sg.FolderBrowse(target='input'), sg.OK()]]
sg.Button('Restart Song', button_color=(sg.theme_background_color(), sg.theme_background_color()),
               image_filename=image_restart, image_size=(50, 50), image_subsample=2, border_width=0)
VerticalSeparator(pad=None)
sg.OneLineProgressMeter('My Meter', i+1, 1000,  'key', 'Optional message')
Output(size=(80,20))


Qt Designer

https://github.com/nngogol/PySimpleGUIDesigner
pip install PySimpleGUIDesigner

Use GUI(by default):
PySimpleGUIDesigner

Use CLI:
PySimpleGUIDesigner -xml “~/folder1/test.ui” -ob “somegroupBox”

#removing (if installed) PySimpleGUIDesigner: 源码安装
pip uninstall -y PySimpleGUIDesigner

mkdir psgdesigner
cd psgdesigner
git clone https://github.com/nngogol/PySimpleGUIDesigner
python3 -m PySimpleGUIDesigner

python3 main.py –xmlfile=”~/folder1/test.ui” –objname=”somegroupBox”
#a bit shorter command:
python3 main.py -xml “~/folder1/test.ui” -ob “somegroupBox”