基于遗传算法的自动拼图(二)

适应度度量

两块拼图如果拼在一块的话 则Left-Right方向 相邻的两列色差较小。同理Top-down方向相邻两行的色差会较小

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
def dissimilarity_measure(first_piece, second_piece, orientation="LR"):
"""
依据:在所有颜色通道上的所有相邻像素上的颜色差异。
原始图像中相邻的拼图块趋于共享
类似的颜色沿其邻接边缘,即,即所有相邻像素的平方色差之和
(在所有三个颜色带上)
应该是最小的。
"""
rows, columns, _ = first_piece.shape()
color_difference = None

# | L | - | R |
if orientation == "LR":
color_difference = first_piece[:rows, columns - 1, :] - second_piece[:rows, 0, :]

# | T |
# |
# | D |
if orientation == "TD":
color_difference = first_piece[rows - 1, :columns, :] - second_piece[0, :columns, :]

squared_color_difference = np.power(color_difference / 255.0, 2)
#行相加
color_difference_per_row = np.sum(squared_color_difference, axis=1)
#列相加
total_difference = np.sum(color_difference_per_row, axis=0)

value = np.sqrt(total_difference)

return value

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
#个体:拼图的一种解决方案
class Individual(object):
def __init__(self, pieces, rows, columns, shuffle=True):
self.pieces = pieces[:]
self.rows = rows
self.columns = columns
self._fitness = None
#python装饰器 把一个getter方法变成属性,只需要加上@property就可以了
@property
def fitness(self):
"""Evaluates fitness value.

Fitness value is calculated as sum of dissimilarity measures between each adjacent pieces.
适应度值是计算每个相邻块之间不同度量值的总和。
"""
if self._fitness is None:
fitness_value = 1 / self.FITNESS_FACTOR
# For each two adjacent pieces in rows
for i in range(self.rows):
for j in range(self.columns - 1):
ids = (self[i][j].id, self[i][j + 1].id)
fitness_value += ImageAnalysis.get_dissimilarity(ids, orientation="LR")
# For each two adjacent pieces in columns
for i in range(self.rows - 1):
for j in range(self.columns):
ids = (self[i][j].id, self[i + 1][j].id)
fitness_value += ImageAnalysis.get_dissimilarity(ids, orientation="TD")

self._fitness = self.FITNESS_FACTOR / fitness_value

return self._fitness

轮盘赌选择法


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
#轮盘赌选择
def roulette_selection(population, elites=4):
"""Roulette wheel selection.

Each individual is selected to reproduce, with probability directly
proportional to its fitness score.

:params population: Collection of the individuals for selecting.
:params elite: Number of elite individuals passed to next generation.

Usage::

>>> from gaps.selection import roulette_selection
>>> selected_parents = roulette_selection(population, 10)

"""
fitness_values = [individual.fitness for individual in population]
probability_intervals = [sum(fitness_values[:i + 1]) for i in range(len(fitness_values))]
def select_individual():
"""Selects random individual from population based on fitess value"""
random_select = random.uniform(0, probability_intervals[-1])
selected_index = bisect.bisect_left(probability_intervals, random_select)
return population[selected_index]

selected = []
for i in xrange(len(population) - elites):
first, second = select_individual(), select_individual()
selected.append((first, second))


return selected

参考链接

https://blog.csdn.net/zheng_zhiwei/article/details/23209729
https://www.cnblogs.com/adelaide/articles/5679475.html