搞了一年人脸识别,寻思着记录点什么,于是想写这么个系列,介绍人脸识别的四大块:Face detection, alignment, verification and identification(recognization),本别代表从一张图中识别出人脸位置,把人脸上的特征点定位,人脸校验和人脸识别。(后两者的区别在于,人脸校验是要给你两张脸问你是不是同一个人,人脸识别是给你一张脸和一个库问你这张脸是库里的谁。
今天先介绍第一部分和第二部分。 主要说三篇顶会文章。
==================================
关键词:人脸检测 人脸校准 特征点定位 决策树 随机森林 CART RandForest RandFern Boosting Realboost
==================================
转载注明来自http://www.cnblogs.com/sciencefans/
人脸检测(detection)在opencv中早就有直接能拿来用的haar分类器,基于Viola-Jones算法。但是毕竟是老掉牙的技术,Precision/Recall曲线渣到不行,在实际工程中根本没法给boss看,作为MSRA脑残粉,这里介绍一种MSRA在14年的最新技术:Joint Cascade Face Detection and Alignment(ECCV14)。 这篇文章直接在30ms的时间里把detection和alignment都给做了,PR曲线彪到很高,时效性高,内存占用却非常低,在一些库上虐了Face++和Google Picasa,正好契合这篇想讲的东西。可以作为本节的主线。
人脸校准(alignment)是给你一张脸,你给我找出我需要的特征点的位置,比如鼻子左侧,鼻孔下侧,瞳孔位置,上嘴唇下侧等等点的位置。如果觉得还是不明白,看下图:
图中红色框框就是在做detection,白色点点就是在做alignment。
如果知道了点的位置做一下位置驱动的变形,脸就成正的了,如何驱动变形不是本节的重点,在此省略。
首先介绍一下下面正文要写的东西,由于干货非常多所以可能会看着看着就乱了,所以给出框架图:
=================================
废话说了这么多,正文开始~
detection
作者建立了一个叫post classifier的分类器,方法如下:
1.样本准备:首先作者调用opencv的Viola-Jones分类器,将recal阀值设到99%,这样能够尽可能地检测出所有的脸,但是同时也会有非常多的不是脸的东东被检测出来。于是,检测出来的框框们被分成了两类:是脸和不是脸。这些图片被resize到96*96。
2.特征提取:接下来是特征提取,怎么提取呢?作者采用了三种方法:
第一种:把window划分成6*6个小windows,分别提取SIFT特征,然后连接着36个sift特征向量成为图像的特征。
第二种:先求出一个固定的脸的平均shape(27个特征点的位置,比如眼睛左边,嘴唇右边等等),然后以这27个特征点为中心提取sift特征,然后连接后作为特征。
第三种:用他们组去年的另一个成果Face Alignment at 3000 FPS via Regressing Local Binary Features (CVPR14) ,也就是图中的3000FPS方法,回归出每张脸的shape,然后再以每张脸自己的27个shape points为中心做sift,然后连接得到特征。
3.分类:将上述的三种特征分别扔到线性SVM中做分类,训练出一个能分辨一张图是不是脸的SVM模型。
紧接着作者将以上三种方法做出的分类器和初始分类器进行比对,画了一个样本分布的图:
这个图从左到右依次是原始级联分类器得到的样本分类分布和第一种到第三种方法提取的特征得到的样本分类分布。可见做一下shape alignment可以得到一个更好的分类效果。但是问题来了:如果把所有的windows都做一下alignment,即使是3000 faces per second的速度一张图可能也要处理上1秒,这无法满足一般一秒30帧的实时需求。作者也说,用opencv分类器,参数设成99%的recall率将会带来很严重的效率灾难——一张图能找出来3000个框,处理一张图都要好几秒。
这么渣的效率可咋办呢?以上内容已经证明了alignment确实对detection的preciseness有帮助,这就够啦,对下面的工作也是个启发——能不能在做detection的同时把alignment做了呢?alignment的中间结果是否能给detection带来一些帮助呢?后面慢慢讲。先说两个通用的面部检测和矫正的模型:
1.级联检测分类器(bagging):不失一般性,一个简单的级联分类器是这样的:
图中的Ci代表的是第i个弱分类器。x代表的是特征向量,f代表分类得分。每个Ci会根据自己的分类方法对x输出一个分类结果,比如是一张脸或者不是一张脸,而fn(n=1~N)都会对应一个thresholdΘi,让任意一个fn小于对应的Θi的时候,样本就会被拒绝。通常不是一张脸的图片在经过前几个弱分类器的判断后就会被拒绝,根本不用做后面的判断,所以速度很快。
2.级联回归校准(我这翻译…+_+):这里介绍的是另一个人在10年发的文章:Cascaded Pose Regression (CVPR10) ,给图像一个初始shape(通常采用平均shape),然后通过一次一次的回归把shape回归到正确的地方。算法结构很简单,但是效果确实非常好:
回归过程如下:首先提取特征,原作者采用的是Pose-Indexed point features,然后根据特征训练回归函数(可以用线性回归,CART,随机森林等等),原作者采用了一个叫Random Fern Regressor的东西,这里翻译成随机蕨好了(这名字…),回归出这一阶段的偏移量,然后shape加上这个偏移量,反复这一过程,直到迭代上限或者shape错误率不再下降。随机蕨的算法过程和随机森林类似,他是一个半朴素贝叶斯模型。首先选取M组每组K个特征建立M个蕨(弱分类器),然后假设蕨内特征是相关的,蕨间特征是独立的,这样从统计学上随机蕨是一个完整的把朴素贝叶斯分类器,让计算变得简单:
式中C代表分类,ci代表第I类,M代表蕨数量。
综上,这样回归的过程可以总结成如下形式:
S代表shape,St代表在回归第t阶段的shape,他等于上一阶段的shape加上一个偏置,这个偏置就是上述回归方法之一搞定的。比如随机森林或者随机蕨,或者线性回归。
现在再说说怎么训练得到这个回归Rt。
有两种思路:一种是像刚才随机蕨那样,每个每个蕨的叶子节点存储一个偏移量,计算训练的时候落入这个叶子节点的样本偏移之平均,然后作为最终的叶子节点偏移量。其实就是在优化一个如下目标函数:
然而MSRA组在3000fps中采用的是另一种方法,形状的偏移量ΔδS为:
目标函数是:
其实也是同样的思路,Φ代表特征提取函数,论文中称Φ的输出为局部二值特征(LBF),W为线性回归参数矩阵,其实就是把提取出来的特征映射到一个二维的偏移量上,是一个2*lenth(特征空间维数)的变换矩阵。
首先讲Φ是怎么训练的:Φ其实就是一个随机森林。输入像素差特征(pixel-difference features),输出一个offest。训练的时候随机给每个根节点像素差特征中的一部分。非叶节点的分裂依据是从输入的pixel-difference features中找出能够做到最大的方差衰减的feature。在最后的叶子节点上写上落在叶子节点上的样本偏移量,这个偏移量在之前说到的fern里有用,但是在这里没啥用,因为作者最后不是用这个做回归的而是用LBF,详细的得往下看。如果有多个样本都落在这里,则求平均。这样训练出来的东西就是下面这个公式所表达的东西:
可能有读者看到这就会不懂了,不用管这个公式,等下面的看完了就会懂了。
但是我只想要其中的Φ,于是这里给出了LBF(local binary feature)的定义,直接简单粗暴地统计所有树叶节点是否被该样本落入,如果落入了就记为1否则记为0,然后把所有的01串连起来就是LBF了。还是看图说话:
先看b,随机森林的三棵树,样本经过三棵树后分别落在了第1,2,3个叶子节点上,于是三棵树的LBF就是1000,0100,0010.连接起来就是100001000010.然后看a,把27个特征点的lbf都连接起来形成总的LBF就是Φ了。
接下来是训练w:之前已经得到了wΦ(I,S)以及Φ(I,S),现在想求w,这还不容易吗,直接算呀。不过作者又调皮了,他说他不想求w,而是想求一个总的大W=[w1,w2,w3,…,w27].怎么求呢?得做二次回归。至于为什么要这么做下面会介绍。目标函数:
后面加了个L2项,因为W是炒鸡sparse的,防止过拟合。做线性回归即可得到W。
现在解释一下为啥不直接用w1w2w3…而是要再回归出来一个W:原因有两个:
1. 再次回归W可以去除原先小wi叶子节点上的噪声,因为随机森林里的决策树都是弱分类器嘛噪声多多滴;
2.大W是全局回归(之前的一个一个小w也就是一个一个特征点单独的回归是local回归),全局回归可以有效地实施一个全局形状约束以减少局部误差以及模糊不清的局部表现。
这样一来,测试的时候每输入一张图片I,先用随机森林Φ求出它的LBF,然后在用W乘一下就得到了下一个stage的shape,然后迭代几次就得到了最终的shape。所以效率十分的快。
好了,兜了一大圈该回来了,刚才讲的是两个uniform的model来做detection和shape regression的。接下来该讲作者是怎么边detection边regression shape的了!
作者建立了一个分类回归树,就叫CRT好了。这个CRT在距离根节点比较近的几层偏重于分类,在接近叶子节点的几层偏重于回归,具体实现上,每个节点究竟用于回归还是分类呢?用一个概率p表示用于分类的概率,自然回归就是1-p了。而这个p随着深数的深度减小,作者采用了一个经验公式:
知道了CRT怎么建立,那就直接就看算法细节吧!边测试是不是脸边做特征点回归的算法如下:
这个模型的训练方法如下:
这样就算完了吗?不,既然要实现,就要细看一下以上用到的各类算法细节:
部分摘自其他博客,详见参考文献。
1.CART(Classification And Regression Tree) 思想:递归地将输入空间分割成矩形 优点:可以进行变量选择,可以克服missing data,可以处理混合预测 缺点:不稳定
分类训练过程:
就这样不断分割之后可以建立如下这样的决策树:
2.Bagging (Breiman1996): 也称bootstrap aggregation Bagging的策略: - 从样本集中用Bootstrap采样选出n个样本 - 在所有属性上,对这n个样本建立分类器(CART or SVM or ...) - 重复以上两步m次,i.e.build m个分类器(CART or SVM or ...) - 将数据放在这m个分类器上跑,最后vote看到底分到哪一类 Fit many large trees to bootstrap resampled versions of the training data, and classify by majority vote. 下图是Bagging的选择策略,每次从N个数据中采样n次得到n个数据的一个bag,总共选择B次得到B个bags,也就是B个bootstrap samples.
流程图如下:
3.随机森林:
随机森林,指的是利用多棵树对样本进行训练并预测的一种分类器。该分类器最早由Leo Breiman和Adele Cutler提出,并被注册成了商标。简单来说,随机森林就是由多棵CART(Classification And Regression Tree)构成的。对于每棵树,它们使用的训练集是从总的训练集中有放回采样出来的,这意味着,总的训练集中的有些样本可能多次出现在一棵树的训练集中,也可能从未出现在一棵树的训练集中。在训练每棵树的节点时,使用的特征是从所有特征中按照一定比例随机地无放回的抽取的,根据Leo Breiman的建议,假设总的特征数量为M,这个比例可以是sqrt(M),1/2sqrt(M),2sqrt(M)。
因此,随机森林的训练过程可以总结如下:
(1)给定训练集S,测试集T,特征维数F。确定参数:使用到的CART的数量t,每棵树的深度d,每个节点使用到的特征数量f,终止条件:节点上最少样本数s,节点上最少的信息增益m
对于第1-t棵树,i=1-t:
(2)从S中有放回的抽取大小和S一样的训练集S(i),作为根节点的样本,从根节点开始训练
(3)如果当前节点上达到终止条件,则设置当前节点为叶子节点,如果是分类问题,该叶子节点的预测输出为当前节点样本集合中数量最多的那一类c(j),概率p为c(j)占当前样本集的比例;如果是回归问题,预测输出为当前节点样本集各个样本值的平均值。然后继续训练其他节点。如果当前节点没有达到终止条件,则从F维特征中无放回的随机选取f维特征。利用这f维特征,寻找分类效果最好的一维特征k及其阈值th,当前节点上样本第k维特征小于th的样本被划分到左节点,其余的被划分到右节点。继续训练其他节点。有关分类效果的评判标准在后面会讲。
(4)重复(2)(3)直到所有节点都训练过了或者被标记为叶子节点。
(5)重复(2),(3),(4)直到所有CART都被训练过。
利用随机森林的预测过程如下:
对于第1-t棵树,i=1-t:
(1)从当前树的根节点开始,根据当前节点的阈值th,判断是进入左节点(
=th),直到到达,某个叶子节点,并输出预测值。
(2)重复执行(1)直到所有t棵树都输出了预测值。如果是分类问题,则输出为所有树中预测概率总和最大的那一个类,即对每个c(j)的p进行累计;如果是回归问题,则输出为所有树的输出的平均值。
注:有关分类效果的评判标准,因为使用的是CART,因此使用的也是CART的平板标准,和C3.0,C4.5都不相同。
对于分类问题(将某个样本划分到某一类),也就是离散变量问题,CART使用Gini值作为评判标准。定义为Gini=1-∑(P(i)*P(i)),P(i)为当前节点上数据集中第i类样本的比例。例如:分为2类,当前节点上有100个样本,属于第一类的样本有70个,属于第二类的样本有30个,则Gini=1-0.7×07-0.3×03=0.42,可以看出,类别分布越平均,Gini值越大,类分布越不均匀,Gini值越小。在寻找最佳的分类特征和阈值时,评判标准为:argmax(Gini-GiniLeft-GiniRight),即寻找最佳的特征f和阈值th,使得当前节点的Gini值减去左子节点的Gini和右子节点的Gini值最大。
对于回归问题,相对更加简单,直接使用argmax(Var-VarLeft-VarRight)作为评判标准,即当前节点训练集的方差Var减去减去左子节点的方差VarLeft和右子节点的方差VarRight值最大。
Random Forest与Bagging的区别在于:Bagging每次生成决策树的时候从全部的属性Attributes里面选择,而Random Forest是随机从全部Attributes的集合里面生成一个大小固定的子集,相对而言需要的计算量更小一些。
4.Boosting(Freund & Schapire 1996): boosting在选择hyperspace的时候给样本加了一个权值,使得loss function尽量考虑那些分错类的样本(i.e.分错类的样本weight大)。 怎么做的呢? - boosting重采样的不是样本,而是样本的分布,对于分类正确的样本权值低,分类错误的样本权值高(通常是边界附近的样本),最后的分类器是很多弱分类器的线性叠加(加权组合),分类器相当简单。
结构如图:
AdaBoost和RealBoost是Boosting的两种实现方法。general的说,Adaboost较好用,RealBoost较准确。由于Boosting算法在解决实际问题时有一个重大的缺陷,即他们都要求事先知道弱分类算法分类正确率的下限,这在实际问题中很难做到。后来 Freund 和 Schapire提出了 AdaBoost 算法,该算法的效率与 Freund 方法的效率几乎一样,却可以非常容易地应用到实际问题中。AdaBoost 是Boosting 算法家族中代表算法,AdaBoost 主要是在整个训练集上维护一个分布权值向量 D( x) t ,用赋予权重的训练集通过弱分类算法产生分类假设 Ht ( x) ,即基分类器,然后计算他的错误率,用得到的错误率去更新分布权值向量 D( x) t ,对错误分类的样本分配更大的权值,正确分类的样本赋予更小的权值。每次更新后用相同的弱分类算法产生新的分类假设,这些分类假设的序列构成多分类器。对这些多分类器用加权的方法进行联合,最后得到决策结果。这种方法不要求产生的单个分类器有高的识别率,即不要求寻找识别率很高的基分类算法,只要产生的基分类器的识别率大于 015 ,就可作为该多分类器序列中的一员。 寻找多个识别率不是很高的弱分类算法比寻找一个识别率很高的强分类算法要容易得多,AdaBoost 算法的任务就是完成将容易找到的识别率不高的弱分类算法提升为识别率很高的强分类算法,这也是 AdaBoost 算法的核心指导思想所在, 如果算法完成了这个任务,那么在分类时,只要找到一个比随机猜测略好的弱分类算法,就可以将其提升为强分类算法,而不必直接去找通常情况下很难获得的强分类算法。通过产生多分类器最后联合的方法提升弱分类算法,让他变为强的分类算法,也就是给定一个弱的学习算法和训练集,在训练集的不同子集上,多次调用弱学习算法,最终按加权方式联合多次弱学习算法的预测结果得到最终学习结果。包含以下2点:
样本的权重 AdaBoost 通过对样本集的操作来训练产生不同的分类器,他是通过更新分布权值向量来改变样本权重的,也 就是提高分错样本的权重,重点对分错样本进行训练。
(1) 没有先验知识的情况下,初始的分布应为等概分布,也就是训练集如果有 n个样本,每个样本的分布概率为1/ n。(2) 每次循环后
提高错误样本的分布概率,分错的样本在训练集中所占权重增大 ,使得下一次循环的基分类器能够集中力量对这些错误样本进行判断。
弱分类器的权重 最后的强分类器是通过多个基分类器联合得到的,因此在最后联合时各个基分类器所起的作用对联合结果有很大的影响,因为不同基分类器的识别率不同,他的作用就应该不同,这里通过权值体现他的作用,因此识别率越高的基分类器权重越高,识别率越低的基分类器权重越低。权值计算如下: 基分类器的错误率: e = ∑( ht ( x i) ≠yi) Di (1) 基分类器的权重:W t = F( e) ,由基分类器的错误率计算他的权重。2.3 算法流程及伪码描述 算法流程描述 算法流程可用结构图 1 描述,如图 1 所示 AdaBoost重复调用弱学习算法(多轮调用产生多个分类器) ,首轮调用弱学习算法时,按均匀分布从样本集中选取子集作为该次训练集,以后每轮对前一轮训练失败的样本,赋予较大的分布权值( Di 为第i 轮各个样本在样本集中参与训练的概率) ,使其在这一轮训练出现的概率增加,即在后面的训练学习中集中对比较难训练的样本进行学习,从而得到 T个弱的基分类器, h1 , h2 , …, ht ,其中 ht 有相应的权值 w t ,并且其权值大小根据该分类器的效果而定。最后的分类器由生成的多个分类器加权联合产生。
==================================
参考文章:
[1]Joint Cascade Face Detection and Alignment(ECCV14)
[2]Face Alignment at 3000 FPS via Regressing Local Binary Features (CVPR14)
[3]Cascaded Pose Regression (CVPR10)
[4]Fast Keypoint Recognition in Ten Lines of Code
[5]女神的博文:http://blog.csdn.net/abcjennifer/article/details/8164315
http://blog.sina.com.cn/s/blog_605f5b4f01013r72.html
==================================
转载于:https://www.cnblogs.com/sciencefans/p/4394861.html
你可能感兴趣的:(人脸识别技术大总结1——Face Detection & Alignment)
guava loadingCache代码示例
IM 胡鹏飞
Java 工具类介绍
publicclassTest2{publicstaticvoidmain(String[]args)throwsException{LoadingCachecache=CacheBuilder.newBuilder()//设置并发级别为8,并发级别是指可以同时写缓存的线程数.concurrencyLevel(8)//设置缓存容器的初始容量为10.initialCapacity(10)//设置缓存
C++11堆操作深度解析:std::is_heap与std::is_heap_until原理解析与实践
文章目录堆结构基础与函数接口堆的核心性质函数签名与核心接口std::is_heapstd::is_heap_until实现原理深度剖析std::is_heap的验证逻辑std::is_heap_until的定位策略算法优化细节代码实践与案例分析基础用法演示自定义比较器实现最小堆检查边缘情况处理性能分析与实际应用时间复杂度对比典型应用场景与手动实现的对比注意事项与最佳实践迭代器要求比较器设计C++标
为什么会出现“与此站点的连接不安全”警告?
当浏览器弹出“与此站点的连接不安全”的红色警告时,不仅会让访客感到不安,还可能直接导致用户流失、品牌信誉受损,甚至引发数据泄露风险。作为网站运营者,如何快速解决这一问题?一、为什么会出现“与此站点的连接不安全”警告?浏览器提示“不安全连接”,本质上是检测到当前网站与用户之间的数据传输未经过加密保护。以下是触发警告的常见原因:1.未安装SSL证书SSL(SecureSocketsLayer)证书是网
Flask框架入门:快速搭建轻量级Python网页应用
「已注销」
python-AI python基础 网站网络 python flask 后端
转载:Flask框架入门:快速搭建轻量级Python网页应用1.Flask基础Flask是一个使用Python编写的轻量级Web应用框架。它的设计目标是让Web开发变得快速简单,同时保持应用的灵活性。Flask依赖于两个外部库:Werkzeug和Jinja2,Werkzeug作为WSGI工具包处理Web服务的底层细节,Jinja2作为模板引擎渲染模板。安装Flask非常简单,可以使用pip安装命令
驱动程序为什么要做 WHQL 认证?
GDCA SSL证书
网络协议 网络
驱动程序进行WHQL(WindowsHardwareQualityLabs)认证的核心价值在于解决兼容性、安全性和市场准入三大关键问题,具体必要性如下:️一、规避系统拦截,保障驱动可用性消除安装警告未认证的驱动在安装时会触发Windows的红色安全警告(如“无法验证发布者”),甚至被系统强制拦截。通过WHQL认证的驱动获得微软数字签名,用户可无阻安装。满足系统强制要求Windows1
WHQL签名怎么申请
GDCA SSL证书
windows
WHQL(WindowsHardwareQualityLabs)签名是微软对硬件和驱动程序进行认证的一种方式,以确保它们与Windows操作系统的兼容性和稳定性。以下是申请WHQL签名的基本步骤,供您参考:1.准备阶段准备硬件设备和驱动程序:确保您的硬件设备已经准备好,并且对应的驱动程序已经经过充分的测试,能够在各种配置和环境下正常工作。获取EV代码签名证书:根据微软的要求,驱动程序进行WHQL认
JSON 与 AJAX
Auscy
json ajax 前端
一、JSON(JavaScriptObjectNotation)1.数据类型与语法细节支持的数据类型:基本类型:字符串(需用双引号)、数字、布尔值(true/false)、null。复杂类型:数组([])、对象({})。严格语法规范:键名必须用双引号包裹(如"name":"张三")。数组元素用逗号分隔,最后一个元素后不能有多余逗号。数字不能以0开头(如012会被解析为12),不支持八进制/十六进制
发票合并工具
小朋的软件园
前端 javascript java html 服务器
"发票合并工具"是一款专为高效整理票据设计的实用工具,支持将来自不同渠道的发票文件(如PDF文档、各类图片格式)快速整合为排版规范的PDF文件,尤其适用于财务报销场景下的批量票据处理需求。核心功能亮点多格式兼容:无缝导入PDF文件及常见图片格式(.png/.jpg/.jpeg/.bmp),适配多来源发票整合需求。智能布局配置:提供灵活的页面布局选项(每页2/3/4张发票),其中"2合1"模式针对报
C++ 11 Lambda表达式和min_element()与max_element()的使用_c++ lamda函数 min_element((1)
2401_84976182
程序员 c语言 c++ 学习
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上CC++开发知识点,真正体系化!由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新如果你需要这些资料,可以戳这里获取#include#include#includeusingnamespacestd;boolcmp(int
C++ 11 Lambda表达式和min_element()与max_element()的使用_c++ lamda函数 min_element(
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化的资料的朋友,可以添加戳这里获取一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!intmain(){vectormyvec{3,
【LeetCode 热题 100】24. 两两交换链表中的节点——(解法一)迭代+哨兵
xumistore
LeetCode leetcode 链表 算法 java
Problem:24.两两交换链表中的节点题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。文章目录整体思路完整代码时空复杂度时间复杂度:O(N)空间复杂度:O(1)整体思路这段代码旨在解决一个经典的链表操作问题:两两交换链表中的节点(SwapNodesinPairs)。问题要求将链表中每两个相邻的节点进行交换
JavaScript 树形菜单总结
Auscy
microsoft
树形菜单是前端开发中常见的交互组件,用于展示具有层级关系的数据(如文件目录、分类列表、组织架构等)。以下从核心概念、实现方式、常见功能及优化方向等方面进行总结。一、核心概念层级结构:数据以父子嵌套形式存在,如{id:1,children:[{id:2}]}。节点:树形结构的基本单元,包含自身信息及子节点(若有)。展开/折叠:子节点的显示与隐藏切换,是树形菜单的核心交互。递归渲染:因数据层级不固定,
基于定制开发开源AI智能名片S2B2C商城小程序的社群游戏定制策略研究
说私域
人工智能 小程序 游戏
摘要:本文聚焦社群游戏定制领域,深入探讨以社群文化和用户偏好为导向的定制策略。通过分析互动游戏活动、社群文化塑造等关键要素,结合定制开发开源AI智能名片S2B2C商城小程序的技术特性,提出针对性游戏定制方案。研究旨在提升社群用户参与度与游戏体验,为社群游戏发展提供理论支持与实践指导。关键词:社群游戏定制;定制开发开源AI智能名片S2B2C商城小程序;社群文化;用户偏好一、引言在数字化社交蓬勃发展的
冒泡、选择、插入排序:三大基础排序算法深度解析(C语言实现)
xienda
算法 排序算法 数据结构
在算法学习道路上,排序算法是每位程序员必须掌握的基石。本文将深入解析冒泡排序、选择排序和插入排序这三种基础排序算法,通过C语言代码实现和对比分析,帮助读者彻底理解它们的差异与应用场景。算法原理与代码实现1.冒泡排序(BubbleSort)工作原理:通过重复比较相邻元素,将较大元素逐步"冒泡"到数组末尾。voidbubbleSort(intarr[],intn){ for(inti=0;iarr[
Leetcode 148. 排序链表
文章目录前引题目代码(首刷看题解)代码(8.9二刷部分看解析)代码(9.15三刷部分看解析)前引综合性比较强的一道题,要求时间复杂度必须O(logn)才能通过,最适合链表的排序算法就是归并。这里采用自顶向下的方法步骤:找到链表中点(双指针)对两个子链表排序(递归,直到只有一个结点,记得将子链表最后指向nullptr)归并(引入dummy结点)题目Leetcode148.排序链表代码(首刷看题解)c
python_虚拟环境
阿_焦
python
第一、配置虚拟环境:virtualenv(1)pipvirtualenv>安装虚拟环境包(2)pipinstallvirtualenvwrapper-win>安装虚拟环境依赖包(3)c盘创建虚拟目录>C:\virtualenv>配置环境变量【了解一下】:(1)如何使用virtualenv创建虚拟环境a、cd到C:\virtualenv目录下:b、mkvirtualenvname>创建虚拟环境nam
全面触摸屏输入法设计与实现
长野君
本文还有配套的精品资源,点击获取简介:触摸屏输入法是针对触摸设备优化的文字输入方案,包括虚拟键盘、手写、语音识别和手势等多种输入方式。本方案通过提供主程序文件、用户手册、界面截图、示例图、说明文本和音效文件,旨在为用户提供一个完整的、多样的文字输入体验。开发者通过持续优化算法和用户界面,使用户在无物理键盘环境下也能高效准确地进行文字输入。1.触摸屏输入法概述简介在现代信息技术飞速发展的今天,触摸屏
LeetCode 148. 排序链表:归并排序的细节解析
进击的小白菜
2025 Top100 详解 leetcode 链表 算法
文章目录题目描述一、方法思路:归并排序的核心步骤二、关键实现细节:快慢指针分割链表1.快慢指针的初始化问题2.为什么选择`fast=head.next`?示例1:链表长度为偶数(`1->2->3->4`)三、完整代码实现四、复杂度分析五、总结题目描述LeetCode148题要求对链表进行排序,时间复杂度需为O(nlogn),且空间复杂度为O(logn)。由于链表的特殊结构(无法随机访问),归并排序
前端项目架构设计要领
1.架构设计的核心目标在设计前端项目架构时,核心目标是模块化、可维护、可扩展、可测试,以及开发效率的最大化。这些目标可以通过以下几个方面来实现:组件化:将UI功能封装为可复用的组件。模块化:将业务逻辑分解为独立的模块或服务。自动化构建与部署:实现自动化构建、测试和部署流程,减少人为操作的错误。代码规范化与检查:确保团队协作时,代码风格和质量一致。2.项目目录结构设计一个清晰合理的目录结构对大型项目
精通Canvas:15款时钟特效代码实现指南
烟幕缭绕
本文还有配套的精品资源,点击获取简介:HTML5的Canvas是一个用于绘制矢量图形的API,通过JavaScript实现动态效果。本项目集合了15种不同的时钟特效代码,帮助开发者通过学习绘制圆形、线条、时间更新、旋转、颜色样式设置及动画效果等概念,深化对Canvas的理解和应用。项目中的CSS文件负责时钟的样式设定,而JS文件则包含实现各种特效的逻辑,通过不同的函数或类处理时间更新和动画绘制,提
高效批量单词翻译工具的设计与应用
本文还有配套的精品资源,点击获取简介:在信息技术飞速发展的今天,批量单词翻译工具通过计算机的数据处理能力,大大提高了语言学习和文字处理的效率。用户通过简单输入单词列表到一个文本文件,并运行翻译程序,即可获得翻译结果并保存至指定文件。该工具集成了内置或外部翻译引擎,利用自然语言处理技术实现快速准确的翻译,并可能提供词性识别等附加功能。尽管机器翻译无法完全取代人工校对,但它为用户提供了一种高效的翻译解
嵌入式系统LCD显示模块编程实践
本文还有配套的精品资源,点击获取简介:本文档提供了一个具有800x480分辨率的3.5英寸液晶显示模块LW350AC9001的驱动程序代码,以及嵌入式系统中使用C/C++语言进行硬件编程的实践指南。该模块的2mm厚度使其适用于空间受限的便携式设备。内容包括驱动程序源代码、硬件控制接口使用方法,以及如何在嵌入式系统中进行图形处理、电源管理与性能优化。1.嵌入式系统原理1.1嵌入式系统概念嵌入式系统是
深入剖析OpenJDK 18 GA源码:Java平台最新发展
想法臃肿
本文还有配套的精品资源,点击获取简介:OpenJDK18GA作为Java开发的关键里程碑,提供了诸多新特性和改进。本文章深入探讨了OpenJDK18GA源码,揭示其内部机制,帮助开发者更好地理解和利用这个版本。文章还涵盖了PatternMatching、SealedClasses、Records、JEP395、JEP406和JEP407等特性,以及HotSpot虚拟机、编译器、垃圾收集器、内存模型
Android 开源组件和第三方库汇总
gyyzzr
Android Android 开源框架
转载1、github排名https://github.com/trending,github搜索:https://github.com/search2、https://github.com/wasabeef/awesome-android-ui目录UIUI卫星菜单节选器下拉刷新模糊效果HUD与Toast进度条UI其它动画网络相关响应式编程地图数据库图像浏览及处理视频音频处理测试及调试动态更新热更新
22、文档:Google Docs的强大与易用性
pear55
探索云技术的无限可能 Google Docs 云端文档 语音输入
文档:GoogleDocs的强大与易用性1.GoogleDocs简介GoogleDocs是Google提供的在线办公套件的一部分,它是一个基于云端的文字处
docker-compose方式搭建lnmp环境——筑梦之路
筑梦之路
linux系统运维 国产化 docker android adb
docker-compose.yml文件#生成docker-compose.ymlcat>docker-compose.ymlnginx/conf.d/default.conf">www/index.phpecho"开始启动服务..."docker-composeup-d#获取本机ipip_addr=$(hostname-I|awk'{print$1}')echo"部署完成!"echo"访问测试页
Python爱心光波
系列文章序号直达链接Tkinter1Python李峋同款可写字版跳动的爱心2Python跳动的双爱心3Python蓝色跳动的爱心4Python动漫烟花5Python粒子烟花Turtle1Python满屏飘字2Python蓝色流星雨3Python金色流星雨4Python漂浮爱心5Python爱心光波①6Python爱心光波②7Python满天繁星8Python五彩气球9Python白色飘雪10Pyt
Python流星雨
Want595
python 开发语言
文章目录系列文章写在前面技术需求完整代码代码分析1.模块导入2.画布设置3.画笔设置4.颜色列表5.流星类(Star)6.流星对象创建7.主循环8.流星运动逻辑9.视觉效果10.总结写在后面系列文章序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python
ARM嵌入式可编程控制器技术开发
拉勾科研工作室
arm开发
PLC自动化设计|毕业设计指导|工业自动化解决方案✨专业领域:PLC程序设计与调试工业自动化控制系统HMI人机界面开发工业传感器应用电气控制系统设计工业网络通信擅长工具:西门子S7系列PLC编程三菱/欧姆龙PLC应用触摸屏界面设计电气CAD制图工业现场总线技术自动化设备调试主要内容:PLC控制系统设计工业自动化方案规划电气原理图绘制控制程序编写与调试毕业论文指导毕业设计题目与程序设计✅具体问题可以
基于链家网的二手房数据采集清洗与可视化分析
Mint_Datazzh
项目 selenium 网络爬虫
个人学习内容笔记,仅供参考。项目链接:https://gitee.com/rongwu651/lianjia原文链接:基于链家网的二手房数据采集清洗与可视化分析–笔墨云烟研究内容该课题的主要目的是通过将二手房网站上的存量与已销售房源,构建一个二手房市场行情情况与房源特点的可视化平台。该平台通过HTML架构和Echarts完成可视化的搭建。因此,该课题的主要研究内容就是如何利用相关技术设计并实现这样
Java实现的基于模板的网页结构化信息精准抽取组件:HtmlExtractor
yangshangchuan
信息抽取 HtmlExtractor 精准抽取 信息采集
HtmlExtractor是一个Java实现的基于模板的网页结构化信息精准抽取组件,本身并不包含爬虫功能,但可被爬虫或其他程序调用以便更精准地对网页结构化信息进行抽取。
HtmlExtractor是为大规模分布式环境设计的,采用主从架构,主节点负责维护抽取规则,从节点向主节点请求抽取规则,当抽取规则发生变化,主节点主动通知从节点,从而能实现抽取规则变化之后的实时动态生效。
如
java编程思想 -- 多态
百合不是茶
java 多态详解
一: 向上转型和向下转型
面向对象中的转型只会发生在有继承关系的子类和父类中(接口的实现也包括在这里)。父类:人 子类:男人向上转型: Person p = new Man() ; //向上转型不需要强制类型转化向下转型: Man man =
[自动数据处理]稳扎稳打,逐步形成自有ADP系统体系
comsci
dp
对于国内的IT行业来讲,虽然我们已经有了"两弹一星",在局部领域形成了自己独有的技术特征,并初步摆脱了国外的控制...但是前面的路还很长....
首先是我们的自动数据处理系统还无法处理很多高级工程...中等规模的拓扑分析系统也没有完成,更加复杂的
storm 自定义 日志文件
商人shang
storm cluster logback
Storm中的日志级级别默认为INFO,并且,日志文件是根据worker号来进行区分的,这样,同一个log文件中的信息不一定是一个业务的,这样就会有以下两个需求出现:
1. 想要进行一些调试信息的输出
2. 调试信息或者业务日志信息想要输出到一些固定的文件中
不要怕,不要烦恼,其实Storm已经提供了这样的支持,可以通过自定义logback 下的 cluster.xml 来输
Extjs3 SpringMVC使用 @RequestBody 标签问题记录
21jhf
springMVC使用 @RequestBody(required = false) UserVO userInfo
传递json对象数据,往往会出现http 415,400,500等错误,总结一下需要使用ajax提交json数据才行,ajax提交使用proxy,参数为jsonData,不能为params;另外,需要设置Content-type属性为json,代码如下:
(由于使用了父类aaa
一些排错方法
文强chu
方法
1、java.lang.IllegalStateException: Class invariant violation
at org.apache.log4j.LogManager.getLoggerRepository(LogManager.java:199)at org.apache.log4j.LogManager.getLogger(LogManager.java:228)
at o
Swing中文件恢复我觉得很难
小桔子
swing
我那个草了!老大怎么回事,怎么做项目评估的?只会说相信你可以做的,试一下,有的是时间!
用java开发一个图文处理工具,类似word,任意位置插入、拖动、删除图片以及文本等。文本框、流程图等,数据保存数据库,其余可保存pdf格式。ok,姐姐千辛万苦,
php 文件操作
aichenglong
PHP 读取文件 写入文件
1 写入文件
@$fp=fopen("$DOCUMENT_ROOT/order.txt", "ab");
if(!$fp){
echo "open file error" ;
exit;
}
$outputstring="date:"." \t tire:".$tire."
MySQL的btree索引和hash索引的区别
AILIKES
数据结构 mysql 算法
Hash 索引结构的特殊性,其 检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
可能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢
JAVA的抽象--- 接口 --实现
百合不是茶
抽象 接口 实现接口
//抽象 类 ,方法
//定义一个公共抽象的类 ,并在类中定义一个抽象的方法体
抽象的定义使用abstract
abstract class A 定义一个抽象类 例如:
//定义一个基类
public abstract class A{
//抽象类不能用来实例化,只能用来继承
//
JS变量作用域实例
bijian1013
作用域
<script>
var scope='hello';
function a(){
console.log(scope); //undefined
var scope='world';
console.log(scope); //world
console.log(b);
TDD实践(二)
bijian1013
java TDD
实践题目:分解质因数
Step1:
单元测试:
package com.bijian.study.factor.test;
import java.util.Arrays;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.bijian.
[MongoDB学习笔记一]MongoDB主从复制
bit1129
mongodb
MongoDB称为分布式数据库,主要原因是1.基于副本集的数据备份, 2.基于切片的数据扩容。副本集解决数据的读写性能问题,切片解决了MongoDB的数据扩容问题。
事实上,MongoDB提供了主从复制和副本复制两种备份方式,在MongoDB的主从复制和副本复制集群环境中,只有一台作为主服务器,另外一台或者多台服务器作为从服务器。 本文介绍MongoDB的主从复制模式,需要指明
【HBase五】Java API操作HBase
bit1129
hbase
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.ha
python调用zabbix api接口实时展示数据
ronin47
zabbix api接口来进行展示。经过思考之后,计划获取如下内容: 1、 获得认证密钥 2、 获取zabbix所有的主机组 3、 获取单个组下的所有主机 4、 获取某个主机下的所有监控项  
jsp取得绝对路径
byalias
绝对路径
在JavaWeb开发中,常使用绝对路径的方式来引入JavaScript和CSS文件,这样可以避免因为目录变动导致引入文件找不到的情况,常用的做法如下:
一、使用${pageContext.request.contextPath}
代码” ${pageContext.request.contextPath}”的作用是取出部署的应用程序名,这样不管如何部署,所用路径都是正确的。
Java定时任务调度:用ExecutorService取代Timer
bylijinnan
java
《Java并发编程实战》一书提到的用ExecutorService取代Java Timer有几个理由,我认为其中最重要的理由是:
如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。此时,已经被
SQL 优化原则
chicony
sql
一、问题的提出
在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统
java 线程弹球小游戏
CrazyMizzz
java 游戏
最近java学到线程,于是做了一个线程弹球的小游戏,不过还没完善
这里是提纲
1.线程弹球游戏实现
1.实现界面需要使用哪些API类
JFrame
JPanel
JButton
FlowLayout
Graphics2D
Thread
Color
ActionListener
ActionEvent
MouseListener
Mouse
hadoop jps出现process information unavailable提示解决办法
daizj
hadoop jps
hadoop jps出现process information unavailable提示解决办法
jps时出现如下信息:
3019 -- process information unavailable3053 -- process information unavailable2985 -- process information unavailable2917 --
PHP图片水印缩放类实现
dcj3sjt126com
PHP
<?php
class Image{
private $path;
function __construct($path='./'){
$this->path=rtrim($path,'/').'/';
}
//水印函数,参数:背景图,水印图,位置,前缀,TMD透明度
public function water($b,$l,$pos
IOS控件学习:UILabel常用属性与用法
dcj3sjt126com
ios UILabel
参考网站:
http://shijue.me/show_text/521c396a8ddf876566000007
http://www.tuicool.com/articles/zquENb
http://blog.csdn.net/a451493485/article/details/9454695
http://wiki.eoe.cn/page/iOS_pptl_artile_281
完全手动建立maven骨架
eksliang
java eclipse Web
建一个 JAVA 项目 :
mvn archetype:create
-DgroupId=com.demo
-DartifactId=App
[-Dversion=0.0.1-SNAPSHOT]
[-Dpackaging=jar]
建一个 web 项目 :
mvn archetype:create
-DgroupId=com.demo
-DartifactId=web-a
配置清单
gengzg
配置
1、修改grub启动的内核版本
vi /boot/grub/grub.conf
将default 0改为1
拷贝mt7601Usta.ko到/lib文件夹
拷贝RT2870STA.dat到 /etc/Wireless/RT2870STA/文件夹
拷贝wifiscan到bin文件夹,chmod 775 /bin/wifiscan
拷贝wifiget.sh到bin文件夹,chm
Windows端口被占用处理方法
huqiji
windows
以下文章主要以80端口号为例,如果想知道其他的端口号也可以使用该方法..........................1、在windows下如何查看80端口占用情况?是被哪个进程占用?如何终止等. 这里主要是用到windows下的DOS工具,点击"开始"--"运行",输入&
开源ckplayer 网页播放器, 跨平台(html5, mobile),flv, f4v, mp4, rtmp协议. webm, ogg, m3u8 !
天梯梦
mobile
CKplayer,其全称为超酷flv播放器,它是一款用于网页上播放视频的软件,支持的格式有:http协议上的flv,f4v,mp4格式,同时支持rtmp视频流格 式播放,此播放器的特点在于用户可以自己定义播放器的风格,诸如播放/暂停按钮,静音按钮,全屏按钮都是以外部图片接口形式调用,用户根据自己的需要制作 出播放器风格所需要使用的各个按钮图片然后替换掉原始风格里相应的图片就可以制作出自己的风格了,
简单工厂设计模式
hm4123660
java 工厂设计模式 简单工厂模式
简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式。是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
maven笔记
zhb8015
maven
跳过测试阶段:
mvn package -DskipTests
临时性跳过测试代码的编译:
mvn package -Dmaven.test.skip=true
maven.test.skip同时控制maven-compiler-plugin和maven-surefire-plugin两个插件的行为,即跳过编译,又跳过测试。
指定测试类
mvn test
非mapreduce生成Hfile,然后导入hbase当中
Stark_Summer
map hbase reduce Hfile path实例
最近一个群友的boss让研究hbase,让hbase的入库速度达到5w+/s,这可愁死了,4台个人电脑组成的集群,多线程入库调了好久,速度也才1w左右,都没有达到理想的那种速度,然后就想到了这种方式,但是网上多是用mapreduce来实现入库,而现在的需求是实时入库,不生成文件了,所以就只能自己用代码实现了,但是网上查了很多资料都没有查到,最后在一个网友的指引下,看了源码,最后找到了生成Hfile
jsp web tomcat 编码问题
王新春
tomcat jsp pageEncode
今天配置jsp项目在tomcat上,windows上正常,而linux上显示乱码,最后定位原因为tomcat 的server.xml 文件的配置,添加 URIEncoding 属性:
<Connector port="8080" protocol="HTTP/1.1"
connectionTi