导航:首页 > 源码编译 > 嵌入式图像算法

嵌入式图像算法

发布时间:2025-01-16 08:08:54

1. 在图像识别这一块,目前有没有可以移植到嵌入式设备的深度学习算法

深度学习在物体识别中最重要的进展体现在ImageNet ILSVRC3挑战中的图像分类任务。传统计算机视觉方法在此测试集上最低的错误率是26.172%。2012年,欣顿的研究小组利用卷积网络把错误率降到了15.315%。此网络结构被称为Alex Net,与传统的卷积网络相比,它有三点与众不同之处:首先,Alex Net采用了dropout的训练策略,在训练过程中将输入层和中间层的一些神经元随机置零。这模拟了噪音对输入数据的各种干扰使一些神经元对一些视觉模式产生漏检的情况。Dropout使训练过程收敛得更慢,但得到的网络模型更加鲁棒。其次,Alex Net采用整流线型单元作为非线性的激发函数。这不仅大大降低了计算的复杂度,而且使神经元的输出具有稀疏的特征,对各种干扰更加鲁棒。第三,Alex Net通过对训练样本镜像映射和加入随机平移扰动,产生了更多的训练样本,减少了过拟合。
在ImageNet ILSVRC 2013比赛中,排名前20的小组使用的都是深度学习技术。获胜者是纽约大学罗伯·费格斯(Rob Fergus)的研究小组,所采用的深度模型是卷积网络,并对网络结构作了进一步优化,错误率为11.197%,其模型称作Clarif。
在ILSVRC 2014比赛中,获胜者GooLeNet[18]将错误率降到了6.656%。GooLeNet突出的特点是大大增加了卷积网络的深度,超过了20层,这在此之前是不可想象的。很深的网络结构给预测误差的反向传播带了困难,这是因为预测误差是从最顶层传到底层的,传到底层的误差很小,难以驱动底层参数的更新。GooLeNet采取的策略是将监督信号直接加到多个中间层,这意味着中间层和底层的特征表示也要能够对训练数据进行准确分类。如何有效地训练很深的网络模型仍是未来研究的一个重要课题。
虽然深度学习在ImageNet上取得了巨大成功,但是很多应用的训练集是较小的,在这种情况下,如何应用深度学习呢?有三种方法可供参考:(1)可以将ImageNet上训练得到的模型作为起点,利用目标训练集和反向传播对其进行继续训练,将模型适应到特定的应用[10]。此时ImageNet起到预训练的作用。(2)如果目标训练集不够大 ,可以将底层的网络参数固定,沿用ImageNet上的训练集结果,只对上层进行更新。这是因为底层的网络参数是最难更新的,而从ImageNet学习得到的底层滤波器往往描述了各种不同的局部边缘和纹理信息,而这些滤波器对一般的图像有较好的普适性。(3)直接采用ImageNet上训练得到的模型,把最高的隐含层的输出作为特征表达,代替常用的手工设计的特征。

2. 嵌入式工程师面试中常出现的算法

嵌入式工程师面试中常出现的算法

嵌入式系统是以应用为中心,以计算机技术为基础,并且软硬件可裁剪,适用于应用系统对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统。下面我为大家整理了关于嵌入式工程师面试中经常出现的算法文章,希望对你有所帮助。

二分查找的代码.

int bfind(int* a,int len,int val)

{

int m = len/2;

int l = 0;

int r = len;

while(l!=m && r!= m)

{

if(a[m] > val)

{

r = m;

m = (m+l)/2;

}

else if(a[m] < val)

{

l = m;

m = (m+r)/2;

}

else

return m;

}

return -1; //没有找到

}

写出在母串中查找子串出现次数的代码.

int count1(char* str,char* s)

{

char* s1;

char* s2;

int count = 0;

while(*str!='')

{

s1 = str;

s2 = s;

while(*s2 == *s1&&(*s2!='')&&(*s1!='0'))

{

s2++;

s1++;

}

if(*s2 == '')

count++;

str++;

}

return count;

}

查找第一个匹配子串位置,如果返回的是s1长度len1表示没有找到

size_t find(char* s1,char* s2)

