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上直接执行的方法。

    希望对同道中人有启示!

  • 相关阅读:
    LeetCode 1122. Relative Sort Array (数组的相对排序)
    LeetCode 46. Permutations (全排列)
    LeetCode 47. Permutations II (全排列 II)
    LeetCode 77. Combinations (组合)
    LeetCode 1005. Maximize Sum Of Array After K Negations (K 次取反后最大化的数组和)
    LeetCode 922. Sort Array By Parity II (按奇偶排序数组 II)
    LeetCode 1219. Path with Maximum Gold (黄金矿工)
    LeetCode 1029. Two City Scheduling (两地调度)
    LeetCode 392. Is Subsequence (判断子序列)
    写程序判断系统是大端序还是小端序
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/7262746.html
Copyright © 2011-2022 走看看