logistic混沌映射算法

简述

Logistic 混沌映射算法是一种十分简单的算法,其函数是源于一个人口统计的动力学系统,系统方程形式如下: \[ X(k+1)=uX(k)[1-X(k)],\ (k=0,1,\dots,n) \] 由此可知其是一个非线性方程,当同时也是一个递推序列,当满足下述条件时,Logistic 函数将工作于混沌状态: \[ \begin{cases} 0<X(0)<1\\ 3.5699456\dots<\mu\le4 \end{cases} \] 此时当确定一个 \(X(0)\)\(\mu\) 时,我们将得到一个混沌序列。

图像置乱

序列生成

  1. 首先我们需求一个 \(X_0\) 和一个 \(\mu\),带入方程进行迭代得到一个足够混乱的 \(X(0)\)
  2. 以该 \(X(0)\) 再往下迭代,得到一个 Logistic 序列。

需要注意的是,往往我们会使迭代次数足够大,这样才能得到足够混乱的序列。

再将序列归一化到 \((0,255)\) 区间内即可。

置乱

存在一个 \(M\times N\) 的图像,将其转化为 \(M\times N\) 的序列,与生成的 Logistic 序列进行异或,如此便完成了一次置乱。

而因为其是通过异或进行置乱的,所以当我们对该序列再进行一次置乱,便可得到原图。

实现

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
31
32
33
34
35
36
37
38
39
40
41
42
from PIL import Image
import numpy as np

def logistic(im, x0: int, mu: int, times: int = 500):
"""
Logistic图像置乱

Parameters:
im - Image.open获取的图像类
x0 - 初始密钥
mu - 初始密钥
times - 混沌系统的迭代次数

Returns:
置乱完毕的Image图像类
"""
width, height = im.size
im = np.array(im, dtype = np.uint8).flatten()
num = im.size

for _ in range(times):
x0 = mu * x0 * (1 - x0)

E = np.empty(num, dtype = np.float64)
E[0] = x0
for i in range(0,num-1):
E[i+1] = mu * E[i] * (1-E[i])
E = np.round(E*255).astype(np.uint8)

im = np.bitwise_xor(E, im)
im = im.reshape(width, height, -1)
im = np.squeeze(im)
im = Image.fromarray(im)
return im

im = Image.open("flag.png")
# im = im.convert("L")
x0 = 0.43
mu = 3.9

im_de = logistic(im, x0, mu)
im_de.save(f'flagde.png')

该实现可以应用于彩色图片和灰度图。

同时我还实现了一个 Logistic 的迭代器:

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
31
32
33
34
35
36
def LogisticRange(x0: int, mu: int, limit: int, times: int = 500):
"""
Logistic序列有限迭代器

Parameters:
x0 - 初始密钥
mu - 初始密钥
limit - 序列上限
times - 混沌系统的迭代次数

Returns:
序列值
"""
for _ in range(times):
x0 = mu * x0 * (1 - x0)
for _ in range(limit):
yield x0
x0 = mu * x0 * (1 - x0)

def LogisticCount(x0: int, mu: int, times: int = 500):
"""
Logistic序列无限迭代器

Parameters:
x0 - 初始密钥
mu - 初始密钥
times - 混沌系统的迭代次数

Returns:
序列值
"""
for _ in range(times):
x0 = mu * x0 * (1 - x0)
while True:
yield x0
x0 = mu * x0 * (1 - x0)