用 mathematica 生成 identicon 头像 2. 用Mathematica生成10*10像素的Identicon头像 3. 更通用些? 4. 用Python来试试看

Identicon 在很多大型IT网站上可以见到,比如 Github、Sourceforge、Stackoveflow等。Github 给新用户生成 5x5 像素的 Identicons 头像。

Identicon 是如何生成的呢?

每一个用户都有一个ID的哈希值,然后根据哈希值再来决定每个像素点。以5*5 的头像为例,一共有25个像素点,每个像素点可选择 0(无着色) 或 1(着色),理论上可以有$2^{25}$种组合,即使考虑对称性也仍然有$2^{15}$种组合,若是再考虑不同的颜色,那组合会更多。

分享一个哈希头像的生成网站:http://identicon.net,这里可以是用不同的编码方式:MD5、SHA128、SHA256等。

下面分享下用Mathematica生成的头像。

在网络上找到一篇关于用Mathematica生成Identicon程序[1],在此基础上略作修改。程序内有备注,方便阅读。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
name = "Idenicon"; 
hashcode =
Hash[name,
"MD5"]; (*以MD5方式转换成哈希值,此处可选择MD5、SHA256、SHA512等*)
hashcode2deci =
IntegerDigits[hashcode, 2, 128]; (*将哈希值转成128位的二进制数*)
seperate =
Partition[hashcode2deci, 16] ;(*将128位的二进制划分,16个一组,共8组*)
BXOR =
BitXor @@@ seperate; (*位异或,变成8个0 或者 1 的数字*)
{row5,
col3} = {BXOR[[1 ;; 5]],
BXOR[[-3 ;;]]};(*将第1到第5个数字取出,倒数3个数字取出构造数组*)
leftPart =
Table[BitXor[r, c], {r, row5}, {c,
col3}] ;(*构造5*5矩阵的左半边矩阵5*3*)
trans =
Transpose[leftPart];(*将矩阵转置*)
rightt =
trans[[2 ;; 2, All]] ; (*取转置矩阵的最后一行*)
For[i = 1, i >= 1, i--,
rightt = Join[rightt,
trans[[i ;; i, All]]]]; (*将矩阵行数降序排列*)
rightPart =
Transpose[rightt] ;(* 将右侧矩阵转置*)
joinedmatrix =
Join[leftPart, rightPart, 2];(*将左右两个矩阵合并*)
MatrixPlot[joinedmatrix,
ColorRules -> {1 -> Hue[Rescale[hashcode, {0, 2^128 - 1}]],
0 -> White}] (*绘制矩阵,并控制颜色和框线*)

在Mathematica中运行上述程序即可生成Identicon头像,你就能看到了。

大致讲一下上述程序的逻辑:

  1. 将字符串生成由0 和1组成的128位哈希值;
  2. 将哈希值分组,每16个为一组,一共8组;
  3. 使用位异或得到每组的0 或1 值;
  4. 将8个位异或值分成前5组和后3组,其中后3组控制5*5 矩阵的左半边矩阵(5*5)
  5. 生成了一个5*3的矩阵;
  6. 将该矩阵做轴对称变换(先转置5*3矩阵,后逆序排列取前两行,再转置成5*2的右矩阵)
  7. 两个矩阵合并成5*5矩阵,并绘制图像。

这里的可能存在的问题是:

Q: 为什么是128位哈希值,为什么要以16个为一组?
A: 这是可以修改的(在下面的例子中——150位哈希值并以10个为一组)。

Q: 这里为什么会出现8?
A: 因为在5*5矩阵,先生成左半边的矩阵,即5*3矩阵;若是10*10矩阵,则会生成10*5矩阵。

2. 用Mathematica生成10*10像素的Identicon头像

我们来试一下10*10像素的Identicon头像吧,只需要把程序中的几行修改一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
name = "Identicon"; 
hashcode =
Hash[name,
"MD5"]; (*以MD5方式转换成哈希值*)
hashcode2deci =
IntegerDigits[hashcode, 2, 150]; (*将哈希值转成150位的二进制数*)
seperate =
Partition[hashcode2deci, 10] ;(*将150位的二进制划分,10个一组,共15组*)
BXOR =
BitXor @@@ seperate; (*位异或,变成15个0 或者 1 的数字*)
{row10,
col5} = {BXOR[[1 ;; 10]],
BXOR[[-5 ;;]]}(*将第1到第10个数字取出,倒数5个数字取出构造数组*)
leftPart =
Table[BitXor[r, c], {r, row10}, {c,
col5}] ;(*构造10*10矩阵的左半边矩阵10*5*)
trans = Transpose[leftPart];(*将矩阵转置*)
rightt = trans[[4 ;; 4, All]]
For[i = 3, i >= 1, i--, rightt = Join[rightt, trans[[i ;; i, All]]]];
rightPart = Transpose[rightt] ;
joint = Join[leftPart, rightPart, 2] ;
joint // MatrixForm
(*joint = Join[leftPart,rightt,2]*) (*合并两个矩阵*)
MatrixPlot[joint,
ColorRules -> {1 -> Hue[Rescale[hashcode, {0, 2^128 - 1}]],
0 -> White}, Frame -> None] (*绘制矩阵,并控制颜色和框线*)

3. 更通用些?

考虑程序的通用性和兼容性,将需要改变的参数(dimensionelementnum)列出,就有了以下的调整,其中dimension是需要生成Identicon的尺寸,例如5*5,10*10等,elementnum是指划分元素的数目(可不修改)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
name = "Identicon"; 
dimension = 25;
elementnum = 5;
(*--以下为主程序--*)
hashcode = Hash[name, "MD5"];
hashcode2deci =
IntegerDigits[hashcode, 2,
elementnum*(dimension + Quotient[dimension, 2] +
Mod[dimension, 2])];
seperate = Partition[hashcode2deci, element] ;
BXOR = BitXor @@@ seperate;
{rowd, cold} = {BXOR[[1 ;; dimension]],
BXOR[[-Quotient[dimension, 2] - Mod[dimension, 2] ;;]]};
leftPart = Table[BitXor[r, c], {r, rowd}, {c, cold}] ;
trans = Transpose[leftPart];
rightt =
trans[[Quotient[dimension, 2] + Mod[dimension, 2] - 1 ;;
Quotient[dimension, 2] + Mod[dimension, 2] - 1, All]] ;
For[i = Quotient[dimension, 2] + Mod[dimension, 2] - 2, i >= 1, i--,
rightt = Join[rightt, trans[[i ;; i, All]]]];
rightPart = Transpose[rightt] ;
joinedmatrix = Join[leftPart, rightPart, 2];
MatrixPlot[joinedmatrix,
ColorRules -> {1 -> Hue[Rescale[hashcode, {0, 2^128 - 1}]],
0 -> White}]

生成的Identicon如下图所示。

4. 用Python来试试看

首先利用pip包管理工具下载identicon库

1
$ pip install identicon

新建一个test.py的文件

1
2
3
import identicon  
img= identicon.render_identicon('123123', 16)
img.save('123123.png')

在python中运行,即可得到以下图片。

是不是有点不一样?这是因为生成像素矩阵的算法不一样,有时间再研究研究吧。


参考:

[1] Mathematica实战范例:[15]Github 头像制作


Log:

2019-01-11: 上传
2019-01-09: 调试通用程序
2019-01-08: Hexo插入数学公式
2019-01-04: 调试Mathematica程序
2018-12-29: 创建