起因:b站刷到一个在点阵屏上用按键画数字然后识别的视频,有点意思想自己做做
目标
1、51引脚不够,用红外来控制单片机,在点阵屏上画数字
2、画完后,红外控制开始识别
3、识别完成在LCD屏上显示
代码参考了江协科技和普中手册
0、public
//public.h
#ifndef _PUBLIC_H_
#define _PUBLIC_H_
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
#include "reg52.h"
// LED点阵 从左往右每一列的数据
extern u8 GLED_PER_COL_DATA[8];
// 坐标 前四位x 后四位y
extern u8 point;
// 控制
#define DISABLE 0
#define ENABLE 1
void delay_10us(u16 ten_us);
void delay_ms(u16 ms);
float my_exp(float x);
#endif
//public.c
#include "public.h"
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1时,大约延时10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us) {
while (ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms延时函数,ms=1时,大约延时1ms
* 输 入 : ms:ms延时时间
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms) {
u16 i, j;
for (i = ms; i > 0; i--)
for (j = 110; j > 0; j--);
}
// 求e的x次幂
float my_exp(float x) {
x = 1.0f + x / 1024;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
return x;
}
1、串口
首先肯定是串口代码,用于调试
//uart.h
#ifndef _UART_H_
#define _UART_H_
#include <stdio.h>
#include "public.h"
#define UART_REC_LEN 32 // 定义最大接收字节数 50
extern u8 xdata UART_RX_BUF[UART_REC_LEN]; // 接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
extern u16 xdata UART_RX_STA; // 接收状态标记
/* printf */
char putchar(char c);
void UART_Init(void);
void UART_SendData(u8 dat);
void UART_SendString_DisIR(u8 *pbuf);
void UART_SendString_EnIr(u8 *pbuf);
// 串口接收使用
/* if (UART_RX_STA & 0x8000){ // 判断串口是否接收完数据,接收到的数据就是UART_RX_BUF
UART_RX_STA = 0; // 清除标记,等待下次接收
UART_SendString(UART_RX_BUF);
UART_SendString("\r\n");
} */
#endif
/*
%c:字符。
%d:十进制整数。
%i:整数,基本等同于%d。
%o:八进制整数。
%p:指针。
%s:字符串。
%u:符(unsigned int)。
%x:十六进制整数。
%%:输出一个百分号。
%zd: size_t类型。
%a:十六进制浮点数,字母输出为小写。
%A:十六进制浮点数,字母输出为大写。
%e:使用科学计数法的浮点数,指数部分的e为小写。
%E:使用科学计数法的浮点数,指数部分的E为大写。
%f:小数(包含 float 类型和 double类型) 。
%g:6个有效数字的浮点数。整数部分一旦超过6位,就会自动转为科学计数法,指数部分的e为小写。
%G:等同于%g,唯一的区别是指数部分的E为大写。
%Le:科学计数法表示的long double类型浮点。
%Lf: long double类型浮点。
%hd:十进制 short int型。
%ho:八进制 short int型。
%hx:十六进制 short int类型。
%hu: unsigned short int型。
%ld:十进制 long int类型。
%lo:八进制 long int类型。
%lx:十六进制 long int类型。
%lu: unsigned long int。
%lld:十进制 long long int类型。
%llo:八进制 long long int类型。
%llx:十六进制 long long int型。
%llu: unsigned long long int型。
%n:已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中。
*/
//uart.c
#include "uart.h"
#define RELOAD_COUNT 0xFA // 宏定义波特率发生器的载入值 [email protected]
// 串口初始化
void UART_Init(void) // [email protected]
{
PCON |= 0x80; // 波特率倍速
SCON = 0x50; // 8位数据,可变波特率
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x20; // 设定定时器1为8位自动重装方式
TL1 = RELOAD_COUNT; // 设定定时初值
TH1 = TL1; // 设定定时器重装值
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
// 开启中断
EA = 1; // 总中断控制
ES = 1; // 串口中断
}
// 串口发送一个字节
void UART_SendData(u8 dat) {
ES = 0; // 关闭串口中断
TI = 0; // 清发送完毕中断请求标志位
SBUF = dat; // 发送
while (TI == 0); // 等待发送完毕
TI = 0; // 清发送完毕中断请求标志位
ES = 1; // 允许串口中断
}
// 重写 putchar 函数, 然后就可直接用printf打印
char putchar(char c) {
UART_SendData(c);
return c;
}
// 串口发送字符串 保证字符串发送完整
void UART_SendString_DisIR(u8 *pbuf) {
ES = 0; // 关闭串口中断
TI = 0; // 清发送完毕中断请求标志位
while (*pbuf != '\0') // 遇到空格跳出循环
{
// UART_SendData(*pbuf);
SBUF = *pbuf; // 发送
while (TI == 0); // 等待发送完毕
TI = 0; // 清发送完毕中断请求标志位
delay_10us(5);
pbuf++;
}
ES = 1; // 允许串口中断
}
// 串口发送字符串,期间可被其它发送中断打断
void UART_SendString_EnIr(u8 *pbuf) {
while (*pbuf != '\0') // 遇到空格跳出循环
{
UART_SendData(*pbuf);
delay_10us(5);
pbuf++;
}
}
u8 xdata UART_RX_BUF[UART_REC_LEN]; // 接收缓冲,最大UART_REC_LEN个字节.带末尾结束符
/* 接收状态标记
bit15, 接收完成标志
bit14, 接收到0x0d,回车键标志,\r
bit13~0, 接收到的有效字节数目 */
u16 xdata UART_RX_STA = 0;
// 串口接收中断函数
void UART_IRQn() interrupt 4 {
u8 r;
if (RI) {
RI = 0; // 清除接收中断标志位
r = SBUF; // 读取接收到的数据
if ((UART_RX_STA & 0x8000) == 0) // 接收还未完成
{
if (UART_RX_STA & 0x4000) // 接收到了0x0d \r
{
if (r != 0x0a) { // 换行符,接收错误\n
UART_RX_STA = 0; // 接收错误,重新开始
} else {
UART_RX_STA |= 0x8000; // 接收完成了
UART_RX_BUF[UART_RX_STA & 0X3FFF] = '\0'; // 添加结束符
}
} else // 还没收到0X0D
{
if (r == 0x0d) {
UART_RX_STA |= 0x4000;
} else {
UART_RX_BUF[UART_RX_STA & 0X3FFF] = r;
UART_RX_STA++;
if (UART_RX_STA > (UART_REC_LEN - 2))
UART_RX_STA = 0; // 接收数据错误,重新开始接收
}
}
}
}
}
2、8*8矩阵led
//leds.h
#ifndef _LEDS_H_
#define _LEDS_H_
#include "public.h"
// 使用P0 P34 P35 P36
#define LEDDZ_COL_PORT P0 // 点阵列控制端口
// 定义 74HC595 控制管脚
sbit SRCLK = P3 ^ 6; // 移位寄存器时钟输入
sbit MRCLK = P3 ^ 5; // 存储寄存器时钟输入
sbit SER = P3 ^ 4; // 串行数据输入
void hc595_write_data(u8 dat);
void led_display();
#endif
//uart.c
#include "leds.h"
/********************************************************************
***********
* 函 数 名 : hc595_write_data(u8 dat)
* 函数功能 : 向 74HC595 写入一个字节的数据
* 输 入 : dat:数据
* 输 出 : 无
*********************************************************************
**********/
void hc595_write_data(u8 dat) {
u8 i = 0;
for (i = 0; i < 8; i++) // 循环 8 次即可将一个字节写入寄存器中
{
SER = dat >> 7; // 优先传输一个字节中的高位
dat <<= 1; // 将低位移动到高位
SRCLK = 0;
delay_10us(1);
SRCLK = 1;
delay_10us(1); // 移位寄存器时钟上升沿将端口数据送入寄存器中
}
MRCLK = 0;
delay_10us(1);
MRCLK = 1; // 存储寄存器时钟上升沿将前面写入到寄存器的数据输出
}
/********************************************************************
* 函 数 名 : led_display()
* 函数功能 : 在点阵上显示数据
* 输 入 : GLED_PER_COL_DATA 从左往右每一列的位选数据
* 输 出 : 无
* 备 注 : 无
* *********************************************************************
*/
void led_display() {
u8 i = 0;
for (; i < 8; i++) // 循环 8 次扫描
{
u8 tmp = (i == (point >> 4)) ? (GLED_PER_COL_DATA[i] | (0x80 >> (point & 0x0f))) : GLED_PER_COL_DATA[i]; // 获取当前列的数据
LEDDZ_COL_PORT = ~(0x80 >> i); // 传送列选数据
hc595_write_data(tmp); // 传送位选数据
delay_ms(1); // 延时一段时间,等待显示稳定
hc595_write_data(0x00); // 消影
}
}
3、红外
要用到定时器0
//timer.h
#ifndef _TIMER_H_
#define _TIMER_H_
#include "public.h"
void timer0_init();
void timer0_set_counter(u16 value);
u16 timer0_get_counter(void);
void timer0_cmd(u8 ensta);
/* // 定时器 0 中断1函数模板
void timer0_routine() interrupt 1 {
static u16 count = 0;
count++;
if (count == 1000) {
}
} */
#endif
//timer.c
#include "timer.h"
/****************************************************************
***************
* 函 数 名 : Timer0Init
* 函数功能 : 定时器 0 初始化,不使用中断
* 输 入 : 无
* 输 出 : 无
*****************************************************************
**************/
void timer0_init() {
TMOD &= 0XF0; // 清除定时器 0 模式位
TMOD |= 0X01; // 选择为定时器 0 模式,工作方式 1,仅用 TR0 打开启动。
TF0 = 0; // 清除 TF0 标志
TR0 = 0; // 定时器 0 停止
TH0 = 0xFC; // 给定时器赋初值
TL0 = 0x18;
// ET0 = 1; // 打开定时器 0 中断允许
// EA = 1; // 打开总中断
// PT0 = 1; // 设置定时器 0 为高优先级
}
/****************************************************************
* 函 数 名 : void timer0_set_counter(u16 value)
* 函数功能 : 设置定时器 0 计数值
* 输 入 : value 定时器 0 计数值
* 输 出 : 无
* ***************************************************************
*/
void timer0_set_counter(u16 value) {
TH0 = value >> 8;
TL0 = value;
}
/****************************************************************
* 函 数 名 : u16 timer0_get_counter(void)
* 函数功能 : 获取定时器 0 计数值
* 输 入 : 无
* 输 出 : 定时器 0 计数值
* ***************************************************************
*/
u16 timer0_get_counter(void) {
return (TH0 << 8) | TL0;
}
/****************************************************************
* 函 数 名 : void timer0_cmd(FunctionalState ensta)
* 函数功能 : 定时器 0 启动/停止
* 输 入 : ensta 定时器 0 启动ENABLE/停止DISABLE
* 输 出 : 无
* ***************************************************************
*/
void timer0_cmd(u8 ensta) {
TR0 = ensta;
}
用到中断0
//interrupt.h
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include "public.h"
void int0_init(void);
/* // 外部中断0中断函数模板
void int0_routine(void) interrupt 0 {
} */
#endif
//interrupt.c
#include "interrupt.h"
/**
* @brief 外部中断0初始化
* @param 无
* @retval 无
*/
void int0_init(void) {
IT0 = 1; // 下降沿触发
IE0 = 0; // 清除外部中断0标志
EX0 = 1; // 打开外部中断0
EA = 1; // 打开总中断
PX0 = 1; // 设置外部中断0为高优先级
}
红外
//ir.h
#ifndef _IR_H_
#define _IR_H_
#include "cnn.h"
#include "interrupt.h"
#include "public.h"
#include "timer.h"
/**
* 红外编码
* start-> 0: 900 * 10us 1: 450 *10us
* data:
* 0-> 0: 56 * 10us 1: 56 * 10us
* 1-> 0: 56 * 10us 1: 169 * 10us
* repeat-> 0: 900 * 10us 1: 225 * 10us
* 长度: 110ms
*/
void ir_init(void);
void cmd_exec(void);
#endif
//ir.c
#include "ir.h"
u16 ir_time;
u8 ir_state;
const u32 code C = 1;
u32 xdata ir_data; // 格式:地址+地址反码+命令+命令反码 8+8+8+8
u8 ir_data_index;
u8 ir_address;
u8 ir_command;
// 红外接收器初始化
void ir_init(void) {
timer0_init();
int0_init();
}
/* 普中自带遥控器 不好用
ir_data: ffffa25d 电源
ir_data: 0000629d Mode
ir_data: ffffe21d 静音
ir_data: 000022dd 启停
ir_data: 000002fd 左
ir_data: ffffc23d 右
ir_data: ffffe01f EQ e0
ir_data: ffffa857 VOL-
ir_data: ffff906f VOL+
ir_data: 00006897 0
ir_data: ffff9867 RPT
ir_data: ffffb04f U/SD
ir_data: 000030cf 1
ir_data: 000018e7 2 18
ir_data: 00007a85 3
ir_data: 000010ef 4 10
ir_data: 000038c7 5 38
ir_data: 00005aa5 6 5a
ir_data: 000042bd 7
ir_data: 00004ab5 8 4a
ir_data: 000052ad 9
*/
/* switch (ir_command) {
case 0x18: { // 2 y-
if ((point & 0x0f) == 0)
point |= 0x07;
else
point--;
break;
}
case 0x4a: { // 8 y+
if ((point & 0x0f) == 7)
point &= 0xf0;
else
point++;
break;
}
case 0x10: { // 4 x-
if ((point & 0xf0) == 0)
point |= 0x70;
else
point -= 0x10;
break;
}
case 0x5a: { // 6 x+
if ((point & 0xf0) == 0x70)
point &= 0x0f;
else
point += 0x10;
break;
}
case 0x38: { // 5 反转
GLED_PER_COL_DATA[point >> 4] ^= (0x80 >> (point & 0x0f));
break;
}
case 0xe0: { // 开始
break;
}
} */
/*
小米万能遥控器 3MDVD播放机
ir_data: ffff 80 7f 上
ir_data: ffff 90 6f 下
ir_data: ffff 98 67 左
ir_data: ffff 88 77 右
ir_data: 0000 02 fd OK
ir_data: ffff e8 17 开始
e0 清除
*/
// 命令执行
void cmd_exec(void) {
switch (ir_command) {
case 0x80: { // 上 y-
if ((point & 0x0f) == 0)
point |= 0x07;
else
point--;
break;
}
case 0x90: { // 下 y+
if ((point & 0x0f) == 7)
point &= 0xf0;
else
point++;
break;
}
case 0x98: { // 左 x-
if ((point & 0xf0) == 0)
point |= 0x70;
else
point -= 0x10;
break;
}
case 0x88: { // 右 x+
if ((point & 0xf0) == 0x70)
point &= 0x0f;
else
point += 0x10;
break;
}
case 0x02: { // ok 反转
GLED_PER_COL_DATA[point >> 4] ^= (0x80 >> (point & 0x0f));
break;
}
case 0xe0: { // 清除
u8 i = 0;
for (; i < 8; i++) {
GLED_PER_COL_DATA[i] = 0;
}
break;
}
case 0xe8: { // 开始
get_res();
break;
}
}
}
// 外部中断0中断函数模板
void int0_routine(void) interrupt 0 {
if (ir_state == 0) { // 空闲状态
timer0_set_counter(0); // 下降沿触发,进入中断,开始计时解码
timer0_cmd(ENABLE);
ir_state = 1;
} else if (ir_state == 1) { // 等待Start信号或Repeat信号
ir_time = timer0_get_counter(); // 下一个下降沿到达,计算时间
timer0_set_counter(0); // 计时器清零
if (ir_time > 12442 - 1000 && ir_time < 12442 + 1000) {
ir_state = 2; // 接收到了Start信号 9ms+450ms; 之后进行数据接收
} /* else if (ir_time > 10368 - 1000 && ir_time < 10368 + 1000) {
// 接收到了Repeat信号 9ms+2.25ms; 之后结束
timer0_cmd(DISABLE);
ir_state = 0;
// cmd_exec();
} */
else {
ir_state = 1; // 接收出错,两下降沿时间差不对;重新接收,等待下一个下降沿时间差
}
} else if (ir_state == 2) {
ir_time = timer0_get_counter();
timer0_set_counter(0);
if (ir_time > 1032 - 1000 && ir_time < 1032 + 500) { // 接收到数据0
ir_data &= ~(0x0001 << (31 - ir_data_index));
ir_data_index++;
} else if (ir_time > 2074 - 500 && ir_time < 2074 + 1000) { // 接收到数据1
ir_data |= 0x0001 << (31 - ir_data_index);
ir_data_index++;
} else { // 接收出错,两下降沿时间差不对;重新接收,等待下一个satrt/repeat信号
ir_data_index = 0;
ir_state = 1;
}
if (ir_data_index >= 32) { // 接收到了32位数据 8+8+8+8
ir_data_index = 0;
/* ir_address = (u8)(ir_data >> 24);//省略 */
ir_command = (u8)(ir_data >> 8);
timer0_cmd(DISABLE);
ir_state = 0;
// 数据验证 普中的红外遥控器 地址与反码相同,命令与反码按位取反
if (/* (ir_address == (u8)(ir_data >> 16)) &&//省略 */ (ir_command == ~(u8)(ir_data))) {
cmd_exec();
}
}
}
}
4、LCD
lcd原来的8位数据口接在P0上,但P0被矩阵led用了,所以用杜邦线接到P1上,换一下LCD_DataPort
//lcd1602.h
#ifndef __LCD1602_H__
#define __LCD1602_H__
#include "public.h"
#include "reg52.h"
// 引脚配置:
sbit LCD_RS = P2 ^ 6;
sbit LCD_RW = P2 ^ 5;
sbit LCD_EN = P2 ^ 7;
#define LCD_DataPort P1
// 用户调用函数:
void LCD_Init(); //
void LCD_ShowString(u8 Line, u8 Column, char *String); //
#endif
//lcd1602.c
#include "lcd1602.h"
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(u8 Command) {
LCD_RS = 0;
LCD_RW = 0;
LCD_DataPort = Command;
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
delay_ms(1);
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(u8 Data) {
LCD_RS = 1;
LCD_RW = 0;
LCD_DataPort = Data;
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
delay_ms(1);
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(u8 Line, u8 Column) {
if (Line == 1) {
LCD_WriteCommand(0x80 | (Column - 1));
} else if (Line == 2) {
LCD_WriteCommand(0x80 | (Column - 1 + 0x40));
}
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD_Init() {
LCD_WriteCommand(0x38); // 八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c); // 显示开,光标关,闪烁关
LCD_WriteCommand(0x06); // 数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01); // 光标复位,清屏
}
/**
* @brief 在LCD1602指定位置开始显示所给字符串
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串
* @retval 无
*/
void LCD_ShowString(u8 Line, u8 Column, char *String) {
u8 i;
LCD_SetCursor(Line, Column);
for (i = 0; String[i] != '\0'; i++) {
LCD_WriteData(String[i]);
}
}
5、识别
可以在电脑上训练,但要在51上识别,不能用库
不会,去找了个能懂的视频:10分钟!60行代码!从零实现数字识别【不调用任何深度学习库】 可行
5.1 获取数据集
没有8*8点阵的数据集,为了方便用uni-app写了个网页,花了十几分钟手搓了500个
<template>
<view style="display: flex;flex-direction:row" class="content">
<view style="width: 620px;margin-right: 20px;margin-left: 40px;">
<scroll-view style="border: 2px solid #ccc;height: 400px;" scroll-y>
<text selectable>{{content}}</text>
</scroll-view>
<view style="display: flex;flex-direction: row;margin: 10px;">
<button @click="dialog">清除</button>
<button @click="storage">存储</button>
<text>数量: {{cnt}}</text>
</view>
</view>
<view class="content">
<view class="content">
<view v-for="i in [0,1,2,3,4,5,6,7]" :id="i">
<button style="width: 40px;height: 40px;text-align: center;border: 0px;" :type="primarys[i][j]"
v-for="j in [0,1,2,3,4,5,6,7]" :id="`${i}${j}`">{{nums[i][j]}}</button>
</view>
</view>
<view class="content" style="flex-direction: column;margin: 10px;">
<input type="button" @input="input" style="width: 40px;border: 2px solid #ccc;margin: 10px;" />
<button style="margin: 5px;" @click="save">暂存</button>
<button @click="clear">清除</button>
</view>
</view>
</view>
<!-- 加确认框,搓了一大堆,点错了就很淦 -->
<uni-popup ref="popup" type="dialog">
<uni-popup-dialog mode='base' type='warn' :duration="2000" :before-close="true" @close="popup.close()"
@confirm="clearContent"></uni-popup-dialog>
</uni-popup>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { onLoad, onReady } from '@dcloudio/uni-app'
const nums = ref<number[][]>([])
const primarys = ref<string[][]>([])
const digit = ref('0')
const cnt = ref(0)
const content = ref('')
const popup = ref<any>(null)
//输入当前的字符画的值
const input = (event) => {
digit.value = event.detail.value
}
//保存到文件的函数 https://blog.csdn.net/dangfulin/article/details/141495821
function saveToFile(content, filename) {
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filename;
// 这行是必要的,用于在浏览器中触发下载
document.body.appendChild(link);
link.click();
// 清理并移除链接
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
//保存 按列衔接存为一行
const storage = () => {
console.log('存', content.value);
saveToFile(content.value, `${digit.value}.txt`)
clearContent()
}
const dialog = () => {
popup.value.open()
}
//清除已暂存的字符画
const clearContent = () => {
content.value = ''
cnt.value = 0
popup.value.close()
}
//鼠标按下和抬起事件 用于左键按下时画数字字形
let flag = false
addEventListener('mousedown', () => { flag = true })
addEventListener('mouseup', () => {
flag = false
})
let hasEnter : boolean[][] = [] //再次滑入时,不反转
let eles : HTMLElement[][] = []
onReady(() => {
//获取8*8每个按钮 添加鼠标滑入事件 画字型
for (let row = 0; row < 8; row++) {
eles.push([])
for (let col = 0; col < 8; col++) {
eles[row][col] = document.getElementById(`${row}${col}`)
eles[row][col].addEventListener('mouseenter', () => {
if (flag && !hasEnter[row][col]) {
change(row, col)
hasEnter[row][col] = true
}
})
eles[row][col].addEventListener('mousedown', () => {
//添加滑动事件起始点的按下事件 从起点开始
change(row, col)
hasEnter[row][col] = true
})
}
}
})
// 反转
const change = (row : string | number, col : string | number) => {
nums.value[row][col] = nums.value[row][col] ? 0 : 1
primarys.value[row][col] = nums.value[row][col] ? 'warn' : 'primary'
}
//暂存 这里行列反转了??? 不知道为什么 不过刚好要按列存取
const save = async () => {
let str = ''
str = `${digit.value}\n`
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
str += `${nums.value[row][col]}`
}
}
str += '\n'
content.value += str
cnt.value++
clear()
}
//清除数字字形
const clear = () => {
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
hasEnter[row][col] = false
nums.value[row][col] = 0;
primarys.value[row][col] = 'primary'
}
}
}
//初始化
onLoad(() => {
for (let row = 0; row < 8; row++) {
hasEnter.push([])
nums.value.push([]);
primarys.value.push([])
for (let col = 0; col < 8; col++) {
hasEnter[row][col] = false
nums.value[row][col] = 0;
primarys.value[row][col] = 'primary'
}
}
})
</script>
<style>
.content {
display: flex;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
5.2 数据集处理
乱序一下
import random
nums = ''
for i in range(10):
with open('D:/Hardware/cnn_c90/datasets/num'+str(i)+'.txt', 'r') as f:
nums += f.read()
with open('D:/Hardware/cnn_c90/datasets/nums.txt', 'w') as f:
f.write(nums)
datas = []
num = ''
flag = 0
with open('D:/Hardware/cnn_c90/datasets/nums.txt', 'r') as f:
for line in f.readlines():
if flag == 0:
flag = 1
num = line
else:
flag = 0
num = num+line
datas.append(num)
# print(num)
# print(datas)
# 乱序
random.shuffle(datas)
print(datas)
with open('D:/Hardware/cnn_c90/datasets/trans_nums.txt', 'w') as f:
for data in datas:
f.write(data)
5.3 训练
修改一下代码,训练并存储数据集
import numpy as np
from tqdm import trange
class Dataloader:
"""数据读取"""
def get_data(self, path, cnt):
"""对原始数据进行处理..."""
images, labels = [], [] # 获得原始数据
# images = np.reshape(images, (cnt, 28 * 28)) # 28*28的矩阵拉伸为1*784的矩阵
with open(path, 'r') as file:
for _ in trange(cnt, desc='读取原始数据: '):
labels.append(int(file.readline()[0])) # 读label
img = []
for c in file.readline():
if c != '\n':
img.append(int(c))
images.append(img)
images = np.array(images)
labels = np.eye(10)[labels] # 单独的标签扩展为[0..9]的矩阵
print("\033[31m对原始数据进行处理......Done\033[0m")
return images, labels
def save(wih, who, bih, bho):
with open('model88.txt', 'w') as file:
file.write('float wih[20][64] = {')
for i in wih:
file.write('{')
cnt = 0
for j in i:
file.write(str(j))
cnt += 1
if cnt != 64:
file.write(', ')
file.write('}, ')
file.write('};\n')
file.write('float who[10][20] = {')
for i in who:
file.write('{')
cnt = 0
for j in i:
file.write(str(j))
cnt += 1
if cnt != 20:
file.write(', ')
file.write('}, ')
file.write('};\n')
file.write('float bih[20][1] = {')
for i in bih:
file.write('{')
for j in i:
file.write(str(j))
file.write('}, ')
file.write('};\n')
file.write('float bho[10][1] = {')
for i in bho:
file.write('{')
for j in i:
file.write(str(j))
file.write('}, ')
file.write('};\n')
if __name__ == "__main__":
# 通过dataloader读取数据
dataloader = Dataloader()
images, labels = dataloader.get_data("D:\\Hardware\\cnn_c90\\datasets\\trans_nums.txt", 500)
# 创建模型
# 本代码重在快速实现神经网络,因此对模型不做封装
w_i_h = np.random.uniform(-0.5, 0.5, (20, 64)) # 设置浮点位数float32
w_i_h = w_i_h.astype('float32')
w_h_o = np.random.uniform(-0.5, 0.5, (10, 20))
w_h_o = w_h_o.astype('float32')
b_i_h = np.zeros((20, 1), dtype=np.float32)
b_h_o = np.zeros((10, 1), dtype=np.float32)
# 训练模型
# - 设置超参数
learn_rate = 0.01
nr_correct = 0
epochs = 2000
for epoch in range(epochs):
for img, l in zip(images, labels):
img.shape += (1,)
l.shape += (1,) # 转纵向
# 前向传播
# - 输入层->隐藏层
h_pre = b_i_h + w_i_h @ img
h = 1 / (1 + np.exp(-h_pre))
# - 隐藏层->输出层
o_pre = b_h_o + w_h_o @ h
o = 1 / (1 + np.exp(-o_pre))
# - 损失函数计算
e = 1 / len(o) * np.sum((o - l) ** 2, axis=0)
nr_correct += int(np.argmax(o) == np.argmax(l))
# 反向传播
# - 输出层->隐藏层
delta_o = 0.2 * (o - l)
delta_z = (o * (1 - o))
delta_w_h = np.transpose(h)
w_h_o += -learn_rate * delta_o @ delta_w_h * delta_z
b_h_o += -learn_rate * delta_o
# - 隐藏层->输入层
delta_h = np.transpose(w_h_o)
delta_z_2 = (h * (1 - h))
delta_w_i = np.transpose(img)
w_i_h += -learn_rate * delta_h @ delta_o * delta_z_2 @ delta_w_i
b_i_h += -learn_rate * delta_h @ delta_o * delta_z_2
# 输出精准度
print(f"Acc: {round((nr_correct / images.shape[0]) * 100, 2)}%")
nr_correct = 0
# 展示效果
while True:
save(w_i_h, w_h_o, b_i_h, b_h_o)
index = int(input("输入编号进行预测"))
img = images[index]
label = labels[index]
img.shape += (1,)
# 前向传播
h_pre = b_i_h + w_i_h @ img.reshape(64, 1)
h = 1 / (1 + np.exp(-h_pre))
o_pre = b_h_o + w_h_o @ h
o = 1 / (1 + np.exp(-o_pre))
print(f"label: {label.argmax()}, predicted: {o.argmax()}")
5.4 在C90上再验证
C51上C语言是C90版本
//main.h
#ifndef CNN_C90_MAIN_H
#define CNN_C90_MAIN_H
#define u8 unsigned char
#define u16 unsigned int
float wih[20][64] = {
{-0.90370303, -1.6227865, 0.006758991, -0.043860592, -0.90419644, -1.5324701, -0.4218245, 0.093345255, 0.25426397, 0.42317036, 0.27248868, -0.838949, -2.093729, -1.0263836, 0.45135808, -0.33422244, 0.38394472, -0.2922178, -0.12184342, -0.8867094, -1.8839365, 0.22697262, -0.5545746, 0.07332433, -0.24611361, 0.86308557, 0.5044917, 0.062405705, -2.4997396, -0.7037517, -0.17633998, 0.25601822, -0.35345513, 0.61995137, -1.0216911, -0.330688, -2.0762396, -0.7677815, 0.5156707, -0.16015412, 0.46908054, -1.9604108, -0.29565606, -0.457637, -0.06060111, -0.61806655, 0.84591347, -0.14021254, 0.09382368, 1.2968239, -1.2011486, -2.160614, -0.81069696, -0.015993768, 0.86204576, -0.22618859, -0.17467403, -0.7236278, 0.41246638, -0.07713144, -0.3216405, -0.6040587, -0.31066683, 0.33204365},
{-0.18481503, 0.02653262, 0.5838272, -0.013661329, -0.19371973, 1.4654182, -0.16194782, 0.3047478, 0.21975555, 0.5717147, 0.909599, -0.9400009, -0.34779134, 1.8818125, -0.49049872, 0.3848227, 0.46840906, -0.26648197, 0.055842612, 0.42987975, 0.931795, 1.8954206, 0.12181818, -0.19418885, 0.6967165, 0.8170402, -0.14423162, 0.32624382, 1.3851455, 1.3319912, -1.1704016, -0.13452211, -0.11261311, -0.41096523, 0.6911238, 2.0207267, 0.007220461, -0.35985875, -0.40490603, -0.4454801, 0.5191932, 1.2247704, -0.4550718, 1.7727829, 0.42461827, -0.7293822, -0.301481, 1.30334, 0.44246933, -1.0345244, 0.84448487, 0.114373475, -1.3343246, 0.42405686, -0.2457504, 1.5834155, 0.53824705, -0.06273292, 0.17574663, 2.1929073, -0.43338934, 1.1680564, -0.9566098, 0.61969316},
{-0.08448971, -0.06244183, 0.20608118, 1.8847405, 1.8401487, 1.0568348, -0.54447895, -0.42619503, -1.0028598, -0.7916237, 0.7776437, 2.6451797, 1.4491127, 1.3515941, -0.1525097, -0.9111067, -0.35362643, 0.67927057, -0.22971867, 1.7717862, 2.084796, 0.72105414, 0.46293026, -0.3687547, -0.04160447, -1.201657, 0.37202802, -0.97886324, -0.32591164, -2.5771186, -0.95847386, -0.07437611, -0.7089568, 0.32310572, 0.08149235, 0.34042874, 0.32750925, 1.0343381, -1.4179256, -1.8821793, -1.983775, 0.93952405, 1.2394896, 1.4812709, 0.2726556, 0.27329028, -1.2619059, -2.325326, -0.6536865, 0.127664, -0.11920281, 0.70355153, 0.79011184, -0.2506556, -0.8062013, 0.012836788, 0.2328178, -0.068411306, -0.7334768, 1.7404035, 0.8091098, 1.1574407, 2.0655131, 0.47859055},
{-0.28008026, -0.32492366, 0.13952315, -0.41921338, -0.5023364, -1.2394183, -0.3949447, 0.4893474, -0.57464814, -0.56293637, 0.060509097, 0.039110083, -1.4391131, -0.1481465, -1.0518702, -0.040501382, -0.7300588, -0.5928659, -0.44644672, 0.05788317, -2.3058808, 0.64715236, -0.6008122, -0.12720154, -0.0058052554, -0.34468967, -0.45653287, -0.7098025, -2.8473496, 0.033189263, -0.15926114, -0.19961172, 0.10261695, -0.697879, -0.5346125, -0.33358884, -1.9487486, 0.16498438, -0.33422765, -0.33342296, -0.4264499, -0.28664133, -0.087725945, -0.70558876, -0.35886464, -1.1452191, -0.77950174, 0.27590302, 0.0981756, 0.24444334, -0.42614698, -0.11963545, -0.64529085, -0.121452585, -0.3471749, -1.6613324, -0.5887918, 0.15745597, -0.6374025, -0.5649907, -0.65113693, -0.2332076, -0.11517975, -0.38157293},
{-0.23989499, 0.10138975, 0.2992003, 1.3381269, 1.050818, -1.1137307, 0.2794603, -0.074104175, 0.35742193, 0.5488519, -0.55003595, 2.6086407, 1.1276761, -1.805448, 0.31624112, -1.0226605, -1.0375922, -1.3576412, 0.6522544, 1.4344914, 2.9542446, -0.8358149, -0.03914513, 0.026673306, -1.3996806, 0.39960584, -0.9237489, -0.595945, 2.6251652, 1.628705, -0.36176848, 0.15991825, -1.8657323, -2.171719, 0.8560495, -0.236917, 1.7283155, -0.077344574, 0.30085137, 0.6763216, 0.5794219, -1.6057203, -2.4041576, 1.7152463, 1.3750616, 2.0734801, 0.43874618, -0.037784614, 0.49655357, -0.007411618, -1.2285866, 1.965862, 1.965069, -0.047366317, -0.106121145, -0.60989666, -1.1255263, -0.39952987, -0.012124025, 0.14022711, -0.8944051, 1.721918, 1.7988228, 0.59003425},
{-0.10961173, -0.6910169, -0.8075776, -0.74457544, 0.053036503, 0.5468102, -0.04126562, 1.0954581, -1.2138356, -1.4219544, -0.81520236, 0.06809384, -1.6032428, -0.46908212, 0.53823084, 0.8055395, -2.0159664, -0.28746095, -1.1964657, 1.020267, -1.6349722, -1.05356, -0.43398958, 1.2818125, -0.74442136, -0.14068039, -0.018787296, 0.82255083, -0.67692673, 1.908894, 1.9061124, 1.8043677, 0.7050398, 0.81938165, 0.69161284, 0.004269418, 0.5949326, -0.43212122, 0.24324839, 0.8079723, 0.67968553, 0.33509198, 1.1000239, -0.11229033, 0.80615014, -1.2090825, 0.49910334, -0.7847982, -0.5413785, -1.0303452, 0.614484, -0.63636, 0.13785855, 0.6207389, 1.8965181, -1.579762, 0.9521444, -0.5475616, 0.11707687, -0.72770244, -0.6405429, -1.4559705, -0.5141972, -1.5517235},
{-0.17733128, 0.19089474, -1.78983, -1.081373, 0.007871058, -0.21385096, 1.1410884, 1.7022002, -1.083664, -0.6007506, -1.7507249, -1.5028456, 0.515323, 1.8474102, 2.5001929, 1.363286, -0.2868847, -1.6242372, -2.2344706, -1.8678485, -0.08318619, 4.3101273, 2.8022432, 2.2247834, -0.1304224, -0.022850921, -2.0945702, -1.044108, 0.7445825, 0.5423329, 1.3169034, -0.39946398, -0.078247, -0.3732368, -1.3609457, -0.81833595, 0.5006247, 1.7806033, 0.012465007, 0.40372467, -0.12701432, 0.000118904456, 1.0033633, 0.395385, -1.1447972, -0.32591328, -0.41404682, 0.4038883, 0.060149994, 0.9167585, 0.6525008, 0.05794753, -0.7027614, -1.601301, 0.7910355, 0.75375915, 0.42463538, 1.6335574, 1.1835599, -0.5365144, 0.13045251, -2.008306, -1.5719049, -0.17551544},
{0.19962265, 0.9040419, -0.41108456, 0.39710236, 0.0035398765, -2.160669, 0.7407019, 0.4443096, 0.66132635, 1.0680324, 0.04655871, -0.12773506, 0.44296113, -2.1415608, 0.053617466, -0.7654339, -0.55000913, 1.5437307, 0.76365995, -1.353169, -1.4267856, 0.26567465, -0.43128905, 0.5080227, -0.48528558, -0.30378145, 0.81417274, -1.0511185, 0.36138734, -0.95792973, 0.8910673, 0.48785105, -0.8904035, -0.48377457, -0.9980029, 0.9112535, 1.2852162, 1.8648367, -1.9632885, -1.9034109, -1.2496066, -0.8188213, -0.3973547, 0.803014, 1.5538423, 1.3795141, -1.9660959, -1.6505208, 0.528507, 0.10899826, -0.9490996, 0.31345358, 2.1494527, 2.2068872, -2.098412, -1.9218686, -0.047385182, -0.45520595, -0.72099555, 0.09160803, -0.68403226, 0.14585863, -2.0611656, -1.38465},
{0.21106721, -0.5663376, -0.06548628, 1.0173254, 0.5995677, 1.9299055, -0.40289268, 0.024142932, -1.0630907, -0.69513875, 0.25633487, 1.6963174, 0.13189907, 0.82432437, -1.1637928, 0.51822656, 0.29654595, 1.0964646, -0.42981228, 1.1963503, 0.5458766, -1.0733994, 0.062050987, 0.8061106, 0.8928707, 0.41125992, 0.7230523, -1.0004281, -0.888854, -0.15059184, 0.6819982, -0.46539697, 0.40095344, 0.22693694, 2.7507834, -0.9765539, -0.91406816, -0.10050919, -1.1451228, -0.22315933, 0.07438359, 0.3475488, 0.72298115, -0.334541, -0.37646225, 1.568643, -0.08113724, -0.21746147, -0.5260564, -0.0854731, 0.6572121, -0.17562199, 0.112107925, -0.04485716, 0.27897155, 0.24553575, 0.97808814, -1.172291, 0.61723995, -0.026501855, 0.73604804, 0.41664672, 1.6242247, 0.25898677},
{-0.53685343, 0.27027404, -1.1696752, -0.54213065, -0.9190853, 0.032319013, -0.34781703, -0.030913185, -0.78295964, -0.12853839, 0.31618023, -0.13328803, -0.72663397, -1.0652502, -1.0067376, 0.17512704, -1.2194577, 0.48107573, -0.009092109, 1.4251565, -2.1243641, -1.5384041, -1.4705309, -0.23642352, -0.1395358, -0.2937295, 0.79682684, -0.6543225, -1.2825743, -1.3568541, -2.046398, 0.38330445, 0.89847195, -1.926154, -0.50696033, 0.77036566, -0.61016494, -0.87539107, 0.7526837, 0.14578561, -1.0635902, -1.0321178, -0.03627153, -0.8321174, 0.124524646, -0.29681563, -0.9913249, -2.7048078, -0.2572564, -0.54465157, 0.3804953, -0.11894237, 1.3975478, -0.008739124, -0.8481273, -1.0363187, -0.37653932, -0.54376435, -1.5431976, -0.12845016, -0.60287046, 0.67853427, -0.7169106, -0.4367748},
{0.55981463, -1.1641444, -0.36438262, 0.49444607, -1.0161186, -0.4240448, 0.20644581, -0.62189525, 1.1042548, 1.0055594, -2.061804, 1.2896538, -1.2618608, -0.71236306, -0.47882888, -0.8935898, 1.2771006, 0.97737974, -3.830193, -0.25664732, 0.51526153, 0.22470197, -0.50966203, 0.098472625, 1.1269736, 1.911295, -2.9255779, 0.46280265, -0.54787755, -0.4255831, -0.3026523, -1.6471986, 0.54709363, 1.3116968, -1.8969926, 0.4624718, 0.33354384, -0.18805933, -0.80478185, -0.33723733, 1.6190752, 0.29034436, -1.6392403, -0.8218444, 0.45748937, 0.65462816, -0.4847167, 0.35811973, 0.51573914, 0.56112254, -0.6837801, -0.43257478, 0.39162534, -0.7721747, 0.30401266, -0.20256715, -0.12978405, -0.5179902, 0.14528042, -0.59022826, -0.37835497, -0.6044354, 0.47107688, -0.048978478},
{-0.830407, 0.94868946, -0.053021755, -1.1392072, 1.0258931, 0.47930944, -0.48818755, -0.53598684, -1.5286567, -0.8185924, -0.44352934, -1.5855994, 1.6295936, 1.5565491, -0.4594488, 0.14589135, -1.4498606, -0.09638974, -0.44209823, -1.1448265, 1.1553231, 0.96300036, 0.297711, -0.33486265, -0.5996388, -0.12269726, 0.34538034, 0.49682134, 1.7431875, 1.7270001, 0.61359435, -0.08531431, 1.1194985, -0.25395283, 0.45225948, -0.33254093, -0.49142018, -0.09798046, 1.267901, 0.5959748, -0.49928436, 1.3182635, 1.3479398, 0.22353283, -2.2125974, -1.7501084, -1.570047, 0.7581281, -1.5386926, -0.13848302, 1.7402154, -0.43388996, -1.3112538, -1.3563507, -1.4564803, 0.98386186, -0.6580134, 1.0460929, 0.14173871, 0.014983103, -0.3311887, -0.7476836, -1.0842048, 1.324009},
{0.68236923, -0.22740963, 0.52448624, -0.9560157, -1.2619071, -0.5293657, 0.011023371, 0.07411865, 1.1045678, 1.1866201, 2.147629, -1.9600328, -2.3767853, -1.2986689, -0.3469053, -0.59443754, 1.082573, 1.9886897, 2.172237, -1.505816, -3.6129553, -1.9031959, 0.39116213, -1.9117448, -0.15495397, 1.135125, 1.0872302, -0.38543183, -2.7717972, -0.39545128, -0.310394, -1.0636134, 0.1442277, 1.5422833, 1.7938291, -0.15417123, -1.6487888, -1.924555, -0.40387183, -0.41476652, 1.2580423, 0.4767336, 0.24072565, -1.7017186, 0.9077837, -1.4571995, -0.32456416, 0.09176439, -0.51802343, -0.5290213, 0.2875309, -1.0347015, -0.27685422, 0.6302265, 1.1248074, -0.042384047, 0.8554518, -1.3651886, 0.30563542, 0.20699824, 0.81288546, -0.19746333, 0.08890713, -0.07507332},
{0.18937048, 0.77593446, -0.040826846, 0.099822596, 0.57205415, 1.2541627, 1.0013996, -0.33150408, -0.6795878, -1.1206908, -2.3181443, -2.2846894, -0.9032402, -0.8503272, -0.80560136, -0.29473165, -1.2669241, -1.1187165, -0.70434606, -0.06093113, -1.077079, 0.10603313, 0.6304957, -0.49328232, -0.7709547, 0.09944248, 0.41406354, -0.48928174, -0.3448364, 0.21150301, 1.2581388, 0.23117699, -1.0022889, 0.36110094, -0.41405913, -0.9597568, -1.6323218, -1.9287173, 2.4731805, 0.8826079, 0.1360742, 0.18998435, 0.74651414, -1.1459556, -1.4628974, -0.3990078, 0.8810199, 1.5831354, -0.2623827, -0.2921589, -1.1026233, -2.7658184, 0.719363, 0.26870668, 0.80756474, 1.0329471, -0.41529283, 0.0027868305, -0.4184263, -1.2974318, -0.30777633, -0.26390573, 1.4770379, 0.9305804},
{0.36492628, 0.36246073, -1.4070342, 0.19662166, -0.36329585, -1.1904411, -1.7952766, -0.54342365, -0.6235874, -1.0528649, -0.47347894, -0.03536505, -0.20266142, -0.13796166, 0.3857793, 0.0076133083, -0.5478579, -1.1103225, -1.2550813, 0.49446392, -0.23652314, 0.28063926, 0.2296214, -0.8089566, -0.71379924, -0.8116344, -0.526067, 0.16365132, -0.3768348, -0.18086562, -0.6915715, -0.02932218, -0.17227441, -0.7566376, -3.1160433, 0.24207872, -0.6844323, 0.56241745, 0.7641027, 0.86661625, -0.724756, -0.5956835, -2.906026, -0.82029223, -0.5280052, 0.9328222, 0.80980295, 0.8583568, -0.39354998, -1.3343416, -2.1438155, -2.5177836, 0.87976205, 0.89891636, 1.4128779, 0.8357512, -1.0261161, -0.23148231, -0.6294251, -2.893315, -1.4009511, 0.06735018, 0.42385456, 0.9046616},
{0.119352, 0.9772793, 0.6384963, -2.2011478, -1.2524942, -2.037623, 0.24083075, 1.3094004, 0.5211749, 0.12588285, -0.5309135, -3.0644922, -0.46507192, -0.39234996, 1.3498019, -0.1483634, 1.1638854, -0.44192886, -1.13133, -1.0038191, -0.4557811, -1.4647924, 0.84541106, -0.01636926, 0.24002273, -1.6808751, -0.59616137, -1.3520907, 1.7963015, -3.0386841, 0.6586133, 0.7790693, 0.1513685, -0.9849836, -1.7251946, 0.044953015, -0.5753291, -0.7783064, 0.18381253, 0.40621015, -1.0306864, 0.5543329, -0.46208987, -0.020203413, -0.37550324, -1.5528892, -0.7203983, 0.498279, -0.9656106, -0.69982404, -0.32651168, 0.11979463, -2.2027533, -0.31584767, 0.024807813, 0.45917353, 0.21653223, 0.83372307, 0.27598244, 0.09120625, 0.45691663, -0.42203763, -2.0963845, -0.31434712},
{0.9694672, -0.21618915, 1.2000359, 1.4444586, 0.12763503, -0.44007143, -0.52253795, 0.19511013, 0.4814508, 0.69288373, 0.80209935, 1.1408228, -0.5770815, -0.69757074, -1.8381656, -0.93887925, 0.29420453, 0.66520464, 0.64318985, 0.1131627, 2.4804077, -1.730284, -2.6548784, -1.5249332, 0.2816821, 0.1806157, -0.20500597, -0.35767922, 1.2063946, -2.2370265, -1.7448623, -1.3403648, -0.67782694, -0.29558426, -0.053324327, -0.43356156, -0.38445562, -1.290601, -0.55036163, -0.7919362, -0.8212288, 0.19941059, 0.20044178, -0.50659764, -0.6866085, -0.9537341, -0.022947935, 0.6344333, 0.04698309, 0.38625598, 0.21129276, -0.14701809, -0.9243069, -0.40494016, -1.9157158, -1.2349731, -0.16974495, -0.7973496, -0.49334237, 0.33268788, -0.30658814, -0.24022289, -0.8470375, -0.77296454},
{1.3792558, 0.3600045, 0.5468229, -0.08909639, -0.8382965, -0.9029627, -1.28078, -0.63418335, -0.84982574, 0.016387843, 1.9495778, 0.89398104, -0.2777039, -0.7896938, -0.81972706, -0.38913116, 0.3948264, 1.4004004, 1.5675489, 0.7240448, -0.2528365, -0.7263563, -0.9510525, -0.688148, -0.06977625, -0.3690885, 0.5533377, 0.9727561, -0.029515458, -0.24345532, -0.21802844, -0.18032533, -0.47439632, -1.7230483, -1.3562231, -0.6619784, 0.88759995, 1.3869495, 1.1429521, 0.654589, -0.031451512, -1.5425696, -1.8436652, -1.8672744, 1.3021322, 1.9544067, 0.5191355, 1.3214257, -0.06958157, -0.72234243, -1.9390411, -1.3050647, 1.0565604, 0.9678962, 0.98017687, 1.3023964, -1.5278738, -0.23616996, -1.585107, -2.2699115, -0.53853023, 0.8132038, 0.7590706, 0.73317206},
{-0.8187737, 0.467179, -0.73361504, -0.3407762, -0.26293063, -1.0500106, 0.4947593, -0.21366, 0.18561968, -0.16594592, 0.14173563, 1.6936625, 1.7120253, -1.424868, 0.76361907, -0.83822757, -0.17544578, -0.011800428, 0.91934395, 1.3541225, -1.2425042, -0.156594, 0.7947865, -0.48207992, 1.3447042, -0.25073656, 1.4096646, 2.8795881, -0.5136539, -1.0368112, -0.4362688, 0.7306975, -0.09019608, 0.39012805, 0.5691338, 1.162135, 1.8983095, -0.36212087, -0.7184063, -0.27831712, -1.7150927, 0.594438, 1.2943473, 0.41104338, 0.46464878, 1.0006706, 0.35518378, -2.0451317, -1.5307034, 0.8499877, 1.1447632, 2.1680858, 1.1034998, 1.1369995, -1.002666, -0.83564883, 0.9039399, 0.22262073, -0.12268762, 2.3627865, 0.3677706, 0.73920745, 0.026835948, -1.3977033},
{1.2600089, 0.067648366, 0.9185, 0.07245796, 0.033649117, 1.0299469, 0.23839106, -0.29191506, 1.7282989, -0.31482607, 0.32536986, -0.17893313, -1.0621817, 0.55509955, 2.07455, -0.016044078, 2.167265, -0.04853997, 1.5335227, -1.4178636, 0.16353802, 0.87930965, 0.4386904, 0.12409826, 0.60591596, 0.72009134, 0.57418287, -1.4734936, -0.58911437, 1.4214422, -1.1867632, 0.033941027, 0.6741393, 3.6147294, -0.904962, -0.13489676, -1.5109322, 0.60367405, 0.7773489, -1.0289242, 2.8056302, -0.29122135, -2.1291616, -0.6375071, -0.08076189, 1.2950406, 0.92092115, -0.33424875, 0.9759254, 0.6305621, -1.8993558, -1.6752487, 1.627763, -0.37919223, 1.0123148, 0.53763217, 0.2818548, 0.41636023, -0.42767346, -1.1393545, 0.3400047, -0.78577006, 0.9938756, 0.72512734},};
float who[10][20] = {{-0.4391785, 0.45936167, 3.009325, -0.9940405, -0.94923043, 1.531904, 4.1249785, 1.7364545, 3.426625, -0.18424246, 0.4717404, 2.1033034, -0.2697841, 2.6408699, -0.46264768, 0.025534296, -0.9158153, -0.6739721, 3.0778866, 1.6586876},
{2.1256936, 0.048414122, 1.0153224, 3.4136572, -0.2511183, 1.4299101, 2.8762167, 1.1248986, -0.11606479, 3.0881038, 0.052111022, 2.1941385, -0.23256095, 2.2201092, 3.4117224, 3.491359, 1.3918484, 0.43595034, 0.57193816, -0.17133746},
{1.1668886, 3.865467, -0.80501586, -0.121559255, -1.1265839, 1.9611652, 4.4882703, -0.62969303, 0.579606, -0.9351614, 0.72108424, 3.6922376, 0.892528, 0.4956507, 0.10175876, 2.211653, 0.7072504, -0.15880612, -0.8451216, 3.3263876},
{0.5671747, 0.18518089, -0.48920166, 1.0538653, 3.1359792, 2.555256, 4.684817, 3.1064205, 0.21195829, -0.4834232, 2.170211, -0.17987826, 0.16602038, -0.31725043, -0.24240737, 3.5321064, 0.55264086, -0.5718727, 3.2886224, -0.090337865},
{0.14142717, 2.3623872, 2.9886448, 0.6653042, 3.047261, 1.0545291, -0.8086263, 3.9324226, 0.9444289, 2.4637024, 0.2810431, 0.6929236, 1.3579776, -0.4159053, 0.38797346, 0.16914849, 2.5964139, 2.6959612, 3.4867737, -0.7064337},
{2.7108688, 0.25739613, -0.3068497, 1.7099086, -0.43095756, 3.103455, -0.017121702, 2.7222502, 2.2039282, 2.1615596, 0.05489299, -1.2183563, 2.6329393, 1.9977432, 2.0274868, 0.52042073, -1.3191999, 2.4624686, 3.1253536, 3.459109},
{-0.04492686, 1.1284969, 0.77378005, -0.41819206, 3.5430558, 1.6225992, 1.4619355, -0.14924008, 1.6083195, -0.76981723, 1.7788991, 1.2977281, -0.78710324, 2.644774, 2.7490668, -0.82152945, 0.578732, 3.278684, 0.3166879, 5.1451254},
{2.5369549, -0.66505665, 0.20186862, 2.6726503, 0.725227, -0.3420248, 0.1468595, 0.93273944, 1.4360497, 0.58014476, 3.4209948, 0.25468013, 3.7943187, 0.060351912, 0.696795, 0.851926, 2.9738708, 0.89314353, -0.47824088, 1.0113764},
{-0.041543253, 3.6848586, 3.2534397, -0.674382, 4.09213, 2.284207, 0.92676896, -1.2109576, 1.7128725, -0.39194766, -0.17690873, 3.4443536, 0.09490261, 0.62224287, -0.8757461, -1.2177278, 0.25689146, 0.03383527, 4.510749, 2.2395403},
{-1.2705529, 2.346738, 0.17966743, 0.7468895, 1.8190755, 3.4053454, -0.040168725, 0.027062561, 2.586291, -0.38730597, -0.19242558, -0.11667485, 3.5816004, -1.3588527, -0.54770744, 2.051337, 0.75088567, 2.4228947, 2.309, 0.7056862},};
float bih[20][1] = {{3.0684712},
{-5.4074607},
{-2.0961134},
{5.402638},
{-3.9972277},
{-2.3793092},
{0.79371244},
{-0.56251353},
{-3.446082},
{3.914923},
{-0.787332},
{-1.0958598},
{-0.5936966},
{0.263845},
{4.3508554},
{4.3272176},
{3.4176707},
{-2.0772617},
{-5.3518133},
{-3.6845343},};
float bho[10][1] = {{-10.985425},
{-14.943932},
{-12.863759},
{-12.288082},
{-14.769943},
{-14.0065365},
{-13.475397},
{-11.442304},
{-13.062471},
{-9.910325},};
u8 images[500][8];
u8 labels[500];
#endif //CNN_C90_MAIN_H
//main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "main.h"
float my_exp(float x) {
x = 1.0f + x / 1024;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
return x;
}
float h_pre[20][1], h[20][1], o_pre[10][1], o[10][1];
void reset() {
memset(h_pre, 0, 20 * 1 * sizeof(float));
memset(h, 0, 20 * 1 * sizeof(float));
memset(o_pre, 0, 10 * 1 * sizeof(float));
memset(o, 0, 10 * 1 * sizeof(float));
}
void get_h_pre(const u8 *img) {
int i, j;
for (i = 0; i < 20; i++) {
for (j = 0; j < 64; j++) {
if ((img[j / 8] >> (7 - j % 8)) & 0x01) {
h_pre[i][0] += wih[i][j];
}
}
h_pre[i][0] += bih[i][0];
}
}
void get_h() {
int i = 0;
for (i = 0; i < 20; i++) {
h[i][0] = 1.0f / (1 + my_exp(-h_pre[i][0]));
}
}
void get_o_pre() {
int i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
o_pre[i][0] += who[i][j] * h[j][0];
}
o_pre[i][0] += bho[i][0];
}
}
void get_o() {
int i = 0;
for (i = 0; i < 10; i++) {
o[i][0] = 1.0f / (1 + my_exp(-o_pre[i][0]));
}
}
u8 get_res() {
u8 res = 0, i;
float cor = 0;
for (i = 0; i < 10; i++) {
if (cor < o[i][0]) {
cor = o[i][0];
res = i;
}
}
return res;
}
void get_data() {
int i, j;
char label_str[3];
char image_str[66];
FILE *fp = fopen("D:\\Hardware\\cnn_c90\\trans_nums.txt", "r");
if (fp == NULL) {
printf("\033[31mERROR: %d %s\n\033[0m", errno, strerror(errno));
exit(-1);
}
for (i = 0; i < 500; i++) {
fgets(label_str, 3, fp);
labels[i] = label_str[0] - '0';
fgets(image_str, 66, fp);
for (j = 0; j < 64; j++) {
if (image_str[j] == '1') {
images[i][j / 8] |= 0x80 >> (j % 8);
}
}
}
printf("数据读取完成\n");
}
int main() {
int i = 0;
//记录正确数量
int cor = 0;
//读取数据
get_data();
//测试
for (i = 0; i < 500; i++) {
reset();
get_h_pre(images[i]);
get_h();
get_o_pre();
get_o();
if (labels[i] == get_res()) {
cor++;
}
}
printf("acc: %f", cor / 500.0);
return 0;
}
跑完一看,很好啊,acc还是90%多,此时的还不知道后面会发生什么
5.5 51上的识别代码
//cnn.h
#ifndef _CNN_H_
#define _CNN_H_
#include "lcd1602.h"
#include "public.h"
void get_res();
#endif
//cnn.c
//模型贴过来
float xdata h_pre[20][1], xdata h[20][1], xdata o_pre[10][1], xdata o[10][1];
void reset() {
u8 i;
for (i = 0; i < 20; i++) {
h_pre[i][0] = 0;
h[i][0] = 0;
}
for (i = 0; i < 10; i++) {
o_pre[i][0] = 0;
o[i][0] = 0;
}
}
void get_h_pre(const u8 *img) {
u8 i, j;
for (i = 0; i < 20; i++) {
for (j = 0; j < 64; j++) {
if ((img[j / 8] >> (7 - j % 8)) & 0x01) {
h_pre[i][0] += wih[i][j];
}
}
h_pre[i][0] += bih[i][0];
}
}
void get_h() {
u8 i = 0;
for (i = 0; i < 20; i++) {
h[i][0] = 1.0 / (1 + exp(-h_pre[i][0]));
}
}
void get_o_pre() {
u8 i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < 20; j++) {
o_pre[i][0] += who[i][j] * h[j][0];
}
o_pre[i][0] += bho[i][0];
}
}
void get_o() {
u8 i = 0;
for (i = 0; i < 10; i++) {
o[i][0] = 1.0 / (1.0 + exp(-o_pre[i][0]));
}
}
// 识别
void get_res(const u8 *img) {
u8 res = 0, i;
float cor = 0;
char xdata pre[10], pro[10];
reset();
get_h_pre(img);
get_h();
get_o_pre();
get_o();
for (i = 0; i < 10; i++) {
if (cor < o[i][0]) {
cor = o[i][0];
res = i;
}
}
sprintf(pre, "Pre: %u", res);
LCD_ShowString(1, 1, pre);
sprintf(pro, "Pro: %.2f%%", cor * 100);
LCD_ShowString(2, 1, pro);
}
5.6 编译运行
编译没问题,下载运行一看,咦?不对,状态和预想的不一样
找了半天程序的问题,最后发现code超了,最多8000
放在xdata里面,code也涨,甚至更多?
然后删改代码,去掉串口,<stdio.h>也不需要了
去掉<math.h>的exp,用自己的
发现调用系统库真耗费空间,虽然去掉后还是超出
修修改改改了一天,还是9000+
最后没办法,打算删去隐藏层,重新跑
5.7 再次训练
各种训练,顶天也就76%的正确率了
import numpy as np
from tqdm import trange
class Dataloader:
"""数据读取"""
def get_data(self, path, cnt):
"""对原始数据进行处理..."""
images, labels = [], [] # 获得原始数据
# images = np.reshape(images, (cnt, 28 * 28)) # 28*28的矩阵拉伸为1*784的矩阵
with open(path, 'r') as file:
for _ in range(cnt):
labels.append(int(file.readline()[0])) # 读label
img = []
for c in file.readline():
if c != '\n':
img.append(int(c))
images.append(img)
images = np.array(images)
labels = np.eye(10)[labels] # 单独的标签扩展为[0..9]的矩阵
print("\033[31m对原始数据进行处理......Done\033[0m")
return images, labels
def save(wio, bio):
with open('model88.txt', 'w') as file:
file.write('float w_i_o[10][64] = {')
for i in wio:
file.write('{')
cnt = 0
for j in i:
file.write(str(j))
cnt += 1
if cnt != 64:
file.write(', ')
file.write('}, ')
file.write('};\n')
file.write('float b_i_o[10][1] = {')
for i in bio:
file.write('{')
for j in i:
file.write(str(j))
file.write('}, ')
file.write('};\n')
wio, bio, a = None, None, 0
if __name__ == "__main__":
# 通过dataloader读取数据
dataloader = Dataloader()
images, labels = dataloader.get_data("trans_nums.txt", 500)
# 创建模型
# 本代码重在快速实现神经网络,因此对模型不做封装
w_i_o = np.random.uniform(-0.5, 0.5, (10, 64))
w_i_o = w_i_o.astype('float32')
b_i_o = np.zeros((10, 1), dtype=np.float32)
# 训练模型
# - 设置超参数
learn_rate = 0.01
nr_correct = 0
epochs = trange(20000)
for epoch in epochs:
for img, l in zip(images, labels):
img.shape += (1,)
l.shape += (1,) # 转纵向
# 前向传播
# - 输入层->o
o_pre = b_i_o + w_i_o @ img
o = 1 / (1 + np.exp(-o_pre))
# - 损失函数计算
e = 1 / len(o) * np.sum((o - l) ** 2, axis=0)
nr_correct += int(np.argmax(o) == np.argmax(l))
# 反向传播
# - 输出层->
delta_o = 0.2 * (o - l)
delta_z = (o * (1 - o))
delta_w_i = np.transpose(img)
w_i_o += -learn_rate * delta_o @ delta_w_i * delta_z
b_i_o += -learn_rate * delta_o
acc = round((nr_correct / images.shape[0]) * 100, 2)
epochs.set_postfix(acc=f"{acc}%", max=f"{a}%")
nr_correct = 0
if a < acc:
a = acc
wio = w_i_o
bio = b_i_o
if a >= 70:
save(wio, bio)
# 展示效果
while True:
# save(w_i_h, w_h_o, b_i_h, b_h_o)
index = int(input("输入编号进行预测"))
img = images[index]
label = labels[index]
img.shape += (1,)
# 前向传播
o_pre = b_i_o + w_i_o @ img.reshape(64, 1)
o = 1 / (1 + np.exp(-o_pre))
print(f"label: {label.argmax()}, predicted: {o.argmax()}")
5.8 再次验证
76%的正确率,只能这样咯
//main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "main.h"
float my_exp2(float x) {
float t = x * 1.442695041f;
int m = 0;
float n = 0;
float tmp_n, j, result;
int i;
m = (round)((int) (t * 2.0) / 2);
n = t - m;
m = (m + 127) << 23;
n = n * 0.693147181f;
tmp_n = n;
j = 1;
result = 1 + n;
for (i = 2; i < 7; i++) {
j = j * i;
tmp_n = tmp_n * n;
result += tmp_n / j;
}
return *(float *) &m * result;
}
float my_exp(float x) {
x = 1.0f + x / 1024;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
x *= x;
return x;
}
void get_data() {
int i, j;
char label_str[3];
char image_str[66];
FILE *fp = fopen("D:\\Hardware\\programs\\cnn_c90\\trans_nums.txt", "r");
if (fp == NULL) {
printf("\033[31mERROR: %d %s\n\033[0m", errno, strerror(errno));
exit(-1);
}
for (i = 0; i < 500; i++) {
fgets(label_str, 3, fp);
labels[i] = label_str[0] - '0';
fgets(image_str, 66, fp);
for (j = 0; j < 64; j++) {
if (image_str[j] == '1') {
images[i][j / 8] |= 0x80 >> (j % 8);
}
}
}
printf("数据读取完成\n");
}
float no_pre[10][1], no[10][1];
void reset() {
int i;
for (i = 0; i < 10; i++) {
no_pre[i][0] = 0;
no[i][0] = 0;
}
}
void get_no_pre(const u8 *img) {
int i, j;
for (i = 0; i < 10; i++) {
for (j = 0; j < 64; j++) {
if ((img[j / 8] >> (7 - j % 8)) & 0x01) {
no_pre[i][0] += w_i_o[i][j];
}
}
no_pre[i][0] += b_i_o[i][0];
}
}
void get_no() {
int i = 0;
for (i = 0; i < 10; i++) {
no[i][0] = 1.0f / (1 + my_exp(-no_pre[i][0]));
}
}
u8 get_nres() {
u8 res = 0, i;
float cor = 0;
for (i = 0; i < 10; i++) {
if (cor < no[i][0]) {
cor = no[i][0];
res = i;
}
}
return res;
}
int main() {
int i = 0;
//记录正确数量
int cor = 0;
//读取数据
get_data();
//测试
for (i = 0; i < 500; i++) {
reset();
get_no_pre(images[i]);
get_no();
if (labels[i] == get_nres()) {
cor++;
}
}
printf("acc: %f", cor / 500.0);
return 0;
}
5.9 可以放下的识别代码
//cnn.c
#include "cnn.h"
// 模型参数
float code w_i_o[10][64] = {
{0.5664128, -0.21377318, -0.9949012, -1.5381784, -0.6744786, 0.031389937, 0.17588668, -0.47555494, -1.0540706, -0.83008116, -1.1026632, 0.2791996, 1.4949312, 0.8007128, 0.17226571, -0.6794696, 0.33934882, -0.41205436, -0.85786813, -0.885778, -0.22843638, 0.22343862, 0.50407225, -0.71781003, 1.0171996, -0.09237784, -1.0800514, -2.699908, -3.1323385, -1.5755824, 2.300938, 1.5855157, -1.2364568, -0.8945054, -0.6154064, -0.117638245, -0.21715613, 0.038885966, -0.59815556, 0.24405, -2.00755, -0.75985026, 0.43208393, 0.17077754, -0.37598416, 0.0685567, -1.2036531, -0.60508895, 0.4161404, 0.8650985, -0.6206283, -1.0404283, -1.273805, -1.3590841, -0.7722982, 0.76257795, 0.13840488, -0.32380986, -0.25333732, -0.014944064, -0.56606346, -0.65280145, -0.36057612, 0.019987313},
{-0.1287646, 1.7691618, -1.1548091, -0.66205424, -0.46131417, 0.13660304, -0.6822341, -0.1587507, -0.15591387, -1.0338596, 0.48730052, -1.1988409, -0.16180669, -0.31696317, 0.18199006, -0.12097158, -2.1686668, -0.437815, -1.114581, 0.86003315, -0.87250894, 0.3907029, -0.33462653, -0.6833954, -0.10904898, -0.2668449, 0.6546389, -0.9240991, -0.012335212, -0.84346825, -0.25090387, 0.5224132, 1.4049937, -0.7072402, -0.9833269, -0.43207213, -0.6533614, 0.09074907, 0.096326075, 0.05208772, -2.737896, -1.0028173, -0.6560741, -1.1592655, -1.2793996, -1.1738114, -0.79059035, -0.110063724, -0.4057571, -0.42603657, 0.48673856, -0.25040984, -0.54386926, -0.05663645, 0.0633362, -0.00384197, -0.27499703, 1.158131, -0.32893884, -0.6537069, -0.37018344, -0.5214341, -0.20541938, -0.04008949},
{0.45087922, -0.44029087, 0.02818912, -0.9861958, -0.14602016, 0.6199761, 0.26170665, 0.4773626, 0.19992071, 0.39806223, 0.19171926, -1.898419, -0.8119795, 2.0020351, 0.26241535, 0.4530684, 0.44913626, -0.025234446, -0.7138027, -2.7908347, 0.4583805, 1.7096424, 0.7780832, 0.3040807, 1.2149675, 0.5965316, -1.2294679, -1.0392593, 1.815863, 0.345495, -0.31170833, 0.7029222, 1.2379982, -0.74947476, -0.9227225, -0.28138041, -0.36642802, -0.7547913, 0.59573627, 0.20162958, 0.6739312, 0.21116792, 0.695258, 0.45859963, -1.9335011, -1.6994677, 0.32537702, 0.38245207, -0.6413663, 0.31038445, 0.17677906, -1.1035521, -1.5025705, -0.77915066, 0.4588546, 1.1508449, 0.23090373, -0.16805865, -0.06785368, 0.39476854, -0.5246919, -0.12579326, -0.1466648, 0.31628335},
{-0.27442276, 0.5376627, -0.029169874, -1.9675182, 0.2569605, -2.526442, 0.4888193, 0.3914235, -0.36344862, -0.076950766, -0.74662167, -1.6026591, 0.4519849, -2.101405, 0.67674446, 0.049886927, -1.1595732, -0.5162468, 0.16083445, -2.5138109, 0.07903132, -1.7985072, 0.8392261, 0.74122584, -1.826293, -0.2513942, -0.8832548, -1.7359478, 1.0858169, -1.7366488, 0.89563257, 0.6370047, -0.73518175, -0.60361, -0.7951568, -0.68310374, 0.5708151, -0.14829913, -1.1781907, 0.060677845, -0.6314977, -0.4661686, -0.62409884, 1.0835748, -0.28249732, 0.13847184, -1.8021599, -0.4948054, -1.1481088, 0.29535308, -0.6657051, 1.5209445, -0.8130289, -0.3716246, 0.08509089, -0.98847365, 0.042415492, 0.36641946, 0.37069294, -0.8917385, -0.062407386, -0.43371075, -1.2039088, -0.9063634},
{1.0098052, 0.9638526, 1.0310292, 1.1218865, 0.13098039, -0.44242826, 0.14832462, 0.093124725, 0.32978576, 1.69877, 1.8342276, 1.6463071, 1.6425794, -0.07154793, -1.5220383, -0.81401753, -1.5759354, 1.7026329, 1.4346062, 2.705223, 1.0447, -0.776469, -1.8811721, -1.8876435, -0.5229143, -0.29949275, 1.6944939, 1.7749103, 1.6006886, -0.75252247, -0.062181108, -0.13629967, -0.37296852, -1.178062, 0.6418236, 2.5275185, 2.1645277, 1.4632483, -1.1301785, -1.8371595, -1.809058, -0.48071632, 0.6477235, 2.1100097, 1.7931606, 1.3773451, -0.5475025, -0.5024947, 1.337733, -0.36974832, 0.66300565, 1.5456525, 2.2928379, 1.9860828, -1.4773195, 0.0668749, 0.09991437, -0.41769972, -1.1866688, 2.8109226, -0.14803259, 1.9053943, -0.9735171, -0.3339023},
{-0.24487436, -0.42400324, -0.30249482, -0.12105501, -0.29765686, -0.38017425, 0.13065003, 0.21761602, -0.35170588, -0.78531325, 0.04976741, -0.42394328, -0.73761, -0.9301451, -0.15310352, -0.055574946, -0.6484745, -0.14658038, 0.5253345, 0.91049427, -3.101725, -0.23344709, 0.16033864, 0.14616747, -0.63162464, 0.11460595, 1.7047725, -0.7411919, -3.6615617, -0.19269247, -0.26489735, -0.098733775, 0.42233798, 1.9236151, -1.0911032, -0.05932005, -3.2683613, 0.47177082, 1.3705348, -1.6343354, 0.63776124, -2.0953922, -0.6536648, -0.54609483, -0.3478762, 0.9674527, 0.21019526, -2.1315691, -0.5902906, -0.103782475, -1.0732667, -0.32061344, -0.10739035, 0.5160776, 1.0286543, -1.2274673, 0.2536698, -1.5707686, -0.46092844, -1.0782149, 0.041600972, 0.13881266, 0.19510913, -0.47600266},
{0.16206253, -0.41137853, -0.30896583, 0.15597634, -0.2671143, -0.490882, -0.19013932, -0.17649114, -0.14425853, -0.74385893, -0.27669305, 0.5229035, 0.3223738, 0.46223292, 0.76378363, 0.35678196, -0.1909429, -0.59805137, -0.034946203, 0.2438756, 1.2589049, 1.0627805, -0.008614447, -0.47932085, -0.15413885, 0.5135362, 0.055834696, -0.50514984, 0.40221038, 1.3746467, -0.3913967, -0.6308095, 0.6262, 1.654139, -1.9290391, -0.60847926, -0.17292087, 0.22339667, 0.860688, 0.5917775, 2.4611459, -0.07645186, -4.089945, -0.1365905, 0.35009843, 0.83978295, 0.23540232, 0.8632825, 0.16462836, -0.25641006, -3.3173764, 0.019710872, 0.477034, 0.22136706, 0.54076093, 0.2991061, -0.79096633, 0.06622481, -1.6888721, -1.727642, -0.40511695, -0.1578727, 0.4934376, 0.8478045},
{0.8886541, -0.850461, -0.4818631, -0.6828393, -0.97116846, -0.7863555, -0.046479154, -0.49556616, 1.0759739, 0.7518069, -2.3420458, -0.75652367, -1.1588994, -0.9947721, -0.7090172, -0.45524618, 1.5364089, 0.92022544, -0.22594912, -1.223866, -1.4031786, -1.4002037, -1.4645462, -0.92796814, 1.3273005, 1.870906, -1.0081747, -1.4168409, -2.4580073, -2.1507187, -1.7504948, -1.477973, -1.0788976, 0.65131307, 0.6671654, -1.0078651, -1.3393376, -0.81958896, -1.1687428, -0.62359655, 0.44632775, -0.6483983, -0.9376602, -1.204626, -0.34700435, -0.13605659, 0.6364287, 1.5620615, 0.19357407, 1.072611, -0.3364704, -0.5714024, -0.7175412, -0.97793233, -0.6831355, -1.0120184, 0.10754612, -0.72486687, 0.68247044, -0.55654883, -0.51798296, -1.3358388, 0.40848798, 0.05566829},
{0.009082103, -0.8962332, 0.11980997, 0.33128145, 0.79228425, 1.748759, 1.5948095, -0.2304744, 0.030942554, -1.2351195, -0.07378349, 1.380836, 1.183818, 1.141433, 1.2474294, 0.6687325, -0.47671166, 0.20786946, 0.013008165, 2.334073, 2.4743376, 0.6065397, 1.4038479, 0.35357246, -0.1728394, 0.3911426, 1.935861, 3.1084993, 2.2066686, 2.236507, 0.101251304, 1.0822725, 0.9802556, 0.92733866, 2.360789, 1.7853508, 2.5690093, 0.6132833, 0.46499756, 0.025977813, 0.56731886, 1.3453466, 1.5029863, 1.4470205, 0.42743844, 0.93358517, 0.14194085, -0.9889256, 0.47468865, 0.90948784, 1.7025644, 1.3043516, -0.379508, 0.15513512, 0.38815066, 0.042103507, 1.0232406, 0.81580967, 1.2687304, 1.618544, 0.3717951, -0.31052575, 0.66586, 0.026752843},
{1.1892788, 0.8457045, 1.8120186, -0.9023276, -1.5560519, 0.016546793, -0.24336892, 0.22750868, 0.33744442, -1.3129724, 1.0549358, -0.39500278, -0.762012, -0.40559182, -0.98795485, -0.48150063, 0.3036769, 0.11784292, 0.5135058, 1.8106189, -0.83792245, -1.5639293, -0.2018165, 0.5286669, 1.076017, 0.49631706, 0.06660596, 0.7501726, -1.1053836, -0.30826923, -0.28328136, -0.2446471, -0.60855806, -0.5883348, 2.3820124, -0.7981061, 1.6157442, -0.7148589, 0.10950754, 0.001185905, 0.3636903, 1.6486617, 0.84226847, -1.3624489, 0.5755647, 0.4186654, -0.21985774, 0.36796582, -0.5501688, 0.023035761, 0.71817553, 0.11063999, -1.3321682, 0.5219533, 0.39590842, -0.5938355, 0.66772026, 0.10669082, -0.09691508, -0.8214123, -0.014642326, -0.21960828, -0.3641557, -0.63633627},
};
float code b_i_o[10][1] = {
{1.7617584},
{1.8119161},
{-3.708471},
{1.4891008},
{-13.087248},
{-0.25907508},
{-4.3405833},
{1.7190828},
{-18.712358},
{-4.918423},
};
float xdata no_pre[10][1], no[10][1];
// void get_no_pre() {
// int i, j;
// for (i = 0; i < 10; i++) {
// for (j = 0; j < 64; j++) {
// if ((GLED_PER_COL_DATA[j / 8] >> (7 - j % 8)) & 0x01) {
// no_pre[i][0] += w_i_o[i][j];
// }
// }
// no_pre[i][0] += b_i_o[i][0];
// }
// }
// void get_no() {
// int i = 0;
// for (i = 0; i < 10; i++) {
// no[i][0] = 1.0f / (1 + my_exp(-no_pre[i][0]));
// }
// }
void get_res() {
u8 res = 0, i, j;
float cor = 0;
char str[16] = "Res: ";
for (i = 0; i < 10; i++) {
no_pre[i][0] = 0;
no[i][0] = 0;
}
// get_no_pre();
for (i = 0; i < 10; i++) {
for (j = 0; j < 64; j++) {
if ((GLED_PER_COL_DATA[j / 8] >> (7 - j % 8)) & 0x01) {
no_pre[i][0] += w_i_o[i][j];
}
}
no_pre[i][0] += b_i_o[i][0];
}
// get_no();
for (i = 0; i < 10; i++) {
no[i][0] = 1.0f / (1 + my_exp(-no_pre[i][0]));
}
for (i = 0; i < 10; i++) {
if (cor < no[i][0]) {
cor = no[i][0];
res = i;
}
}
str[5] = res + '0';
str[8] = (int)(cor * 10) % 10 + '0';
str[9] = (int)(cor * 100) % 10 + '0';
str[10] = '.';
str[11] = (int)(cor * 1000) % 10 + '0';
str[12] = (int)(cor * 10000) % 10 + '0';
str[13] = '%';
str[14] = '\0';
LCD_ShowString(1, 1, str);
}
6、跑通
//main.c
#include "ir.h"
#include "lcd1602.h"
#include "leds.h"
#include "public.h"
//
u8 GLED_PER_COL_DATA[8] = {0};
u8 point = 0;
void init() {
// leds 使用P0 P34 P35 P36
// ir使用 数据接收P32 外部中断1 P33
ir_init();
// lcd1602 使用P26 P25 P27
LCD_Init();
}
void main() {
init();
LCD_ShowString(1, 1, "START...");
while (1) {
led_display();
}
}
最后总算是跑通了,效果还算理想
可能因为数据集和准确度的原因,2、9的字形会识别成8
补:啊啊啊,突然意识到我犯蠢了;隐藏层不该删掉,应该在保持较高acc的基础上,逐步减少隐藏层大小,直到满足内存要求。。。QAQ,果然还是太小白了,还是得多学