0%

基于LDA的人脸识别方法–fisherface

LDA几何意义

最小化类内散度Jw,最大化类间散度Jb。这样的目的是使得投影后同一类的数据尽可能聚集,不同类的数据尽可能分散,以达到更好的分类效果。

LDA的数学推导过程

Sw:类内散度,操作对象是类内数据,w表示within

Sb:类间散度,操作对象是类的均值,b表示between

St:总散度,操作对象是所有数据,t表示total

假设一共有N个元素,其中有C个类,每个类都有一定数量的元素,我们的目的是找到一个投影矩阵,使得对原数据进行投影后,得到的数据的Jw最小,Jb最大。为了达到Jw最小,Jb最大的目的,可以有多种目标函数,比如使得Jb/Jw最大,比如使得Jw/Jb最小,比如使得Jb-Jw最大,都是可以的。这里以第一种目标,即使得投影后数据的Jb/Jw最大为目标,进行推导。

先证明类间散度Jb可以用类间散度矩阵Sb来表示:

证明过程:

Read more »

基于 2DPCA 的人脸识别方法——特征脸法[3]

2DPCA

论文:Two-dimensional PCA: a new approach to appearance-based face representation and recognition | IEEE Journals & Magazine | IEEE Xplore

提出了 2DPCA 的方法,是对基于PCA的特征脸法的改进。该方案直接对图片本身(矩阵)进行操作,而不是像 PCA 一样,把一张图片拉成一条列向量再进行计算。这种方法显著减少了协方差矩阵的维度,减少了计算量。2DPCA 使用较少的特征向量就能够较好地对人脸进行重构。

Read more »

基于 PCA 的人脸识别方法——特征脸法[2]

前言

这次主要说说 Matlab 实现与可视化。上次用了 YaleB 数据集不够好用,每个人的人脸图片数量不同,导致训练数据和测试数据划分比较麻烦。这次换了ORL数据集,好了些。

PCA

  1. 数据读取与预处理,ORL数据集一共400张图,40人,一个人10张。每个人10张照片,取4张作为测试数据,6张作为训练数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
% 400张图,一共40人,一人10张
load('ORL4646.mat');

% 重塑后400列,一列是一张脸
reshaped_faces = reshape(ORL4646, 46*46,400);

% 取出前40%作为测试数据,剩下60%作为训练数据
test_data_index = [];
train_data_index = [];
for i=0:39
test_data_index = [test_data_index 10*i+1:10*i+4];
train_data_index = [train_data_index 10*i+5:10*(i+1)];
end

test_data = reshaped_faces(:, test_data_index);
train_data = reshaped_faces(:, train_data_index);

得到的训练数据和测试数据都是一个矩阵,每一列就是一张脸。通过提取训练数据中的部分列向量,重塑为方阵,并转化为灰度图像得到下图,代表了未经处理的原始数据,如图所示:

原始数据
Read more »

基于 PCA 的人脸识别方法——特征脸法

  • 论文:Eigenfaces for Recognition (mitpressjournals.org)

  • 1991 年的论文,提出了一种借助 PCA 方法进行有效人脸识别的方法——特征脸法。

  • 思路:借助 PCA 分析主要成分,对人脸数据进行降维,再进行相关计算,以减少复杂度。

PCA 的几何解释

  1. 找到一组新的坐标轴,或者说是一组新的基(basis),用于表示原来的数据,使得在表示数据时不同轴是不相关的(即协方差为0)。

  2. 取出其中含有信息较多(即方差较大)的坐标轴(基),构成(span)一个新的空间,舍弃其他维度的信息。

  3. 由于新空间的维度小于原来的空间,所以把数据投影到新的空间后,可以大大降低数据的复杂度(虽然会损失少量信息)。

Read more »

I got this problem when I was trying to login into my PC by remote desktop APP.

problem

I found many solutions on the Internet but none of them can solve my problem. Finally I found that it just because I have changed the main login email of my Microsoft account a few days ago, and I have to connect to my PC by my new email instead of the old one.

本文地址: https://www.chimaoshu.top/Microsoft-Remote-Desktop-we-couldn-t-connect-to-the-remote-pc-this-might-be-due-to-an-expired-password/
版权声明:本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议,转载请注明出处。

写了 .proto 文件,编译成 c# 使用。在使用时,发现有一些特性一直没有补全。

比如文档说到了:

The collection type for repeated fields is always RepeatedField<T>. This type is like List<T> but with a few extra convenience methods, such as an Add overload accepting a collection of items, for use in colleciton initializers.

