C'est une continuation de la dernière fois et de la dernière fois.
Cependant, j'ai trouvé une meilleure méthode que le "placement optimal de plusieurs images" pour résoudre le problème d'optimisation, j'ai donc adopté cette méthode cette fois.
Avec la génération automatique de modèles de collage, vous pouvez créer des modèles presque illimités. Par conséquent, vous devez créer de nombreux modèles et sélectionner celui qui peut afficher le plus joliment la liste d'images donnée. En fait, il est bon d'exprimer le modèle avec des paramètres et de résoudre le problème d'optimisation, mais c'est une tâche future.
Maintenant, tout d'abord, nous devons réfléchir à ce que cela signifie pour pouvoir afficher le plus beau. Cette fois, j'ai décidé de souligner les deux points suivants.
Le premier critère est facile à comprendre. Plus vous cassez le rapport hauteur / largeur de l'image, moins elle sera belle, alors essayez de la conserver. Cependant, avec seulement le premier critère, une seule image est affichée en grand, et les autres images peuvent être considérablement petites (finalement non affichées). Par conséquent, nous avons adopté la deuxième norme.
Quant à la manière de les réaliser, tout d'abord, les valeurs suivantes sont données.
・ $ H $: Largeur verticale du collage à créer
・ $ W $: Largeur du collage à créer
・ $ \ {x_i \} _ {i = 1} ^ n
Puis positionnez le gabarit
def generate_template(n, width, height, random_state=1, max_random_state=1000000, offset=0):
L = [np.array([offset, offset, width-offset, height-offset])]
random_state_lists = stats.randint.rvs(0, max_random_state, size=(n-1, 4), random_state=random_state)
for idx, random_state_list in enumerate(random_state_lists):
n_areas = len(L)
if n_areas == 1:
i = 0
else:
p = np.repeat(1 / (n_areas + i), n_areas)
x = stats.multinomial.rvs(1, p, size=1, random_state=random_state_list[0])[0]
i = x.argmax()
y = stats.bernoulli.rvs(0.5, size=1, random_state=random_state_list[1])[0]
if y == 0:
b = stats.uniform.rvs(L[i][0], L[i][2] - L[i][0], size=1, random_state=random_state_list[2])[0]
else:
b = stats.uniform.rvs(L[i][1], L[i][3] - L[i][1], size=1, random_state=random_state_list[3])[0]
if y == 0:
area1 = np.array([L[i][0], L[i][1], b-offset/2, L[i][3]])
area2 = np.array([b+offset/2, L[i][1], L[i][2], L[i][3]])
else:
area1 = np.array([L[i][0], L[i][1], L[i][2], b-offset/2])
area2 = np.array([L[i][0], b+offset/2, L[i][2], L[i][3]])
L.pop(i)
L.append(area1)
L.append(area2)
return np.array(L)
Différents modèles peuvent être générés en modifiant random_state pour n. Au fait, le décalage est la distance entre les images (épaisseur de la bordure).
Ensuite, décidez où placer chaque image dans le modèle. Ceci est réalisé en choisissant l'emplacement avec le rapport hauteur / largeur le plus similaire. Trouvez l'emplacement $ j \ _i $ dans le modèle où l'image $ i $ sera placée ci-dessous.
\begin{align*}
j_i &= \text{argmin}_{j} \ \|r_i - r'_j \|^2 \\
r_i &= \frac{[x_i]_1}{[x_i]_0}, \ r'_j = \frac{[s_j]_1}{[s_j]_0}
\end{align*}
Cependant, $ [x] _i $ est le composant $ i $ de $ x $. De plus, une fois que vous avez sélectionné l'emplacement, vous ne pouvez pas le sélectionner. Autrement dit, $ \ {j \ _1, \ ldots, j \ _n \} = \ {1, \ ldots, n \} $.
En utilisant ce qui précède, définissez la fonction de score $ f $ pour la taille du modèle $ S $ comme suit.
\begin{align*}
f(S) = \sum_{i=1}^n \|r_i - r_{j_i}\|^2 + \frac{\alpha}{n}
\sum_{i=1}^n \left( [s_i]_1 [s_i]_2 - \frac{1}{n} \sum_{i'=1}^n [s_{i'}]_1 [s_{i'}]_2 \right)^2
\end{align*}
Créez des modèles $ m $ et appelez-les $ S ^ {(1)}, \ ldots, S ^ {(m)} $. Enfin, choisissez un modèle qui minimise $ f $.
J'ai essayé une expérience basée sur ce qui précède. De plus, j'ai utilisé l'image suivante.
Les résultats expérimentaux sont les suivants.
N'est-il pas bien intégré?
Cette fois, j'ai essayé de générer automatiquement un collage. En conséquence, je pense que nous avons fait quelque chose de propre. En tant que futur numéro,
C'est ça? Le code utilisé pour l'expérience est répertorié ci-dessous. Merci pour la lecture.
import itertools
import glob
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
from skimage import io, transform
def generate_template(n, width, height, random_state=1, max_random_state=1000000, offset=0):
L = [np.array([offset, offset, width-offset, height-offset])]
random_state_lists = stats.randint.rvs(0, max_random_state, size=(n-1, 4), random_state=random_state)
for idx, random_state_list in enumerate(random_state_lists):
n_areas = len(L)
if n_areas == 1:
i = 0
else:
p = np.repeat(1 / (n_areas + i), n_areas)
x = stats.multinomial.rvs(1, p, size=1, random_state=random_state_list[0])[0]
i = x.argmax()
y = stats.bernoulli.rvs(0.5, size=1, random_state=random_state_list[1])[0]
if y == 0:
b = stats.uniform.rvs(L[i][0], L[i][2] - L[i][0], size=1, random_state=random_state_list[2])[0]
else:
b = stats.uniform.rvs(L[i][1], L[i][3] - L[i][1], size=1, random_state=random_state_list[3])[0]
if y == 0:
area1 = np.array([L[i][0], L[i][1], b-offset/2, L[i][3]])
area2 = np.array([b+offset/2, L[i][1], L[i][2], L[i][3]])
else:
area1 = np.array([L[i][0], L[i][1], L[i][2], b-offset/2])
area2 = np.array([L[i][0], b+offset/2, L[i][2], L[i][3]])
L.pop(i)
L.append(area1)
L.append(area2)
return np.array(L)
def estimate(X, w, h, random_states, offset=0):
r = np.c_[X[:, 0] / X[:, 1]]
r2 = r**2
best_L = None
best_s = None
lowest_linkage = np.inf
for random_state in random_states:
s = stats.uniform.rvs(0, 1, random_state=random_state)
L = generate_template(X.shape[0], w*s, h*s, random_state=random_state, offset=offset*s)
r_temp = np.c_[(L[:, 2] - L[:, 0]) / (L[:, 3] - L[:, 1])]
r_temp2 = r_temp**2
dist2 = r2 + r_temp2.T - r.dot(r_temp.T)
assignment = []
linkage = 0
selected = set()
for i, idx in enumerate(dist2.argsort(axis=1)):
for j in idx:
if j not in selected:
linkage += dist2[i, j]
assignment.append(j)
selected.add(j)
break
assignment = np.array(assignment)
L = L[assignment]
A = L.copy()
size = np.c_[L[:, 2] - L[:, 0], L[:, 3] - L[:, 1]]
L = np.c_[L[:, 0], L[:, 1], np.min(size / X, axis=1)]
mu = L[:, 2].mean()
var = np.sqrt(np.mean((L[:, 2] - mu)**2))
linkage = linkage + var
if linkage < lowest_linkage:
lowest_linkage = linkage
best_L = A
best_s = s
return best_L, best_s, lowest_linkage
if __name__ == '__main__':
images = []
X = []
for filename in glob.glob("img/*")[:3]:
image = io.imread(filename)
images.append(image)
X.append((image.shape[0], image.shape[1]))
X = np.array(X)
Z = np.c_[X[:, 1], X[:, 0]]
width, height = 375, 667
L, s, linkage_value = estimate(Z, width, height, range(100), offset=0)
L = L / s
print(linkage_value)
position = np.int32(np.c_[L[:, 1], L[:, 0]])
size = np.int32(np.c_[L[:, 3] - L[:, 1], L[:, 2] - L[:, 0]])
canvas = np.zeros((height, width, 3))
for i in range(len(images)):
image = images[i]
print(image.shape)
canvas[position[i][0]:position[i][0]+size[i][0], position[i][1]:position[i][1]+size[i][1]] = transform.resize(image, size[i])
plt.imshow(canvas)
plt.show()
Recommended Posts