【Curie Nano试用】 A5.Curie神经元算法库--CurieNeurons
CurieNeurons,即Curie神经元。Neurons能通过示例学习,不用编程,可以通过数据离线学习。general vision提供了两个版本可供下载,免费版和收费19美刀的专业版。
下载地址:http://www.general-vision.com/software/curieneurons/
为了尝鲜我们先体验一下免费版吧,
相关的文档:
详细的信息可以看文档里的介绍,这里我们就直接切入正题了。
需要的材料很简单,Curie Nano板和一块AD Keyborad板。
这个AD Keyborad DFROBOT商城有卖,不过太贵了买不起,好在提供原理图,我手工做了一个。
5个按键只占用一个模拟IO口,很巧妙的设计。
这里VCC接3.3V,IO口接A5。
示例代码:/*
Name: CurieNeurons_andIMU2.0.ino
Created: 7/21/2016 11:08:34 AM
Author: HansYang
*/
#include <CurieIMU.h>
#include <BMI160.h>
#include <CurieNeurons.h>
#include <stdlib.h>
#define DEBUG1
#define ACC_FEATURE_ONLY
#define MANUAL_SCALING
#ifdef ACC_FEATURE_ONLY
#define SAMPLENBR 3
#else
#define SAMPLENBR 6
#endif // ACC_FEATURE_ONLY
#define MAX_SAMPLING_TIME 3000//ms
#define SAMPLING_INTERVAL 50//ms
#define MAX_VECTOR_LEN 60//MAX_SAMPLING_TIME/SAMPLING_INTERVAL
#define DOWNSAMPLER_SEGS 10
//ADkeyboard
int adc_key_val = { 850,900, 940, 960, 980 };
#define NUM_KEYS 5
int adc_key_in;
int key = -1;
//CurieNeurons
CurieNeurons hNN;
int cat, prevcat;
int dist, nid;
//IMU data
int16_t ax, ay, az;
int16_t gx, gy, gz;
int minax, minay, minaz, maxax, maxay, maxaz;
int mingx, mingy, mingz, maxgx, maxgy, maxgz;
int Sax, Say, Saz, Sgx, Sgy, Sgz;
//Others
uint64_t timer;
short vector_len;
byte vector;
byte pattern;
byte learnflag;
void feature_extraction(byte* src_vector, int src_len, byte *dst_vector)
{
int seg_len = src_len / (DOWNSAMPLER_SEGS * SAMPLENBR);
double res;
for (int icol = 0; icol < SAMPLENBR; icol++)
{
int sum = 0;
for (int i = 0; i < src_len; i++)
{
sum += src_vector;
}
//mean
int aver = sum / src_len;
int e = 0;
int mad = 0;
//int rms = 0;
//byte max = src_vector;
//byte min = src_vector;
int ratiocount = { 0 };
for (int i = 0; i < src_len; i++)
{
e += (src_vector - aver)*(src_vector - aver);
mad += abs(src_vector - aver);
//rms += src_vector * src_vector;
//if (src_vector > max)
// max = src_vector;
//if (src_vector < min)
// min = src_vector;
if (src_vector <= 200)
{
if (src_vector <= 150)
{
if (src_vector <= 100)
{
if (src_vector <= 50)
{
ratiocount++;
}
else
ratiocount++;
}
else
ratiocount++;
}
else
ratiocount++;
}
else
ratiocount++;
}
//standard deviation
res = sqrt(e / (src_len - 1)) * 2;
//MAD
res = mad / src_len * 2;
//RMS
//res = sqrt(rms / src_len);
for (int i = 0; i < 5; i++)
{
res = 0;//ratiocount;// * 255 / src_len;
}
for (int iseg = 0; iseg < DOWNSAMPLER_SEGS; iseg++)
{
int sum = 0;
for (int ismp = 0; ismp < seg_len; ismp++)
{
int offset = icol + (iseg * seg_len + ismp)*SAMPLENBR;
sum += (int)src_vector;
src_vector = 0;
}
res = sum / seg_len;
}
}
for (int i = 0; i < SAMPLENBR * 17; i++)
{
pattern = (int)(res + 0.5) * 0x00FF;
}
#ifdef DEBUG1
Serial.print("\n");
for (int i = 0; i < SAMPLENBR*17; i++)
{
Serial.print(pattern);
Serial.print("\t");
}
//Serial.print("\n");
#endif // DEBUG1
}
int get_key(unsigned int input) //1 2 3 4 5
{
int k;
for (k = 0; k < NUM_KEYS; k++)
{
if (input < adc_key_val)
{
return k + 1;
}
}
if (k >= NUM_KEYS)
k = -1;// No valid key pressed
return k + 1;
}
void read_data_once()
{
CurieIMU.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
/*int R = sqrt(ax*ax + ay*ay + az*az);
double tX = acos(ax / R);
double tY = acos(ay / R);
double tZ = acos(az / R);
ax = ax - 8192 * cos(tX);
ay = ay - 8192 * cos(tY);
az = ax - 8192 * cos(tZ);*/
vector = (byte)(((ax - minax) * 255 / Sax) & 0x00FF);
vector = (byte)(((ay - minay) * 255 / Say) & 0x00FF);
vector = (byte)(((az - minaz) * 255 / Saz) & 0x00FF);
#ifndef ACC_FEATURE_ONLY
vector = (byte)(((gx - mingx) * 255 / Sgx) & 0x00FF);
vector = (byte)(((gy - mingy) * 255 / Sgy) & 0x00FF);
vector = (byte)(((gz - mingz) * 255 / Sgz) & 0x00FF);
#endif // !ACC_FEATURE_ONLY
/*vector = ax;
vector = ay;
vector = az;
#ifndef ACC_FEATURE_ONLY
vector = gx;
vector = gy;
vector = gz;
#endif // !ACC_FEATURE_ONLY */
if (vector_len < (MAX_VECTOR_LEN - 2)*SAMPLENBR ) {
vector_len++;
Serial.print("*");
}
else
{
Serial.print("O");
}
}
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.print("CurieNeurons initializing...");
hNN.begin();
hNN.forget();
Serial.println("Done");
Serial.print("CurieIMU initializing...");
CurieIMU.begin();
Serial.println("Done");
Serial.println("Initializing IMU device...");
CurieIMU.begin();
// use the code below to calibrate accel/gyro offset values
Serial.println("Internal sensor offsets BEFORE calibration...");
Serial.print(CurieIMU.getXAccelOffset());
Serial.print("\t"); // -76
Serial.print(CurieIMU.getYAccelOffset());
Serial.print("\t"); // -235
Serial.print(CurieIMU.getZAccelOffset());
Serial.print("\t"); // 168
Serial.print(CurieIMU.getXGyroOffset());
Serial.print("\t"); // 0
Serial.print(CurieIMU.getYGyroOffset());
Serial.print("\t"); // 0
Serial.println(CurieIMU.getZGyroOffset());
Serial.println("About to calibrate. Make sure your board is stable and upright");
delay(2000);
// The board must be resting in a horizontal position for
// the following calibration procedure to work correctly!
Serial.print("Starting Gyroscope calibration...");
CurieIMU.autoCalibrateGyroOffset();
Serial.println(" Done");
Serial.print("Starting Acceleration calibration...");
CurieIMU.autoCalibrateXAccelOffset(0);
CurieIMU.autoCalibrateYAccelOffset(0);
CurieIMU.autoCalibrateZAccelOffset(1);
Serial.println(" Done");
Serial.println("Internal sensor offsets AFTER calibration...");
Serial.print(CurieIMU.getXAccelOffset());
Serial.print("\t"); // -76
Serial.print(CurieIMU.getYAccelOffset());
Serial.print("\t"); // -2359
Serial.print(CurieIMU.getZAccelOffset());
Serial.print("\t"); // 1688
Serial.print(CurieIMU.getXGyroOffset());
Serial.print("\t"); // 0
Serial.print(CurieIMU.getYGyroOffset());
Serial.print("\t"); // 0
Serial.println(CurieIMU.getZGyroOffset());
Serial.println("Enabling Gyroscope/Acceleration offset compensation");
CurieIMU.setGyroOffsetEnabled(true);
CurieIMU.setAccelOffsetEnabled(true);
CurieIMU.setAccelerometerRange(4);
//hNN.GCR(128); //LSUP distance
//hNN.MAXIF(600);
#ifdef MANUAL_SCALING
minax = minay = minaz = maxax = maxay = maxaz = -32768;
mingx = mingy = mingz = maxgx = maxgy = maxgz = 32767;
Sax = Say = Saz = Sgx = Sgy = Sgz = 65535;
#else
Serial.println("\nAssessing the amplitude of motions...Press any key to continue");
adc_key_in = analogRead(5);
while (adc_key_in > 980)
{
adc_key_in = analogRead(5);
CurieIMU.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
if (ax>maxax) maxax = ax; if (ax<minax) minax = ax;
if (ay>maxay) maxay = ay; if (ay<minay) minay = ay;
if (az>maxaz) maxaz = az; if (az<minaz) minaz = az;
if (gx>maxgx) maxgx = gx; if (gx<mingx) mingx = gx;
if (gy>maxgy) maxgy = gy; if (gy<mingy) mingy = gy;
if (gz>maxgz) maxgz = gz; if (gz<mingz) mingz = gz;
}
Sax = maxax - minax;
Say = maxay - minay;
Saz = maxaz - minaz;
Sgx = maxgx - mingx;
Sgy = maxgy - mingy;
Sgz = maxgz - mingz;
Serial.print("\nSa :\t"); Serial.print(Sax); Serial.print(","); Serial.print(Say); Serial.print(","); Serial.print(Saz);
Serial.print("\nSg :\t"); Serial.print(Sgx); Serial.print(","); Serial.print(Sgy); Serial.print(","); Serial.println(Sgz);
#endif
timer = 0;
prevcat = 0x7FFF;
learnflag = 0;
Serial.print("The program will begin in 2 seconds...\n");
delay(2000);
Serial.println("Start.");
}
// the loop function runs over and over again until power down or reset
void loop() {
timer = millis();
adc_key_in = analogRead(5);
key = get_key(adc_key_in);
if (key!=0)
{
learnflag = key;
read_data_once();
}
else if (learnflag != 0)
{
read_data_once();
feature_extraction(vector, vector_len, pattern);
//downsampler_means(vector, vector_len, pattern, SAMPLENBR*DOWNSAMPLER_SEGS);
#ifdef DEBUG
Serial.print("\n");
for (int i = 0; i < SAMPLENBR*DOWNSAMPLER_SEGS; i++)
{
Serial.print(pattern);
Serial.print("\t");
}
Serial.print("\n");
#endif //DEBUG
if (learnflag != 5)
{
hNN.learn(pattern, SAMPLENBR * 17, learnflag);
Serial.print("\nLearned motion #");
Serial.print(learnflag);
Serial.println("once, please repeat.");
}
else
{
int res = hNN.classify(pattern, SAMPLENBR * 17, &dist, &cat, &nid);
cat &= 0x00FF;
if (res != 0)
{
Serial.print("\nMotion Detected. #"); Serial.println(cat);
}
else
{
Serial.println("\nMotion Unknow.");
}
}
learnflag = 0;
vector_len = 0;
}
while ((millis() - timer) < SAMPLING_INTERVAL);
}编译示例代码并上传到Curie Nano中,打开串口工具,并将开发板平放等待陀螺仪自动校准。如图所示:
动作学习:
按住黄色、绿色、蓝色或者红色按键做动作,动作完成松手。黄色对应动作1,绿色对应动作2,蓝色对应动作3,红色对应动作4。
每种动作可以多做几次,这样识别的准确率会高一些。
下图是我按住黄色按键1和绿色按键2完成的动作识别。
识别动作:
按住中间的白色按键5,做出刚才的动作,程序会识别属于刚才的哪个动作。
如下图所示,如果做出的动作不是刚才的两种之一会显示未知。
动作的采样时间可以在以下的语句修改,但是时间越来复杂度也就越高,识别的准确率也就越低。
程序说明:
在这个过程中,主要是采用按键按下作为动作的开始,松开表示动作的结束,再将采样的动作进行数据分析,再由CurieNeurons神经网络进行学习。识别动作的方式同理。
这个有意思,感谢分享。 这个好有意思! 楼主什么时候买收费版,不知道收费版可不可以共享? slotg 发表于 2017-5-16 23:40 static/image/common/back.gif
这个有意思,感谢分享。
谢谢支持 噗噗熊 发表于 2017-5-17 09:37 static/image/common/back.gif
这个好有意思!
这个板子确实有好多好玩的地方。 我叫逗逗 发表于 2017-5-17 09:46 static/image/common/back.gif
楼主什么时候买收费版,不知道收费版可不可以共享?
看了一下介绍,专业版识别算法准确率高一些。楼主没有这方面的需求,暂时不会考虑买专业版。
页:
[1]