但是我定新建一个 repeated 字段后并没有它说到的 Add() 方法,然后在网上查到了别人的代码的的确确用了 Add 方法。

查了挺久,没发现有人和我有类似问题,最后发现只是因为没有安装 protobuf 的依赖。

由于.proto生成的c#代码也是依赖于 Google.Protobuf 的,所以在没有安装之前一直没有补全,安装之后就好了。

本文地址: https://www.chimaoshu.top/c-在使用protobuf过程中遇到的小坑/
版权声明:本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议,转载请注明出处。

遇到的问题

我想在数据库中存一个被转化为Base64字符串的SHA256哈希值,我在想要用什么类型的值来存储,是用Text还是char[n],这实际上和base64编码的长度有关,于是就查了下wiki。

编码原理

编码其实是基于一个64个数值的编码表(图源维基百科):
base64编码表

也就是说每一个base64字符能够表示6bit的内容(2的6次方为64),换句话说,每4个base64字符(4 * 6 = 24)可以表示3(3 * 8 = 24)字节的内容。

Read more »

首先到release页面下载cpp的release:

https://github.com/protocolbuffers/protobuf/releasesgithub.com

比如这种:

img

你可以手动下载后解压,或者:

1
2
3
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/protobuf-cpp-3.14.0.tar.gz
tar -zxvf protobuf-cpp-3.14.0.tar.gz
cd protobuf-cpp-3.14.0

检查依赖文件是否齐全:

1
autoreconf -f -i

否则后续make可能会出现这样的问题:

img

正常的流程是:

1
./configure --prefix=/usr/local/

但是由于我们没有sudo权限,一方面不能使用bash运行configure,一方面无法写/usr/local/,所以这两个地方都需要做修改:

在./configure前面加上sh,后面的路径换成自己有权限的路径:

1
sh ./configure --prefix=替换成一个你拥有权限的目录

然后是:

1
2
3
make
make check
make install

即可等待安装完成,其中make和make check耗时较长,如果不愿意等,可以跳过make check 过程。

考虑到我们是在自己指定的目录下安装的,可能该目录没有被添加到本用户的环境变量下,因此可以:

1
vim ~/.bash_profile

然后把目录路径添加到PATH的最后面:

img

当初我弄到这里以为大功告成了,其实后面还有一大堆坑等着我,如果你写了一个protobuf的测试程序用原生g++进行编译,还会遇到大量的问题。

简单的说,你最好把protobuf手动添加到g++寻找头文件的路径、寻找动态、静态链接库的路径,否则后续编译可能会出很多奇怪的问题。当然你也可以在编译时使用-I、-L的命令,也许可以不用设置这些东西:

