• 上海站 | 高性能计算之GPU CUDA培训4月13-15日三天密集式学习 快速带你晋级阅读全文>正文共13130个字,5张图,预计阅读时间33分钟。树莓派3B+英特尔神经计算棒进行高速目标检测NCS Pi代码:训练数据预处理:...
        

    上海站 | 高性能计算之GPU CUDA培训

    4月13-15日640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1三天密集式学习  快速带你晋级阅读全文>


    正文共13130个字,5张图,预计阅读时间33分钟。


    树莓派3B+英特尔神经计算棒进行高速目标检测


    640?wx_fmt=png&wxfrom=5&wx_lazy=1

    NCS Pi


    代码:
    训练数据预处理:
    https://gist.github.com/ahangchen/ae1b7562c1f93fdad1de58020e94fbdf


    测试:https://github.com/ahangchen/ncs_detection

    Star是一种美德。


    background


    最近在做一个项目,要在树莓派上分析视频中的图片,检测目标,统计目标个数,这是一张样例图片


    640?wx_fmt=png

    Cattle Counting


    Motivation


    当下效果最好的目标检测都是基于神经网络来做的,包括faster rcnn, ssd, yolo2等等,要在树莓派这种资源紧张的设备上运行检测模型,首先想到的就是用最轻量的MobileNet SSD,使用Tensorflow object detection api实现的MobileNet SSD虽然已经非常轻,但在树莓派上推导一张1280x720的图仍然需要2秒,有兴趣的同学可以参考这两个项目:


    • armv7版Tensorflow(必须是1.4及以上):https://github.com/lhelontra/tensorflow-on-arm/releases

    • Tensorflow Object detection API: https://github.com/tensorflow/models/tree/master/research/object_detection


    具体的操作在Tensorflow文档里都说的很清楚了,在树莓派上的操作也是一样的,有问题可以评论区讨论。


    Hardware


    极限的模型仍然不能满足性能需求,就需要请出我们今天的主角了,Intel Movidius Neural Computing Stick。


    640?wx_fmt=png

    Intel Movidius Neural Computing Stick


    处理器Intel Movidius VPU
    支持框架TensorFlow, Caffe
    连接方式USB 3.0 Type-A
    尺寸USB stick (72.5mm X 27mm X 14mm)
    工作温度0° - 40° C



    x86_64 Ubuntu 16.04主机

    Raspberry Pi 3B  Stretch desktop

    Ubuntu 16.04 虚拟机
    系统要求USB 2.0 以上 (推荐 USB 3.0)

    1GB 内存

    4GB 存储



    实际上这不是一个GPU,而是一个专用计算芯片,但能起到类似GPU对神经网络运算的加速作用。


    京东上搜名字可以买到,只要500元左右,想想一块GPU都要几千块钱,就会觉得很值了。


    SDK是开源的:https://github.com/movidius/ncsdk

    提问不在GitHub issue里,而是在一个专门的论坛:https://ncsforum.movidius.com/


    虽然目前NCSDK支持的框架包含Tensorflow和Caffe,但并不是支持所有的模型,目前已支持的模型列表可以在这里查到:https://github.com/movidius/ncsdk/releases


    截止到2018年3月15日,NCSDK还没有支持Tensorflow版的MobileNet SSD(比如tf.cast这个操作还未被支持),所以我们需要用Caffe来训练模型,部署到树莓派上。


    Environment


    ncsdk的环境分为两部分,训练端和测试端。


    1、训练端通常是一个Ubuntu 带GPU主机,训练Caffe或TensorFlow模型,编译成NCS可以执行的graph;


    2、测试端则面向ncs python mvnc api编程,可以运行在树莓派上raspbian stretch版本,也可以运行在训练端这种机器上。


    训练端


    安装

    安装这个过程,说难不难,也就几行命令的事情,但也有很多坑在训练端主机上,插入神经计算棒,然后:


    git clone https://github.com/movidius/ncsdk

    cd ncsdk make install


    其中,make install干的是这些事情:


    • 检查安装Tensorflow

    • 检查安装Caffe(SSD-caffe)

    • 编译安装ncsdk(不包含inference模块,只包含mvNCCompile相关模块,用来将Caffe或Tensorflow模型转成NCS graph的)


    注意,


    • 这些库都是安装到/opt/movidius/这个目录下,并关联到系统python3里边的(/usr/bin/python3),如果你电脑里原来有tf或caffe,也不会被关联上去

    • NCSDK mvNCCompile模块目前只兼容python3,我尝试过将安装完的SDK改成兼容python2的版本,可以将模型编译出来,但是在运行时会报错,所以暂时放弃兼容python2了,也建议大家用默认的python3版本

    • 这个步骤主要的坑来自万恶的Caffe,如果你装过python3版的caffe,大概会有经验一些,这里有几个小坑提示一下:

      • 最好在ncsdk目录中的ncsdk.conf中,开启caffe的cuda支持,即设置CAFFE_USE_CUDA=yes,这样你之后也能用这个caffe来训练模型

      • caffe的依赖会在脚本中安装,但有些Debian兼容问题要解决

      • 开启CUDA支持后,编译caffe会找不到libboost-python3,因为在Ubuntu16.04里,它叫libboost-python3.5,所以要软链接一下:


    cd /usr/lib/x86_64-linux-gnu/

    sudo ln -s libboost_python-py35.so libboost_python3.so


    • 其他可能出现的caffe的坑,可以在我博客找找答案,如果没有的话,就去caffe的GitHub issue搜吧

    测试


    一波操作之后,我们装好了ncsdk编译模块,可以下载我训练的caffe模型,尝试编译成ncs graph


    git clone https://github.com/ahangchen/MobileNetSSD mvNCCompile example/MobileNetSSD_deploy.prototxt -w MobileNetSSD_deploy.caffemodel -s 12 -is 300 300 -o ncs_mobilenet_ssd_graph


    这里其实是调用python3去执行/usr/local/bin/ncsdk/mvNCCompile.py这个文件, 不出意外在当前版本(1.12.00)你会遇到这个错误:


    [Error 17] Toolkit Error: Internal Error: Could not build graph. Missing link: conv11_mbox_conf


    这是因为NCSDK在处理caffe模型的时候,会把conv11_mbox_conf_new节点叫做conv11_mbox_conf,所以build graph的时候就会找不着。因此需要为这种节点起一个别名,即,将conv11_mbox_conf_new起别名为conv11_mbox_conf,修改SDK代码中的/usr/local/bin/ncsdk/Models/NetworkStage.py,在第85行后面添加:


    if ''_new' in name:    self.alias.append(name[:-4])


    于是就能编译生成graph了,你会看到一个名为ncs_mobilenet_ssd_graph的文件。


    上边这个bug我已经跟NCSDK的工程师讲了,他们在跟进修这个bug:

    640?wx_fmt=png

    NCS bug


    测试端


    NCSDK

    测试端要安装ncsdk python api,用于inference,实际上测试端能做的操作,训练端也都能做


    git clone https://github.com/movidius/ncsdk

    cd api/src 

    make install


    从输出日志可以发现,将ncsdk的lib和include文件分别和系统的python2(/usr/bin/python2)和python3(/usr/bin/python3)做了关联。


    然后你可以下一个GitHub工程来跑一些测试:


    git clone https://github.com/movidius/ncappzoo

    cd ncappzoo/apps/hello_ncs_py python3 hello_ncs.py python2 hello_ncs.py


    没报错就是装好了,测试端很简单。


    openCV


    看pyimagesearch这个教程(https://www.pyimagesearch.com/2017/09/04/raspbian-stretch-install-opencv-3-python-on-your-raspberry-pi/)


    Caffe模型训练


    就是正常的用caffe训练MobileNet-SSD,主要参考这个仓库:


    MobileNet-SSD: https://github.com/chuanqi305/MobileNet-SSD


    README里将步骤讲得很清楚了


    1、下载SSD-caffe(这个我们已经在NCSDK里装了)


    2、下载chuanqi在VOC0712上预训练的模型


    3、把MobileNet-SSD这个项目放到SSD-Caffe的examples目录下,这一步可以不做,但是要对应修改train.sh里的caffe目录位置


    4、创建你自己的labelmap.prototxt,放到MobileNet-SSD目录下,比如说,你是在coco预训练模型上训练的话,可以把coco的标签文件复制过来,将其中与你的目标类(比如我的目标类是Cattle)相近的类(比如Coco中是Cow)改成对应的名字,并用它的label作为你的目标类的label。


    (比如我用21这个类代表Cattle)


    1、用你自己的数据训练MobileNet-SSD,参考SSD-caffe的wiki,主要思路还是把你的数据转换成类似VOC或者COCO的格式,然后生成lmdb,坑也挺多的:


    假设你的打的标签是这样一个文件raw_label.txt,假装我们数据集只有两张图片:


    data/strange_animal/1017.jpg 0.487500   0.320675    0.670000    0.433193 data/strange_animal/1018.jpg 0.215000   0.293952    0.617500    0.481013


    我们的目标是将标签中涉及的图片和位置信息转成这样一个目录(在ssd-caffe/data/coco目录基础上生成的):


    coco_cattle

    ├── all # 存放全部图片和xml标签文件 │   ├── 1017.jpg

    │   ├── 1017.xml

    │   ├── 1018.jpg

    │   └── 1018.xml

    ├── Annotations # 存放全部标签xml

    │   ├── 1017.xml

    │   └── 1018.xml

    ├── create_data.sh # 将图片转为lmdb的脚本 ├── create_list.py # 根据ImageSets里的数据集划分文件,生成jpg和xml的对应关系文件到coco_cattle目录下,但我发现这个对应关系文件用不上 ├── images  # 存放全部图片 │   ├── 1017.jpg

    │   └── 1018.jpg

    ├── ImageSets # 划分训练集,验证集和测试集等,如果只想分训练和验证的话,可以把minival.txt,testdev.txt,test.txt内容改成一样的 │   ├── minival.txt

    │   ├── testdev.txt

    │   ├── test.txt

    │   └── train.txt

    ├── labelmap_coco.prototxt # 如前所述的标签文件,改一下可以放到MobileNet-SSD目录下 ├── labels.txt

    ├── lmdb # 手动创建这个目录 │   ├── coco_cattle_minival_lmdb # 自动创建的,由图片和标签转换来的LMDB文件 │   ├── coco_cattle_testdev_lmdb

    │   ├── coco_cattle_test_lmdb

    │   └── coco_cattle_train_lmdb

    ├── minival.log

    ├── README.md

    ├── testdev.log

    ├── test.log

    └── train.log


    其中,标签xml的格式如下:


    <annotation>  

    <folder>train</folder>  

    <filename>86</filename>  

    <source>    

    <database>coco_cattle</database>  

    </source>  

    <size>    

    <width>720</width>    

    <height>1280</height>    

    <depth>3</depth>  

    </size>  

    <segmented>0</segmented>  

    <object>   

     <name>21</name>    

    <pose>Unspecified</pose>    

    <truncated>0</truncated>    

    <difficult>0</difficult>   

     <bndbox>      

    <xmin>169</xmin>      

    <ymin>388</ymin>      

    <xmax>372</xmax>      

    <ymax>559</ymax>    

    </bndbox>  </object> 

      <object>    

     <name>21</name>    

    <pose>Unspecified</pose>   

     <truncated>0</truncated>    

    <difficult>0</difficult>    

    <bndbox>      

    <xmin>169</xmin>      

    <ymin>388</ymin>      

    <xmax>372</xmax>     

     <ymax>559</ymax>    

    </bndbox>

     </object></annotation>


    代表一张图中多个对象所在位置(bndbox节点表示),以及类别(name)。


    一开始,all, Annotations, images, ImageSets,lmdb四个目录都是空的,你可以把自己的图片放到随便哪个地方,只要在raw_label.txt里写好图片路径就行。


    读取raw_label.txt,利用lxml构造一棵dom tree,然后写到Annotations对应的xml里,并将对应的图片移动到image目录里,可以参考这份代码。并根据我们设置的train or not标志符将当前这张图片分配到训练集或测试集中(也就是往ImageSet/train.txt中写对应的图片名)


    这样一波操作之后,我们的images和Annotations目录里都会有数据了,接下来我们需要把它们一块复制到all目录下


    cp images/* all/

    cp Annotations/* all/


    然后用create_data.sh将all中的数据,根据ImageSet中的数据集划分,创建训练集和测试集的lmdb,这里对coco的create_data.sh做了一点修改:


    cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd ) root_dir=$cur_dir/../..

    cd $root_dir


    redo=true

    # 这里改成all目录

    data_root_dir="$cur_dir/all"

    # 这里改成自己的数据集名,也是我们这个目录的名字

    dataset_name="coco_cattle"

    # 指定标签文件mapfile="$root_dir/data/$dataset_name/labelmap_coco.prototxt"

    anno_type="detection"

    label_type="xml"

    db="lmdb"

    min_dim=0 max_dim=0 width=0 height=0

    extra_cmd="--encode-type=jpg --encoded"

    if $redo

    then  extra_cmd="$extra_cmd --redo"

    fi

    for subset in minival testdev train test

    do python3 $root_dir/scripts/create_annoset.py --anno-type=$anno_type --label-type=$label_type --label-map-file=$mapfile --min-dim=$min_dim --max-dim=$max_dim --resize-width=$width --resize-height=$height --check-label $extra_cmd $data_root_dir $root_dir/data/$dataset_name/ImageSets/$subset.txt $data_root_dir/../$db/$dataset_name"_"$subset"_"$db examples/$dataset_name 2>&1 | tee $root_dir/data/$dataset_name/$subset.logd

    one


    于是会lmdb目录下会为每个划分集合创建一个目录,存放数据


    ├── lmdb

    │   ├── coco_cattle_minival_lmdb

    │   │   ├── data.mdb

    │   │   └── lock.mdb

    │   ├── coco_cattle_testdev_lmdb

    │   │   ├── data.mdb

    │   │   └── lock.mdb

    │   ├── coco_cattle_test_lmdb

    │   │   ├── data.mdb

    │   │   └── lock.mdb

    │   └── coco_cattle_train_lmdb

    │       ├── data.mdb

    │       └── lock.mdb


    6、将5生成的lmdb链接到MobileNet-SSD的目录下:


    cd MobileNet-SSD ln -s PATH_TO_YOUR_TRAIN_LMDB trainval_lmdb ln -s PATH_TO_YOUR_TEST_LMDB test_lmdb


    7、运行gen_model.sh生成三个prototxt(train, test, deploy)


    # 默认clone下来的目录是没有example这个目录的,而gen_model.sh又会把文件生成到example目录

    mkdir example ./gen_model.sh


    8、训练


    ./train.sh


    这里如果爆显存了,可以到example/MobileNetSSD_train.prototxt修改batch size,假如你batch size改到20,刚好可以吃满GTX1060的6G显存,但是跑到一定步数(设置在solver_test.prototxt里的test_interval变量),会执行另一个小batch的test(这个batch size定义在example/MobileNetSSD_test.prototxt里),这样就会再爆显存,所以如果你的train_batch_size + test_batch_size <= 20的话才可以保证你在6G显存上能顺利完成训练,我的设置是train_batch_size=16, test_batch_size=4


    一开始的training loss可能比较大,30左右,等到loss下降到2.x一段时间就可以ctrl+c退出训练了,模型权重会自动保存在snapshot目录下


    9、运行merge_bn.py将训练得到的模型去除bn层,得到可部署的Caffe模型,这样你就能得到一个名为MobileNetSSD_deploy.caffemodel的权重文件,对应的prototxt为example/MobileNetSSD_deploy.prototxt


    10、离题那么久,终于来到主题,我们要把这个caffemodel编译成NCS可运行的graph,这个操作之前在搭环境的部分也提过:


    mvNCCompile example/MobileNetSSD_deploy.prototxt -w MobileNetSSD_deploy.caffemodel -s 12 -is 300 300 -o ncs_mobilenet_ssd_graph


    参数格式:


    mvNCCompile prototxt路径 -w 权重文件路径 -s 最大支持的NCS数目 -is 输入图片宽度 输入图片高度 -o 输出graph路径


    其实训练端相对于chuanqi的MobileNet-SSD没啥改动,甚至训练参数也不用怎么改动,主要工作还是在数据预处理上,可以参考我的预处理代码(https://gist.github.com/ahangchen/ae1b7562c1f93fdad1de58020e94fbdf)


    树莓派NCS模型测试


    现在我们要用ncs版的ssd模型在树莓派上进行对图片做检测,这个目标一旦达成我们自然也能对视频或摄像头数据进行检测了。


    仓库结构


    ncs_detection

    ├── data # 标签文件 │   └── mscoco_label_map.pbtxt

    ├── file_helper.py # 文件操作辅助函数 ├── model # 训练好的模型放在这里 │   ├── ncs_mobilenet_ssd_graph

    │   └── README.md

    ├── ncs_detection.py # 主入口 ├── object_detection # 改了一下TF的Object detection包中的工具类来用 │   ├── __init__.py

    │   ├── protos

    │   │   ├── __init__.py

    │   │   ├── string_int_label_map_pb2.py

    │   │   └── string_int_label_map.proto

    │   └── utils

    │       ├── __init__.py

    │       ├── label_map_util.py

    │       └── visualization_utils.py

    ├── r10 # 图片数据 │   ├── 00000120.jpg

    │   ├── 00000133.jpg

    │   ├── 00000160.jpg

    │   ├── 00000172.jpg

    │   ├── 00000192.jpg

    │   ├── 00000204.jpg

    │   ├── 00000220.jpg

    │   └── 00000236.jpg

    ├── README.md

    └── total_cnt.txt


    由于这个工程一开始是用Tensorflow Object Detection API做的,所以改了其中的几个文件来读标签和画检测框,将其中跟tf相关的代码去掉。


    TF的图片IO是用pillow做的,在树莓派上速度奇慢,对一张1280x720的图使用Image的get_data这个函数获取数据需要7秒,所以我改成了OpenCV来做IO。


    任务目标


    检测r10目录中的图片中的对象,标记出来,存到r10_tmp目录里。


    流程

    准备目标目录


    def config_init(dataset_pref):    os.system('mkdir %s_tmp' % dataset_pref)    os.system('rm %s_tmp/*' % dataset_pref)


    指定模型路径,标签位置,类别总数,测试图片路径


    PATH_TO_CKPT = 'model/ncs_mobilenet_ssd_graph

    'PATH_TO_LABELS = os.path.join('data', 'mscoco_label_map.pbtxt') NUM_CLASSES = 81TEST_IMAGE_PATHS = [os.path.join(img_dir, '%08d.jpg' % i)

    for i in range(start_index, end_index)]


    发现并尝试打开神经计算棒


    def ncs_prepare():    print("[INFO] finding NCS devices...")    devices = mvnc.EnumerateDevices()  

     if len(devices) == 0:        print("[INFO] No devices found. Please plug in a NCS")        quit()    print("[INFO] found {} devices. device0 will be used. "          "opening device0...".format(len(devices)))    device = mvnc.Device(devices[0])    device.OpenDevice()  

     return device


    将NCS模型加载到NCS中


    def graph_prepare(PATH_TO_CKPT, device):    print("[INFO] loading the graph file into RPi memory...")    

    with open(PATH_TO_CKPT, mode="rb") as f:        graph_in_memory = f.read()    


    # load the graph into the NCS    print("[INFO] allocating the graph on the NCS...")    detection_graph = device.AllocateGraph(graph_in_memory)    

    return detection_graph


    准备好标签与类名对应关系

    category_index = label_prepare(PATH_TO_LABELS, NUM_CLASSES)

    读取图片,由于Caffe训练图片采用的通道顺序是RGB,而OpenCV模型通道顺序是BGR,需要转换一下。


    image_np = cv2.imread(image_path) image_np = cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB)


    使用NCS模型为输入图片推断目标位置


    def predict(image, graph):    image = preprocess_image(image)    graph.LoadTensor(image, None)    (output, _) = graph.GetResult()    num_valid_boxes = output[0]    predictions = []    for box_index in range(num_valid_boxes):        base_index = 7 + box_index * 7        if (not np.isfinite(output[base_index]) or                not np.isfinite(output[base_index + 1]) or                not np.isfinite(output[base_index + 2]) or                not np.isfinite(output[base_index + 3]) or                not np.isfinite(output[base_index + 4]) or                not np.isfinite(output[base_index + 5]) or                not np.isfinite(output[base_index + 6])):          


     continue        (h, w) = image.shape[:2]        x1 = max(0, output[base_index + 3])        y1 = max(0, output[base_index + 4])        x2 = min(w, output[base_index + 5])        y2 = min(h, output[base_index + 6])        pred_class = int(output[base_index + 1]) + 1        pred_conf = output[base_index + 2]        pred_boxpts = (y1, x1, y2, x2)        prediction = (pred_class, pred_conf, pred_boxpts)        predictions.append(prediction)    return predictions


    其中,首先将图片处理为Caffe输入格式,缩放到300x300,减均值,缩放到0-1范围,转浮点数:


    def preprocess_image(input_image):    

    PREPROCESS_DIMS = (300, 300)    

    preprocessed = cv2.resize(input_image, PREPROCESS_DIMS)    

    preprocessed = preprocessed - 127.5    

    preprocessed = preprocessed * 0.007843    

    preprocessed = preprocessed.astype(np.float16)    

    return preprocessed


    graph推断得到目标位置,类别,分数


    graph.LoadTensor(image, None) (output, _) = graph.GetResult()


    其中的output格式为,


    [    

    目标数量,    

    class,score,xmin, ymin, xmax, ymax,    

    class,score,xmin, ymin, xmax, ymax,    .

    .. ]


    根据我们感兴趣的类别和分数进行过滤:


    def predict_filter(predictions, score_thresh):    num = 0    boxes = list()    scores = list()    classes = list()  

     for (i, pred) in enumerate(predictions):        (cl, score, box) = pred        

    if cl == 21 or cl == 45 or cl == 19 or cl == 76 or cl == 546 or cl == 32:          

     if score > score_thresh:                boxes.append(box)                scores.append(score)                classes.append(cl)                num += 1    return num, boxes, classes, scores


    用OpenCV将当前图片的对象数量写到图片右上角,用pillow(tf库中的实现)将当前图片的对象位置和类别在图中标出:


    def add_str_on_img(image, total_cnt):    cv2.putText(image, '%d' % total_cnt, (image.shape[1] - 100, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)


    result = vis_util.visualize_boxes_and_labels_on_image_array(                image_np,                np.squeeze(valid_boxes).reshape(num, 4),                np.squeeze(valid_classes).astype(np.int32).reshape(num, ),                np.squeeze(valid_scores).reshape(num, ),                category_index,                use_normalized_coordinates=True,                min_score_thresh=score_thresh,                line_thickness=8)


    保存图片:


    cv2.imwrite('%s_tmp/%s' % (dataset_pref, image_path.split('/')[-1]),                        cv2.cvtColor(result, cv2.COLOR_RGB2BGR))


    释放神经计算棒:


    def ncs_clean(detection_graph, device):    

    detection_graph.DeallocateGraph()    

    device.CloseDevice

    ()


    运行


    python2 ncs_detection.py


    结果


    框架图片数量/张耗时
    TensorFlow180060min
    NCS180010min
    TensorFlow12sec
    NCS10.3sec


    性能提升6倍!单张图300毫秒,可以说是毫秒级检测了。在论坛上有霓虹国的同行尝试后,甚至评价其为“超爆速”。


    扩展


    单根NCS一次只能运行一个模型,但是我们可以用多根NCS,多线程做检测,达到更高的速度,具体可以看Reference第二条。


    Reference


    https://www.pyimagesearch.com/2018/02/19/real-time-object-detection-on-the-raspberry-pi-with-the-movidius-ncs/


    https://qiita.com/PINTO/items/b97b3334ed452cb555e2


    看了这么久,还不快去给我的GitHub(https://github.com/ahangchen/ncs_detection)点star!


    原文链接:https://www.jianshu.com/p/3e9862a55e43


    查阅更为简洁方便的分类文章以及最新的课程、产品信息,请移步至全新呈现的“LeadAI学院官网”:

    www.leadai.org


    请关注人工智能LeadAI公众号,查看更多专业文章

    640?wx_fmt=jpeg

    大家都在看

    640.png?

    LSTM模型在问答系统中的应用

    基于TensorFlow的神经网络解决用户流失概览问题

    最全常见算法工程师面试题目整理(一)

    最全常见算法工程师面试题目整理(二)

    TensorFlow从1到2 | 第三章 深度学习革命的开端:卷积神经网络

    装饰器 | Python高级编程

    今天不如来复习下Python基础

    展开全文
  • 树莓派3B+平台搭载了Linux嵌入式系统,在Linux(Ubuntu 16.04)上安装python、OpenCV和tensorflow便可以组成一台mini主机用于数据处理。其硬件系统介绍如下: 博通BCM2837B0 SoC,集成四核ARM Cortex-A53(ARMv8)...

    描述:

    树莓派3B+平台搭载了Linux嵌入式系统,在Linux(Ubuntu 16.04)上安装python、OpenCV和tensorflow便可以组成一台mini主机用于数据处理。其硬件系统介绍如下:

    • 博通BCM2837B0 SoC,集成四核ARM Cortex-A53(ARMv8)64位@ 1.4GHz CPU,集成博通 Videocore-IV GPU
    • 内存:1GB LPDDR2 SDRAM
    • 有线网络:千兆以太网(通过USB2.0通道,最大吞吐量 300Mbps)
    • 无线网络:2.4GHz和5GHz 双频Wi-Fi,支持802.11b/g/n/ac
    • 蓝牙:蓝牙4.2&低功耗蓝牙(BLE)
    • 存储:Micro-SD
    • 其他接口:HDMI,3.5mm模拟音频视频插孔,4x USB 2.0,以太网,摄像机串行接口(CSI),显示器串行接口(DSI),MicroSD卡座,40pin扩展双排插针
    • 尺寸:82mmx 56mmx 19.5mm,50克

     


    pivideostream.py - 采集数据

    from picamera.array import PiRGBArray 
    from picamera import PiCamera 
    from threading import Thread 
    import cv2 
    
    class PiVideoStream: 
    
        def __init__(self, resolution=(640, 480), framerate=30): 
         self.camera = PiCamera() 
         self.camera.resolution = resolution 
         self.camera.framerate = framerate 
         self.rawCapture = PiRGBArray(self.camera, size=resolution) 
         self.stream = self.camera.capture_continuous(self.rawCapture,format='bgr', use_video_port=True) 
         self.image = None 
         self.stopped = False 
    
        def start(self): 
         t = Thread(target=self.update) 
         t.daemon = True 
         t.start() 
         return self 
    
        def update(self): 
         for frame in self.stream: 
          self.image = frame.array 
          self.rawCapture.truncate(0) 
    
          if self.stopped: 
           self.stream.close() 
           self.rawCapture.close() 
           self.camera.close() 
           return 
    
        def read(self): 
         return self.image 
    
        def stop(self): 
         self.stopped = True 

    process_img_thread.py - 主程序

    from pivideostream import PiVideoStream 
    import cv2 
    from picamera.array import PiRGBArray 
    from picamera import PiCamera 
    import time 
    
    
    def detect_in_thread(): 
        # Start updating frames in threaded manner 
        face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml') 
        eye_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_eye.xml') 
        thread_stream = PiVideoStream() 
        thread_stream.start() 
        time.sleep(2) 
    
        # Read frames 
        while True: 
    
         # Original image 
         image = thread_stream.read() 
    
         # Full image - face detection 
         gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 
         faces = face_cascade.detectMultiScale(gray,1.3,5) 
         for (x,y,w,h) in faces: 
          detected_face = cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2) 
    
          # Region of interest - eyes detection 
          roi_color = image[y:y+h,x:x+w] 
          roi_gray = gray[y:y+h,x:x+w] 
          eyes = eye_cascade.detectMultiScale(roi_gray,1.03,5,0,(40,40)) 
          for (ex,ey,ew,eh) in eyes: 
           cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,255),2) 
    
         # Show computed image 
         cv2.imshow('Threaded Camera OpenCV Preview',image) 
    
         if cv2.waitKey(1) & 0xFF == ord("q"): 
          break 
    
        # Close image window and thread 
        cv2.destroyAllWindows() 
        thread_stream.stop() 
    
    
    if __name__ == "__main__": 
        detect_in_thread() 

    问题解决:

    I am having problems with Python thread OpenCV (not sure if this is possible), but the threading PiCamera catches the frame well.

    I tried the following except the above:

    1. Use the "YUV" color space instead of "RGB" and simply access the first (Y - lumminance) channel to get grayscale data, wasting less time fetching frames and converting from RGB to grayscale
    2. Try to use LBP cascade instead of HAAR (for example ) - should be faster, but less accurate/usr/local/share/OpenCV/lbpcascades/lbpcascade_frontalface.xml

     

     

     

     

    展开全文
  • 上周 TensorFlow 1.0 的发布使之成为最有前景的深度学习框架,也在中国 AI 社区中掀起了学习 TensorFlow 的热潮,不过光跑例子怎能脱颖而出?本文是数据科学公司(Silicon Valley Data Science)的数据工程师 Matt ...

    上周 TensorFlow 1.0 的发布使之成为最有前景的深度学习框架,也在中国 AI 社区中掀起了学习 TensorFlow 的热潮,不过光跑例子怎能脱颖而出?本文是数据科学公司(Silicon Valley Data Science)的数据工程师 Matt Rubashkin 的一篇实战派文章,介绍了他如何创造性的将深度学习与物联网结合起来解决一个实际问题的思路和过程,非常具有启发性。

    SVDS(Silicon Valley Data Science)曾使用过实时、公开的数据来优化对加州火车到达时间的预测。但是,加州火车的到站时间数据不可靠,因此难以准确预测。我们使用 Raspberry Pi 摄像头和 USB 麦克风,能够侦测到火车的经过及其速度和方向。当在 Mountain View 办公室里装配了一台新的 Raspberry Pi 时,我们遇到了一个棘手的问题:Pi 不单单侦测到了加州火车(true positive),也侦测到了太平洋联合货运的火车和 VTA 轻轨(false positive)。为了确保侦测到的是加州火车的延迟,我们不得不对不同的火车做个靠谱的分类。

    图片描述

    视频:https://youtu.be/n0lCPXzaxTg

    传统的背景图像分类技术是远远不够的,因为我们在整个加州火车系统的铁轨上——包括不同的距离,不同的方向,不同的高度——放满了 Raspberry Pi。而且我们的操作时间也很有限,没有足够的时间来为系统里每一个 RaspberryPi 手动选择模式和特征。

    用 TensorFlow 解围

    幸好是在2016年遇到这个图像分类问题,因为在这一年里很多深度学习相关的图像识别技术的代码被公开了。我们选择使用 Google 的 TensorFlow 卷积神经网络,因为它有简单易用的 Python 库和丰富的在线文档。我拜读过 Pete Warden 关于 TensorFlow 的博客——TensorFlow for Poets(https://codelabs.developers.google.com/codelabs/tensorflow-for-poets/#0),这篇博客里介绍了如何在高性能的 Inception V3 模型上创建定制化图像分类器。而且,我可以用我的笔记本电脑来对这个新模型的增强版通宵进行训练。这样就不需要很贵的 GPU(显卡),也可以在未来对模型进行微调,非常有用。

    我是从 TensorFlow 教程页面中花的识别教程开始的。我使用命令行接口来分类数据集中的图片,也包括 Van Gough 的向日葵这样的定制图片。

    图片描述

    图像中的名称,从上到下依次雏菊,向日葵,蒲公英,郁金香,玫瑰。

    现在我有了用 TensorFlow 来创建图像分类器的经验,便希望建立一个稳健无偏的图像识别模型用来识别火车。虽然之前 Raspberry Pi 拍摄到的图片可以用于训练模型,但我还是选择了更大更多样的数据集。我也将小汽车和卡车包括进模型中,因为他们也可能在某些位置上经过 Raspberry Pi 的侦测点。为了得到这个汽车分类器的训练数据集,我用 Google 找了1000张图片,含:

    • 加州火车
    • 货运火车
    • 轻轨
    • 卡车
    • 小汽车

    测试及配置模型

    对模型训练了一个通宵,第二天一早,我回到办公桌来查看模型运行得怎么样。首先我测试了不包含在训练集里图片,并惊奇的发现,分类器似乎一直可以挑出正确的分类。这里面包括从 Google 上找到的训练集的图片,也包括从 Raspberry Pi 采集到的图片。

    图片描述

    图片中的名称,从上到下依次是:加州火车,运输火车,轻轨,汽车,卡车。

    我在 Raspberry Pi 上运行图片分类器,来保证这套设备用户是可以支付得起的。此外,由于不能保证网络连接的速度,我必须直接在设备上运行分类器以避免把图片发送到中心服务器所造成的延迟。

    Raspberry Pi3 马力(功率)充足,可以直接在设备上进行流处理,因此我们只需要用网络发送小容量的,处理过的数据流,并且这套设备也便宜。这个传感器整体的硬件成本是130美金,所有的代码都是用的开源库。我用 JupyterHub 对其进行了测试,以便控制多个位置上的 Raspberry Pi 设备。有了一个正常运行的车辆分类集,接下来我把模型加载到 Raspberry Pi 上,并在视听流架构下实现了它。

    图片描述

    为了能够在 Raspberry Pi 32Bit ARM芯片上编译,我使用的是来自SamAbraham 的 Pi-TensorFlow enthusiasts 小社区的指引(https://github.com/samjabrahams/tensorflow-on-raspberry-pi),同时也与 Pete Warden,Google 的 TensorFlow 团队进行了沟通。

    解决 TensorFlow 在 Raspberry Pi 上出现的问题

    虽然有好的文档记录如何在 Android 和其他小型计算设备上安装 TensorFlow,但大多数的例子都是单张图片识别或批处理,而非流媒体图片识别。在Pi上单张图片可以简单稳健地给出分数,如下面这个成功的分类所示:

    图片描述

    但是,把85MB的模型加载到内存里需要太长的时间了,因此需要把分类器图表加载到内存里。分类器图表加载到内存之后,Raspberry Pi 拥有总计1G的内存,在我们定制的火车侦测 Python 应用中,有足够的计算资源来处理连续运行的摄像头和麦克风。

    图片描述

    即便如此,用 TensorFlow 分析 PiCamera 拍摄到的每一张图片也是不可行的,因为这样 CPU 的使用率最终将达到100%,导致 Raspberry Pi 系统过热,因此只有运动物体的图片传送给了 Pi 上的图片分类器,并用 TensorFlow 识别不同类型车辆。

    结论

    如果你对使用物联网设备做实时图像分类感兴趣,请从这里开始:

    图片描述


    原文: TensorFlow Image Recognition on a Raspberry Pi
    作者: Matthew Rubashkin,目前是数据科学公司 Silicon Valley Data Science 的数据工程师,并且是UC Berkeley 博士,拥有光学物理和生物医学研究的背景,并且在软件开发,数据库工程和数据分析方面拥有广泛的经验。
    本文来源AI100公众号(rgznai100),授权CSDN发布。
    欢迎人工智能领域技术投稿、约稿、给文章纠错,请发送邮件至heyc@csdn.net


    图片描述图片描述


    SDCC 2017·上海站将于2017年3月17-19日登陆申城,三大技术峰会24位嘉宾,汇聚国内一线的互联网公司大牛,畅谈运维、数据库和架构的热门话题和技术热点,精益运维发起人&优维科技CEO王津银、MongoDB 大中华区首席架构师唐建法和华为软件API开放平台架构师李林锋等亲临现场。3月5日前门票八折优惠中,5人以上团购立减400元,详情点击注册参会

    展开全文
  • 测试树莓派是否支持OpenMP多核并行操作的代码

    编译makefile生成test可执行文件

    #bulid for stp_test
    #CROSS	=arm-hisiv300-linux-    #HI3536平台编译器
    CROSS	=arm-linux-gnueabihf-   #树莓派的编译器
    
    CC	= $(CROSS)g++
    #C语言编译程序。默认命令是“cc”,即“g++”
    LD	= $(CROSS)ld
    #LD链接器的名字,缺省值是ld
    AR	= $(CROSS)ar	
    #AR函数库打开包程序。默认命令是“ar”
    
    CFLAGS	+= -g -Wall -O2 -fopenmp -mfpu=neon -ldl 
    #-g 在可执行程序中包含标准调试信息
    #-O0 O1 O2 O3 OS ,不同的优化程度
    #-w	关闭所有告警
    #-Wall 允许发出Gcc提供的所有有用的报警信息
    #-werror 把所有的告警信息转化为错误信息,并在告警发生时终止编译过程
    #-fopenmp 
    #-mfpu=neon 使用NEON技术
    #-ldl 链接dl库
    
    HOME_DIR = $(PWD)
    SRC_DIR := $(HOME_DIR)
    INCLUDE_DIR := $(HOME_DIR)/include
    
    AFLAGS	+=	-arv
    #编译汇编语言源文件de选项
    
    CFLAGS  += 	-I$(SRC_DIR)
    CFLAGS  += 	-I$(INCLUDE_DIR)
    CFLAGS  += 	-I$(INCLUDE_DIR)/api
    CFLAGS  += 	-I$(INCLUDE_DIR)/inner
    CFLAGS  += 	-I$(INCLUDE_DIR)/mkp
    #-I 在头文件的搜索路径列表中添加dir目录
    
    LIBS := $(HOME_DIR)/lib/libmed.a \
    	$(HOME_DIR)/lib/libmpi.a \
    	$(HOME_DIR)/lib/libhdmi.a \
    	$(HOME_DIR)/lib/libdnvqe.a \
    	$(HOME_DIR)/lib/libive.a \
    	$(HOME_DIR)/lib/libjpeg.a \
    	$(HOME_DIR)/lib/libjpeg6b.a \
    	$(HOME_DIR)/lib/libtde.a \
    	$(HOME_DIR)/lib/libupvqe.a \
    	$(HOME_DIR)/lib/libVoiceEngine.a \
    	$(HOME_DIR)/lib/libpciv.a \
    	$(HOME_DIR)/lib/alg/libgsfacedt.a \
    	$(HOME_DIR)/lib/alg/libopencv_highgui.a \
    	$(HOME_DIR)/lib/alg/libopencv_imgproc.a \
    	$(HOME_DIR)/lib/alg/libopencv_video.a \
    	$(HOME_DIR)/lib/alg/libopencv_core.a \
    	$(HOME_DIR)/lib/alg/liblibpng.a \
    	$(HOME_DIR)/lib/alg/liblibjpeg.a \
    	$(HOME_DIR)/lib/alg/libzlib.a
    #.a 静态库 .so 动态库
    
    mSRCS = $(SRC_DIR)/test.c
    #源文件为test.c
    
    OBJS = $(patsubst %.c, %.o, $(mSRCS))
    #OBJS = test.o
    
    TARGET := $(PWD)/test
    #目标文件 TARGET = test
    
    
    
    #hs-build: $(TARGET)
    
    $(TARGET) :$(OBJS)
    	$(CC) $(CFLAGS) -o $@ $(mSRCS)  -lpthread  -lm  -ldl -Bstatic  $(LIBS)    #-lz
    #  $@ 表示当前的目标文件,即TARGET = test
    
    clean: 
    	rm -f $(OBJS)
    	rm -f $(TARGET)

    编译所用的test.c源码

    #include "VideoAnalyse.h"
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <omp.h>
    #include <sys/time.h>
    
    void test(void)
    {
    	struct timeval start,end; //定义两个时间变量用来表示开始和结束
    	int j=500000000;
    	gettimeofday(&start,NULL);	//获得当前的时间,并把它存放到start中
    	/*
    	while (j--)
    	{
    		int a = 0;
    		int i;	
    		for(i=0;i<500000000;i++)
    		{
    			a = a +i;
    		}
    		for(i=0;i<500000000;i++)
    		{
    			a = a +i;
    		}
    		//printf("%d: a = %d\n",  a);
    	}
    	*/
    	printf("numthread=%d \n",omp_get_thread_num());
    	gettimeofday(&end,NULL);	//获得当前的时间,并把它存放到end中
    	printf("num_procs=%d thread_num=%d runtime=%ds:%dus\n",omp_get_num_procs(),omp_get_thread_num()
    		,end.tv_sec -start.tv_sec, end.tv_usec - start.tv_usec);
    }
    
    
    void *thfun_1(void *arg)
    {   
    	int i;
    	printf("new  thread 1 start!\n");
    
    	for(;;)
    		{
    			for(i=0;i<10000000;i++);
    			for(i=0;i<10000000;i++);
    			for(i=0;i<10000000;i++);
    		}
    	printf("new  thread 1 end!\n");
    
        return ((void *)0);
    
    }
    
    void *thfun_2(void *arg)
    {     
    	int i;
    	printf("new  thread 2 start!\n");
    
    	for(;;)
    		{
    			for(i=0;i<10000000;i++);
    			for(i=0;i<10000000;i++);
    			for(i=0;i<10000000;i++);
    		}
    	printf("new  thread 2 end!\n");	
    
        return ((void *)0);
    
    }
    
    void *thfun_3(void *arg)
    {     
    	int i;
    	printf("new  thread 3 start!\n");
    
    	for(;;)
    		{
    			for(i=0;i<10000000;i++);
    		}
    	printf("new  thread 3 end!\n");
    
        return ((void *)0);
    
    }
    
    void *thfun_4(void *arg)
    {     
    	int i;
    	printf("new  thread 4 start!\n");
    
    	for(;;)
    		{
    			for(i=0;i<10000000;i++);
    		}
    	printf("new  thread 4 end!\n");
    
        return ((void *)0);
    
    }
    
    
    
    int main(int argc, char *argv[])
    {
    	int j,ret;
    	pthread_t pthid;
    	struct timeval start,end;
    	
    
    #if 1
    	/*创建四个线程,成功返回0,出错返回错误码
    	第一个参数为指向线程标识符的指针。
    	第二个参数用来设置线程属性。
    	第三个参数是线程运行函数的起始地址。
    	最后一个参数是运行函数的参数。*/
    	ret=pthread_create(&pthid,NULL,thfun_1,(void *)"testTh1");	
    	if(ret!=0)
    		{
    		  perror("can'tcreat thread 1 ");
    		  exit(EXIT_FAILURE);
    	}	
    
    	ret=pthread_create(&pthid,NULL,thfun_2,(void *)"testTh2");
    	if(ret!=0)
    		{
    		  perror("can'tcreat thread 2 ");
    		  exit(EXIT_FAILURE);	
    	}
    	
    
    	ret=pthread_create(&pthid,NULL,thfun_3,(void *)"testTh3");
    	if(ret!=0)
    		{
    		  perror("can'tcreat thread 3 ");
    		  exit(EXIT_FAILURE);
    	}
    
    	ret=pthread_create(&pthid,NULL,thfun_4,(void *)"testTh4");
    	if(ret!=0)
    		{
    		  perror("can'tcreat thread 4");
    		  exit(EXIT_FAILURE);	
    	}
    #endif	
    
    	while(1)
    	{	
    
    #pragma omp parallel sections 
    {
    
    #pragma omp section
    		printf("section 1 ThreadId = %d\n", omp_get_thread_num());
    /*
    #pragma omp section 
    		for(j=0;j<3;j++)
    		{
    		    	test();	
    		 }
    */
    }
    
    /*
    	    gettimeofday(&start,NULL);
    #pragma omp parallel for 
    		for(j=0;j<8;j++)
    			{		
    		 	test();		
    			}
    		gettimeofday(&end,NULL);
    		printf("Total time runtime=%ds:%dus \n",end.tv_sec -start.tv_sec, end.tv_usec - start.tv_usec);
    */		
    
    	}
    	exit(0);
    
    	return 0;
    }
    


    
    

    
    
    展开全文
  • Opencv嵌入式图像处理

    图像处理这几年可谓是大红大紫了一番,尤其是OpenCV的出现让很多之前只有研究者才能使用的算法变成了小白装个库调用个函数就可以解决的问题。但是实时性一直以来都是一个非常头疼的问题,尤其是在嵌入式平台上进行图像处理的门槛一直以来都没有降低。今天在这挖个坑,想和大家一起把图像处理搬到嵌入式平台上去,让图像处理从花拳绣腿的演示实验,到真正真枪实剑。

    1. 硬件选择
      图像处理方面ARM,DSP,FPGA,GPU四者可谓是各有各的优点。ARM的最大优点是系统封装,一旦ARM加上了系统那程序写起来会避免接触诸多底层的麻烦。在2014年之前,大多数高端开发板还停留在DSP+ARM的架构上,程序写起来可谓是难上加难。而单纯ARM CPU的嵌入式平台即便是可以跑较为完整的Linux系统,运算速度和桌面平台也差一个数量级。
      2014年英伟达推出了Jetson 系列的带GPU的嵌入式超级计算机在硬件上打破这一难题。入门级Jetson tk1 以及高配版Jeston tx1 基本上可以完全满足用户对于嵌入式图像处理的硬件需求。本系列将使用Jetson tk1作为嵌入式图像处理的硬件平台使用
      英伟达Jetson tk1 Developer Kit
      Jeston tk1 全名Nvidia Jeston Tegra K,他拥有Cortex-A15架构的32位四核心CPU,拥有192核心的开普勒GPU, 2GB内存,并有USB 3.0、HDMI 1.4、SATA、千兆以太网(Realtek RTL8111GS)、音频(Realtek ALC5639)、mini PCI-E。总的来说,除了USB接口数目,其他的都已经绰绰有余,配得上“超级计算机的名号”。不过关于硬件方面,有几个藏得很深的地方要拿出来说明一下:

      • 板子一共有四个串口,一个RS232串口和三个TTL电平,英伟达官方文档中不建议使用UART 2,因为他适用于开发板的调试功能;
      • RS232串口存在只能发不能收的问题,目前尚未解决;
      • USB控制器不支持Kinect V2。
    2. 软件介绍
      Jeston tk1 自带有Tegra系统,其实就是一个加入部分优化的ARM Ubuntu。Tegra保留了几乎所有Ubuntu 14.04 LST的功能,如果你是一个Linux程序员那上手起来一定会非常快。此外,Nivida 还提供了Tegra2Opencv的工具包,使用它可以利用NVCC编译Opencv,这比使用ARM编译的Opencv速度要快很多。值得一提的是,使用NVCC编译的Opencv可以利用Opencv中的GPU模块,虽然Gpu模块现在还是一个效率存疑的模块,但是就我的测试结果来看,使用GpuMat 和Gpu::initUndistortRectifyMap效率cv::initUndistortRectifyMap的5倍。
      这里写图片描述
      此外,Jeston tk1 还有英伟达自家的VisionWorks 图像处理库,这个基于OpenVX的开源(虽然我至今没有找到他的CPP文件)图像处理库提供基于硬件加速的视觉处理算法,就我自己的测试结果来看,像光流检测,立体匹配等VsionWorks里有的模块,效率基本上都是Opencv的10倍以上,这一点会在以后的文章中详细说明。

    3. 本系列说明
      本系列将采用Jeston Tk1 作为硬件实现平台,算法方面会兼用Opencv和VisionWorks两个库,对比他们效率,有什么问题希望大家可以与我一起交流~
    展开全文
  • 读取树莓派4B处理器(CPU)的实时温度 树莓派发布4B后,性能提升了不少,但是温度也是高的不行,所以最好配置一个小风扇和散热片还是比较好的 俩种办法都可以实现 1.Shell命令读取 打开终端 cd /sys/class/...
  • 树莓派3B+ 开启超频

    2017-11-12 19:47:05
    正如我们所知,树莓派CPU默认频率是1200MHz,在一般状态下处于600MHz,对于这个CPU性能如何,我就不多说了,由于树莓派到现在都还没有官方64bit的系统,我们在处理视觉图像时,处理时长令人心寒,所以在这里提供一个...
  • 高帧率opencv卡顿问题解决方案 参考了以下的文章: ...如果是python3,最后复制的不是cv2.so文件,而是在cv2.so同级目录下有一个python3目录,将里面的.so文件复制到相应的位置就可以了。 ...
  • 用过亚马逊的DeepLens吗?这是一款专门面向开发人员的全球首个支持深度学习的摄像机,它所使用的机器学习算法不仅可以检测物体活动和面部表情,而且还可以检测类似弹吉他等复杂的活动。有了DeepLens,智能摄像机的...
  • 因为树莓派的 cpu 和内存大小的限制,在树莓派上跑 IDE 不太可能,对于简单的程序,我们可以通过 bashgcc -o main main.cpp 完成小程序的编译过程.然而我们如果要开发像车牌识别,人脸识别这样的基于 opencv 的大型...
  • 一、树莓派4B产品介绍 <原理图> 树莓派最新发布的第四代产品 Raspberry Pi 4 B, 性能与树莓派 3B+相比无论是处理器速度,还是多媒体和内存上都有显著提升。Raspberry Pi 4 B拥有与入门级 x86 PC 系统相媲美...
  • 『1』对深度学习(Deep Learning)的简单介绍以下解释来自维基百科:深度学习是机器学习拉出的分支,它试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。深度学习的用途实在太广泛...
  • 带你了解树莓派

    2017-12-13 23:30:46
    在本文中,你学到了树莓派是什么,它为什么存在,如何购买树莓派以及你需要哪些外设来让树莓派启动并运行。你知道了树莓派可用的操作系统并且知道如何获取Raspbian的副本。你还学会了如何让你的树莓派启动并运行,...
  • 6.1树莓派基本操作目前提供了三个应用程序,分别为:raspistill、raspivid、raspistillyuv。其中 raspistill 和 raspistillyuv 非常相似,并且都是用于捕捉图像,而 raspivid 用于捕捉视频。 所有应用程序均基于...
  • 树莓派学习(一)

    2017-09-29 22:19:35
    树莓派进阶(一) 1.1 树莓派3 B型 SOC 博通BroadcomBCM2835芯片 CPU 700MHZ ARM A11 GPU Broadcom Video IV 支持openGL/ mpeg-4 AVC高清解码 内存 GPU共享512MB 图像输出 复合RCA接口,HDMI,DSI接LCD 音频...
  • 听闻 TensorFlow 专门推出了官方适配树莓派的版本,就立马买了一个树莓派试一试,不过考虑到最新的树莓派3B+虽然是有GPU,但依旧很垃圾,所以选择了最简单的 MINST 上手。 (软硬件环境:树莓派3B+、树莓派官方 CSI...
  • 在上一篇博客中介绍了该项目的的需求分析以及先期的准备,今天就记录一下在树莓派上的开发过程,我从接触树莓派到完成项目也只是过了俩周的时间,肯定是没有把树莓派完全玩透的,遇到问题最好的方法还是去谷歌,如果...
  • 这周用树莓派做了个小项目,期间遇到的问题可真不少,所幸一个一个都解决了。中间走了不少弯路,浪费了很多时间,但同时也增进了对python,tensorflow,opencv,PIL,picamera还有inception,ssd-mobilenet的了解,...
  • 树莓派+openCV物联网工程(一) OpenCV配合树莓派Rasperry Pi,通过读取PiCamera视频,进行人脸识别、边缘检测、语义分割、自动驾驶、图像识别等...树莓派图像处理部分使用的开源计算机视觉环境 OpenCV 1.0OpenC...
1 2 3 4 5 ... 20
收藏数 796
精华内容 318