zoukankan      html  css  js  c++  java
  • 深度学习之Matlab 转C++在iOS上測试CNN手型识别

    1 前言

    在上一篇Blog。我介绍了在iOS上执行CNN的一些方法。

    可是,一般来说。我们须要一个性能强劲的机器来跑CNN,我们仅仅只是须要将得到的结果用于移动端。

    之前在Matlab使用UFLDL的代码改动后跑了手型识别的3层CNN,这里我们就考虑将Matlab转C之后移植到xcode中。

    Step 1:Matlab 转c

    首先要保证代码能够跑。能够执行,比方我这边。例如以下測试cnn识别手型:
    手型图片

    >> parameters = load('./opt_parameters/opttheta_8epoches_cnn.mat');
    cnnPredict(imread('./data/test_five1 (1).bmp'),parameters.opttheta)
    ans =
    
         5

    大家能够看到。我识别出来是5个手指。OK,CNN没有问题。如今就是要将cnnPredict函数转c,这里大家能够看到这个函数包括了输入数据和已训练的參数。

    function labels = cnnPredict(images,opttheta)

    基本方式是使用Matlab自带的工具:coder。
    在Command窗体输入coder:
    这里写图片描写叙述
    新建一个项目:
    这里写图片描写叙述
    这里我已经导入了我要转的文件cnnPredict.m,里面有两个输入变量,我须要定义其变量类型,这里我使用autodefine types。就是写一个脚本执行这个函数。即可。

    也就是我一開始贴的代码,识别出来后是这样:
    这里写图片描写叙述
    这里大家能够看到我这边CNN的參数并非非常多,也就是19万个參数而已。


    接下来就是build了。这里选择c/c++ static library。而且仅仅输出c code:
    这里写图片描写叙述
    build结果例如以下:
    这里写图片描写叙述
    有可能你会build失败。这个时候可能是数据类型问题,能够依据详细情况进行改动到成功为止。
    生成的code在目录的codegen目录中:
    这里写图片描写叙述

    Step 2:将.Mat參数导出为.txt格式

    在训练的时候,我们的cnn參数是存储在.mat中,因此,为了能在xcode中使用,我们须要将參数导出,这里我选择导出为.txt格式。
    导出方法非常easy,一条代码;

    >> save('opttheta.txt','opttheta','-ASCII'); %将opt theta參数保存为opttheta.txt

    这里写图片描写叙述

    Step 3: 新建iOSproject。导入cnnPredict代码

    这一步非常easy,把整个目录拉进来就OK了。
    注意cnnPredict.h代码。我们要用的也就是这里面的函数了:

    /*
     * File: cnnPredict.h
     *
     * MATLAB Coder version            : 2.7
     * C/C++ source code generated on  : 16-Jul-2015 16:22:01
     */
    
    #ifndef __CNNPREDICT_H__
    #define __CNNPREDICT_H__
    
    /* Include Files */
    #include <math.h>
    #include <stddef.h>
    #include <stdlib.h>
    #include <string.h>
    #include "rt_nonfinite.h"
    #include "rtwtypes.h"
    #include "cnnPredict_types.h"
    
    /* Function Declarations */
    extern double cnnPredict(const double images[9216], const double opttheta[195245]);
    
    #endif
    
    /*
     * File trailer for cnnPredict.h
     *
     * [EOF]
     */
    

    注意的是导入执行里面有个interface目录会导致执行失败。应删除之,不会影响其它。

    Step 4 在Xcode中导入參数

    这一步就是读取txt文件里的数据并转存为double的数组。直接贴代码:

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"opttheta" ofType:@"txt"];
        NSString *testString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
        NSMutableArray *thetaString = (NSMutableArray *)[testString componentsSeparatedByString:@"
    "];
        [thetaString removeLastObject];
        NSLog(@"Theta1 count:%lu",(unsigned long)thetaString.count);
        for (int i = 0; i < thetaString.count; i++) {
            NSString *data = [thetaString objectAtIndex:i];
            theta[i] = [data doubleValue];
        }

    从代码中能够看到。就是用’ ’来切割数据,道理非常easy。

    Step 5 将图片转换为double数组

    为了使用函数,我们必须将图片转换为数组。

    我们这里显然是使用灰度图片,转换的代码例如以下:

    UIImage *image = [UIImage imageNamed:@"one.bmp"];
    
    
    CGImageRef imageRef = [image CGImage];
    CGDataProviderRef provider = CGImageGetDataProvider(imageRef);
    NSData *data = (id)CFBridgingRelease(CGDataProviderCopyData(provider));
    NSLog(@"image:%lu",(unsigned long)data.length);
    const uint8_t *bytes = [data bytes];

    这里就转换为uint8的数组了,接下来我这边依据须要对图片的灰度矩阵须要进行转置:

    double newBytes[9216];
    
        for (int y = 0; y < 96 ; y++) {
            for (int x = 0; x < 96; x++) {
                newBytes[x*96 + y] = bytes[y*96 + x];
            }
        }

    Step 6: 执行cnn

    有了上面的处理。这一步直接执行cnnPredict

    double result = cnnPredict(newBytes, theta);
    
    NSLog(@"result:%f",result);

    直接就输出结果了:
    这里写图片描写叙述
    大家看到了吗?识别出的结果为1。就是大拇指的意思。
    事实上看到这里,我自己都是有点激动的。特别爽是不是,iOS上执行的CNN直接识别手势。尽管这边的图片是黑白的比較简单一点。

    小结

    本文总结了怎样将CNN的MATLAB代码转换为C++代码然后在iOS上直接执行的方法。

    希望对同道中人有启示!

  • 相关阅读:
    原创 计算机系学生大学四年应该这样过
    ff3f34fq34f
    指针 引用
    POJ3352Road Construction
    POJ3308Paratroopers
    北大ACM试题分类 实时更新我所有的解题报告链接
    POJ2516Minimum Cost
    【转】一位ACMer过来人的心得
    POJ2528Mayor's posters
    POJ2186Popular Cows
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/7262746.html
Copyright © 2011-2022 走看看