(这些也是在~/.bash_profile文件中设置的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 环境变量,中间用冒号隔开
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:$HOME/protobuf_lib/bin
export PATH

# g++找头文件的路径
CPLUS_INCLUDE_PATH=$HOME/protobuf_lib/include
export CPLUS_INCLUDE_PATH

# 找动态链接库的路径
LD_LIBRARY_PATH=$HOME/protobuf_lib/lib:/usr/local/lib:$HOME/workspace/MouseDB/lib/protobuf/lib
export LD_LIBRARY_PATH

# 找静态链接库的路径
LIBRARY_PATH=$HOME/protobuf_lib/lib:/usr/local/lib:$HOME/workspace/MouseDB/lib/protobuf/lib
export LIBRARY_PATH

# 找pkg_config的路径
export PKG_CONFIG_PATH=$HOME/protobuf_lib/lib/pkgconfig

最后再重新生效一下即可:

1
source ~/.bash_profile

BTW,如果后续编译出现google::protobuf::之类undefined的问题,请务必再编译时添加

1
-lprotobuf -lpthread

两个参数,比如我的Makefile是这样的:

1
2
3
# proto测试
proto_test : test/test_proto/proto_test.cc
g++ -wall $^ -g -o test/test_proto/$@ -std=c++11 -lprotobuf -lpthread

本文地址: https://www.chimaoshu.top/CentOS下无sudo安装protobuf的过程/
版权声明:本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议,转载请注明出处。

浅析比特币中的数据结构

block chain

​ 从整体上看,block chain是由哈希指针连成的链表。如图所示,除了创世纪块以外,每一个区块都有指向上一个区块的哈希指针,同时最新产生的区块也会有一个哈希指针指向他,只是还未被记录到下一个区块中。

​ 值得一提的是,指向一个区块的哈希值由在此之前的所有区块共同作用。之所以说是“在此之前的所有区块共同作用”,是因为每个区块的block header都会存储上一个区块的哈希值,而计算区块的哈希值又需要整个block header的参与,上一个区块的哈希值自然包含在里面。

​ 因此,只要某一个区块发生了篡改,后续的所有区块的哈希值都需要进行相应的修改,才能使得哈希指针能够对上。这个数据结构的好处是,只要存储最后一个哈希指针,就能检测前面所有的区块是否被篡改过,这是区块链不可篡改性的基石。

block body

​ 顾名思义,block body是每一个区块的身体部分,它存储了由矿工打包的一些交易。整体上看,block body是由一课Merkle Tree构成的。

​ Merkle Tree,构成block body的数据结构。类似二叉树,但是这里的指针是哈希指针而非普通的指针。block body需要存储每一笔交易的具体内容,这些交易的具体内容都存储在Merkle Tree的叶子节点中。而每一个叶子节点都会生成哈希,兄弟节点之间的哈希会再进行一次哈希,生成父节点的值,以此类推,最终生成一个根哈希值(root hash),存储在block header中。

​ 这种数据结构有什么好处呢?首先,我们只要存储一个root hash就能判断每一笔交易(即叶子节点)是否被篡改,这并不难理解。

​ 其次,我们可以进行所谓的Merkle Proof,即证明某一笔交易是否被写到区块链中。在比特币这个去中心化的世界中,每个设备都是一个节点。挖矿的矿工属于全节点,他们的设备上存储了从创世纪块到现在的所有区块的block header与block body。而比特币钱包属于轻节点,与全节点不同的是,轻节点只存储block header,而不存储block body。前面说到,root hash会存储在block header里面,因此轻节点拥有root hash的内容。当你使用比特币钱包做了一次转账,轻节点(比特币钱包)需要检查转账是否被写在区块链里面,那么钱包会向全节点发起一次请求,由全节点返回对应路径上的哈希(如上图所示,如果想要检查a交易是否被写到区块里面,那么全节点会返回H(b)与H(H(c), H(d))),这样轻节点就可以在O(logN)的时间复杂度内算出root hash,检查其与本地存储的block header里面存储的信息是否一致,如果一致,则证明交易已经被存储到区块中。

block header

block header里面并没有亮眼的数据结构,但它存储的信息仍然十分重要,我们不妨看看:

这是来自https://www.blockchain.com/btc/block的区块链信息,是7分钟前刚被矿工挖到的一个区块。可以看到里面存储了很多信息,比如我们前面提到的,整个区块链的哈希,以及Merkle root的哈希,还有出块的时间、挖矿得到的比特币奖励、矿工小费、协议版本等信息。

本文地址: https://www.chimaoshu.top/浅析比特币中的数据结构/
版权声明:本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议,转载请注明出处。

绕过微信证书检验

微信APP内置了对自家证书的校检,因此抓包时,微信会因为检测到自签名证书而拒绝联网。而Xposed能使用hook的方式来绕过它。

其中VirtualXposed是一个免root的不错选择:

https://github.com/android-hacker/VirtualXposedgithub.com

在项目的release页面可找到APK。

再使用VirtualXposed安装JustTrustMe插件:

https://github.com/Fuzion24/JustTrustMegithub.com

在项目的release页面可找到APK,在安装APK时需选择“在VirtualXposed中安装”。

需要注意的时,VirtualXposed中的插件只会对VirtualXposed中的软件起作用,因此需要在VirtualXposed中也安装微信APP,建议到微信官网寻找32位的微信APP,不要使用64位APP或者使用应用商城的APK进行安装,否则很可能安装失败。

同样的,下载微信的APK后,选择“在VIrtualXposed中安装”即可。

使用Burp进行抓包

需要从电脑中把burp的证书导出并安装到手机里面:

在burp里面选择导出证书(export certificate),然后修改后缀为.cer,传给手机后,选择证书,点击安装,随便勾选用途即可。

img

再次之后,打开手机的wifi–更多设置–开启代理,填你电脑的内网ip(要求手机和电脑在同一局域网)以及burp的监听端口就可以了。

img

先开启burp的监听,然后开启VitualXposed中的微信即可开始对微信进行抓包。

无论是获取微信内置浏览器的cookies,或者对微信小程序进行测试,都可以采用此方法。

本文地址: https://www.chimaoshu.top/VirtualXposed-Burp对微信抓包思路/
版权声明:本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议,转载请注明出处。