Dies ist eine Fortsetzung des letzten und des letzten Males.
Ich habe jedoch eine bessere Methode als "optimale Platzierung mehrerer Bilder" gefunden, um das Optimierungsproblem zu lösen, und habe diese Methode dieses Mal übernommen.
Mit der automatischen Generierung von Collagenvorlagen können Sie nahezu unbegrenzte Vorlagen erstellen. Daher sollten Sie viele Vorlagen erstellen und die auswählen, die die angegebene Bildliste am schönsten anzeigen kann. Eigentlich ist es gut, die Vorlage mit Parametern auszudrücken und das Optimierungsproblem zu lösen, aber das ist eine zukünftige Aufgabe.
Nun müssen wir uns zunächst überlegen, was es bedeutet, das Schönste zeigen zu können. Dieses Mal habe ich beschlossen, die folgenden zwei Punkte hervorzuheben.
Das erste Kriterium ist leicht zu verstehen. Je mehr Sie das Seitenverhältnis des Bildes brechen, desto weniger schön wird es sein. Versuchen Sie also, es beizubehalten. Mit nur dem ersten Kriterium wird jedoch nur ein Bild groß angezeigt, und die anderen Bilder dürfen erheblich klein sein (letztendlich nicht angezeigt). Deshalb haben wir den zweiten Standard übernommen.
Um diese zu realisieren, werden zunächst die folgenden Werte angegeben.
・ $ H $: Vertikale Breite der zu erstellenden Collage
・ $ W $: Breite der zu erstellenden Collage
・ $ \ {x_i \} _ {i = 1} ^ n
Positionieren Sie dann die Vorlage
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)
Durch Ändern von random_state für n können verschiedene Vorlagen generiert werden. Versatz ist übrigens der Abstand zwischen den Bildern (Dicke des Randes).
Als nächstes entscheiden Sie, wo jedes Bild in die Vorlage eingefügt werden soll. Dies wird erreicht, indem der Ort mit dem ähnlichsten Seitenverhältnis ausgewählt wird. Suchen Sie den Ort $ j \ _i $ in der Vorlage, an dem das Bild $ i $ unten platziert wird.
\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*}
$ [X] _i $ ist jedoch die $ i $ -Komponente von $ x $. Sobald Sie den Standort ausgewählt haben, können Sie ihn nicht mehr auswählen. Das heißt, $ \ {j \ _1, \ ldots, j \ _n \} = \ {1, \ ldots, n \} $.
Definieren Sie mithilfe der obigen Funktion die Bewertungsfunktion $ f $ für die Vorlagengröße $ S $ wie folgt.
\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*}
Erstellen Sie $ m $ -Vorlagen und nennen Sie sie $ S ^ {(1)}, \ ldots, S ^ {(m)} $. Wählen Sie schließlich eine Vorlage, die $ f $ minimiert.
Ich habe ein Experiment versucht, das auf dem oben genannten basiert. Außerdem habe ich das folgende Bild verwendet.
Die experimentellen Ergebnisse sind wie folgt.
Ist es nicht gut eingebettet?
Dieses Mal habe ich versucht, automatisch eine Collage zu generieren. Daher denke ich, dass wir etwas Eigenes gemacht haben. Als zukünftige Ausgabe,
--Parametrisieren und optimieren Sie die Vorlage
Ist es? Der für das Experiment verwendete Code ist unten aufgeführt. Danke fürs Lesen.
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