{

size_t i=0;

size_t len1 = strlen(s1)

size_t len2 = strlen(s2);

if(len1-len2<0) return len1;

for(;i {

size_t m = i;

for(size_t j=0;j {

if(s1[m]!=s2[j])

break;

m++;

}

if(j==len)

break;

}

return i }

写出快速排序或者某种排序算法代码

快速排序:

int partition(int* a,int l,int r)

{

int i=l-1,j=r,v=a[r];

while(1)

{

while(a[++i] while(a[--j]>v) if(j<=i) break;

if(i>=j)

break;

swap(a[i],a[j]);

}

swap(a[i],a[r]);

return i;

}

void qsort(int* a,int l,int r)

{

if(l>=r) return;

int i = partition(a,l,r);

qsort(a,l,i-1);

qsort(a,i+1,r);

}

冒泡排序:

void buble(int *a,int n)

{

for(int i=0;i {

for(int j=1;j {

if(a[j] {

int temp=a[j];

a[j] = a[j-1];

a[j-1] = temp;

}

}

}

}

插入排序:

void insertsort(int* a,int n)

{

int key;

for(int j=1;j {

key = a[j];

for(int i=j-1;i>=0&&a[i]>key;i--)

{

a[i+1] = a[i];

}

a[i+1] = key;

}

}

出现次数相当频繁

实现strcmp函数

int strcmp11(char* l,char* r)

{

assert(l!=0&&r!=0);

while(*l == *r &&*l != '') l++,r++;

if(*l > *r)

return 1;

else if(*l == *r)

return 0;

return -1;

}

实现字符串翻转

void reserve(char* str)

{

assert(str != NULL);

char * p1 = str;

char * p2 = str-1;

while(*++p2); //一般要求不能使用strlen

p2 -= 1;

while(p1 {

char c = *p1;

*p1++ = *p2;

*p2-- = c;

}

}

将一个单链表逆序

struct list_node

{

list_node(int a,list_node* b):data(a),next(b) //这个为了测试方便

{}

int data;

list_node* next;

};

void reserve(list_node* phead)

{

list_node* p = phead->next;

if(p == NULL || p->next == NULL) return; //只有头节点或一个节点

list_node* p1=p->next;

p->next=NULL;

while(p1!=NULL)

{

p = p1->next;

p1->next = phead->next;

phead->next = p1;

p1 = p;

}

}

测试程序:

list lt;

lt.phead = new list_node(0,0);

lt.phead->next = new list_node(1,0);

lt.phead->next->next = new list_node(2,0);

lt.phead->next->next->next = new list_node(3,0);

lt.reserve();

list_node * p = lt.phead;

while(p)

{

coutnext;

}

循环链表的节点对换和删除。

//双向循环

list_node* earse(list_node* node)

{

// if(node == rear) return node->next; //对于头节点可判断也可不判断。最好加上

list_node* next = node->next;

next->prev = node->prev;

node->prev->next = next;

delete node;

retrun next;

}

//单项循环

list_node* earse(list_node* node)

{

// if(node == rear) return node->next; //对于头节点可判断也可不判断。最好加上

list_node* p = rear;

while(p->next != node) p=p->next;

p->next = node->next;

delete node;

retrun p->next;

}

将一个数字字符串转换为数字."1234" -->1234

int atoii(char* s)

{

assert(s!=NULL);

int num = 0;

int temp;

while(*s>'0' && *s<'9')

{

num *= 10;

num += *s-'0';

s++;

}

return num;

}

出现次数相当频繁

.实现任意长度的整数相加或者相乘功能。

void bigadd(char* num,char* str,int len)

{

for(int i=len;i>0;i--)

{

num[i] += str[i];

int j = i;

while(num[j]>=10)

{

num[j--] -= 10;

num[j] += 1;

}

}

}

.写函数完成内存的拷贝

void* memcpy( void *dst, const void *src, unsigned int len )

{

register char *d;

register char *s;

if (len == 0)

return dst;

if ( dst > src ) //考虑覆盖情况

{

d = (char *)dst + len - 1;

s = (char *)src + len - 1;

while ( len >= 4 ) //循环展开,提高执行效率

{

*d-- = *s--;

*d-- = *s--;

*d-- = *s--;

*d-- = *s--;

len -= 4;

}

while ( len-- )

{

*d-- = *s--;

}

}

else if ( dst < src )

{

d = (char *)dst;

s = (char *)src;

while ( len >= 4 )

{

*d++ = *s++;

*d++ = *s++;

*d++ = *s++;

*d++ = *s++;

len -= 4;

}

while ( len-- )

{

*d++ = *s++;

}

}

return dst;

}

出现次数相当频繁

编写类String的构造函数、析构函数和赋值函数,已知类String的原型为:

class String

{

public:

String(const char *str = NULL); // 普通构造函数

String(const String &other); // 拷贝构造函数

~ String(void); // 析构函数

String & operate =(const String &other); // 赋值函数

private:

char *m_data; // 用于保存字符串

};

解答:

//普通构造函数

String::String(const char *str)

{

if(str==NULL)

{

m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志''的`空

//加分点:对m_data加NULL 判断

*m_data = '';

}

else

{

int length = strlen(str);

m_data = new char[length+1]; // 若能加 NULL 判断则更好

strcpy(m_data, str);

}

}

// String的析构函数

String::~String(void)

{

delete [] m_data; // 或delete m_data;

}

//拷贝构造函数

String::String(const String &other) // 得分点:输入参数为const型

{

int length = strlen(other.m_data);

m_data = new char[length+1]; //加分点:对m_data加NULL 判断

strcpy(m_data, other.m_data);

}

//赋值函数

String & String::operate =(const String &other) // 得分点:输入参数为const型

{

if(this == &other) //得分点:检查自赋值

return *this;

delete [] m_data; //得分点:释放原有的内存资源

int length = strlen( other.m_data );

m_data = new char[length+1]; //加分点:对m_data加NULL 判断

strcpy( m_data, other.m_data );

return *this; //得分点:返回本对象的引用

}

剖析:

能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!

在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《EffectiveC++》中特别强调的条款。

实现strcpy

char * strcpy( char *strDest, const char *strSrc )

{

assert( (strDest != NULL) && (strSrc != NULL) );

char *address = strDest;

while( (*strDest++ = * strSrc++) != ‘’ );

return address;

}

编写一个函数,作用是把一个char组成的字符串循环右移n个。比如原来是“abcdefghi”如果n=2,移位后应该是“hiabcdefgh”

函数头是这样的:

//pStr是指向以''结尾的字符串的指针

//steps是要求移动的n

void LoopMove ( char * pStr, int steps )

{

//请填充...

}

解答:

正确解答1:

void LoopMove ( char *pStr, int steps )

{

int n = strlen( pStr ) - steps;

char tmp[MAX_LEN];

strcpy ( tmp, pStr + n );

strcpy ( tmp + steps, pStr);

*( tmp + strlen ( pStr ) ) = '';

strcpy( pStr, tmp );

}

正确解答2:

void LoopMove ( char *pStr, int steps )

{

int n = strlen( pStr ) - steps;

char tmp[MAX_LEN];

memcpy( tmp, pStr + n, steps );

memcpy(pStr + steps, pStr, n );

memcpy(pStr, tmp, steps );

}

;

3. 在图像识别这一块,目前有没有可以移植到嵌入式设备的深度学习算法

先说图像识别,一般推荐opencv。因为是Intel主导的一个开源库用C和C++混合编写。如果嵌入式设备是搭配着linux平台应该是可以做的。然后深度学习这块儿的话一般可以入手的就是反向传播,和神经网络搭配。在细一点就是做同一类型的图片的机器学习

阅读全文

与嵌入式图像算法相关的资料

热点内容
36位单片机 浏览:428
英雄联盟山东服务器地址 浏览:212
sd服务器什么意思 浏览:617
thinkphp去indexphp 浏览:62
电脑显示连接未加密 浏览:193
zao服务器怎么修改 浏览:244
php使用jsapi调起支付 浏览:891
vivo云服务器网 浏览:722
cmd远程连接命令行 浏览:961
黑马python讲义 浏览:133
php高并发测试 浏览:88
第二届程序员节开幕式 浏览:84
运维程序员脚本 浏览:371
塑源码燕窝的安全性 浏览:176
作业调度采用高响应比优先调度算法 浏览:160
和平精英如何切换苹果到安卓 浏览:532
数据库调用表单的命令 浏览:923
程序员技能大赛 浏览:11
什么app买品牌衣服 浏览:15
手机看世界名着哪个app好 浏览:495