Metropolis 알고리즘을 사용하여 이미지에서 난수를 생성하여 도트 그림을 생성합니다.
개요
본 기사는 난수 생성 알고리즘인 Metropolis 알고리즘에 의해 화상으로부터 난수를 생성해, 도트 그림을 작성한다고 하는 것입니다. 제목으로 남아 죄송합니다. 다음과 같은 형태입니다.
Motivation
최근 Generative Art에 빠졌습니다. Wiki에 의한 Generative Art의 설명은 이하.
제네레티브 아트 또는 제네라티브 아트(영: Generative Art)는 컴퓨터 소프트웨어의 알고리즘이나 수학적/기계적/무작위적 자율 과정에 의해 알고리즘적으로 생성·합성·구축되는 예술 작품을 가리킨다. 컴퓨터의 계산의 자유도와 계산속도를 살려 자연과학에서 얻은 이론을 실행함으로써 인공과 자연의 중간과 같은 통일감을 가진 유기적인 표현을 하는 작품이 많다.
Metropolis 알고리즘과 같은 난수 생성 알고리즘과 Generative Art는 궁합이 좋은가? 라고 하는 곳에서 이런 일을 할 수 있을까 해 보려고 생각했습니다.
먼저 소스 코드을 붙여 둡니다.
또, 여기서 하고 있는 것을 응용해, 사진으로부터 몇개의 처리(도트 그림, 한 필기의 그림)등을 할 수 있다 iOS 앱 작성했으므로 선전해 둡니다.
Metropolis 알고리즘이란?
나의 해석도 포함하고 있기 때문에 잘못된 부분도 있을지도 모릅니다만 양해 바랍니다.
$z$→$z'$의 전이 확률을 $T(z'|z)$로 합니다.
이때 $T(z'|z)$를 다음과 같이 결정하는 것을 생각합니다.
T(z'|z) = min(1, \frac{p(z')}{p(z)})
그러면 다음과 같은 방정식이 성립합니다.
\begin{align}
p(z)T(z'|z) &= min(p(z), p(z')) \\
&= p(z')T(z|z')
\end{align}
이것은 z에서 오는 z'에 있을 확률과 z'에서 오는 z에 있는 확률이 같다는 것을 의미합니다.
$z$로 총합을 취하면 다음과 같은 등식이 성립합니다. 표현식을 보면 $p(z')$가 항상 일정하다는 것을 알 수 있습니다. 즉, 이와 같이 천이 확률을 선택함으로써 분포가 무너지지 않고 항상 같은 분포로부터 난수를 생성할 수 있게 됩니다.
\begin{align}
p'(z') &= \sum_{z} p(z)T(z'|z) \\
&= \sum_{z} p(z')T(z|z') \\
&= p(z')\sum_{z} T(z|z') \\
&= p(z')
\end{align}
이것을 의사 코드로 하면 다음과 같이 보인다.
z = random(0, 1) * maxZ
for i in range(n):
z_next = random(0, 1) * maxZ
if p(z_next) < p(z):
p(z_next)/p(z)の確率で、z = z_next
else:
z_next = z
코드
코드는 간단하고 다음과 같습니다.
import random
import cv2
import numpy as np
class MetropolistDotPainting:
def __init__(self, img_path, save_path):
self.img = cv2.imread(img_path)
self.save_path = save_path
def draw(self, n, size):
img_paint = np.ones(self.img.shape)
img_paint *= 255
img_width = self.img.shape[1]
img_height = self.img.shape[0]
x = img_width * random.random()
y = img_height * random.random()
for i in range(n):
x_n = img_width * random.random()
y_n = img_height * random.random()
prob = self.get_prob(x, y)
prob_n = self.get_prob(x_n, y_n)
if prob_n < prob:
ratio = prob_n / prob
rand = random.random()
if ratio > rand:
cv2.circle(img_paint, (int(x_n), int(y_n)), size, (0, 0, 0), -1)
x = x_n
y = y_n
else:
cv2.circle(img_paint, (int(x_n), int(y_n)), size, (0, 0, 0), -1)
x = x_n
y = y_n
cv2.imwrite(self.save_path, img_paint)
def get_prob(self, x, y):
x = int(x)
y = int(y)
b = self.img[y, x, 0]
g = self.img[y, x, 1]
r = self.img[y, x, 2]
prob = 0.299 * r + 0.587 * g + 0.114 * b
prob /= 255
prob = 1 - prob
prob = prob ** 5
return prob
if __name__ == '__main__':
img_path = './data/lena.png'
save_path = './data/lena_dot.jpg'
mdp = MetropolistDotPainting(img_path, save_path)
mdp.draw(100000, 1)
마지막으로
이를 적용하고 도트를 컬러로 만들거나 도트 크기를 난수로 생성하거나 도트가 아닌 다각형으로 만들면 재미있는 이미지가 생길 수 있습니다.
틀린 부분 등 있으면 댓글 주시면 다행입니다.
Reference
이 문제에 관하여(Metropolis 알고리즘을 사용하여 이미지에서 난수를 생성하여 도트 그림을 생성합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Rio_physics/items/5304ccf0584c8f372eae
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
최근 Generative Art에 빠졌습니다. Wiki에 의한 Generative Art의 설명은 이하.
제네레티브 아트 또는 제네라티브 아트(영: Generative Art)는 컴퓨터 소프트웨어의 알고리즘이나 수학적/기계적/무작위적 자율 과정에 의해 알고리즘적으로 생성·합성·구축되는 예술 작품을 가리킨다. 컴퓨터의 계산의 자유도와 계산속도를 살려 자연과학에서 얻은 이론을 실행함으로써 인공과 자연의 중간과 같은 통일감을 가진 유기적인 표현을 하는 작품이 많다.
Metropolis 알고리즘과 같은 난수 생성 알고리즘과 Generative Art는 궁합이 좋은가? 라고 하는 곳에서 이런 일을 할 수 있을까 해 보려고 생각했습니다.
먼저 소스 코드을 붙여 둡니다.
또, 여기서 하고 있는 것을 응용해, 사진으로부터 몇개의 처리(도트 그림, 한 필기의 그림)등을 할 수 있다 iOS 앱 작성했으므로 선전해 둡니다.
Metropolis 알고리즘이란?
나의 해석도 포함하고 있기 때문에 잘못된 부분도 있을지도 모릅니다만 양해 바랍니다.
$z$→$z'$의 전이 확률을 $T(z'|z)$로 합니다.
이때 $T(z'|z)$를 다음과 같이 결정하는 것을 생각합니다.
T(z'|z) = min(1, \frac{p(z')}{p(z)})
그러면 다음과 같은 방정식이 성립합니다.
\begin{align}
p(z)T(z'|z) &= min(p(z), p(z')) \\
&= p(z')T(z|z')
\end{align}
이것은 z에서 오는 z'에 있을 확률과 z'에서 오는 z에 있는 확률이 같다는 것을 의미합니다.
$z$로 총합을 취하면 다음과 같은 등식이 성립합니다. 표현식을 보면 $p(z')$가 항상 일정하다는 것을 알 수 있습니다. 즉, 이와 같이 천이 확률을 선택함으로써 분포가 무너지지 않고 항상 같은 분포로부터 난수를 생성할 수 있게 됩니다.
\begin{align}
p'(z') &= \sum_{z} p(z)T(z'|z) \\
&= \sum_{z} p(z')T(z|z') \\
&= p(z')\sum_{z} T(z|z') \\
&= p(z')
\end{align}
이것을 의사 코드로 하면 다음과 같이 보인다.
z = random(0, 1) * maxZ
for i in range(n):
z_next = random(0, 1) * maxZ
if p(z_next) < p(z):
p(z_next)/p(z)の確率で、z = z_next
else:
z_next = z
코드
코드는 간단하고 다음과 같습니다.
import random
import cv2
import numpy as np
class MetropolistDotPainting:
def __init__(self, img_path, save_path):
self.img = cv2.imread(img_path)
self.save_path = save_path
def draw(self, n, size):
img_paint = np.ones(self.img.shape)
img_paint *= 255
img_width = self.img.shape[1]
img_height = self.img.shape[0]
x = img_width * random.random()
y = img_height * random.random()
for i in range(n):
x_n = img_width * random.random()
y_n = img_height * random.random()
prob = self.get_prob(x, y)
prob_n = self.get_prob(x_n, y_n)
if prob_n < prob:
ratio = prob_n / prob
rand = random.random()
if ratio > rand:
cv2.circle(img_paint, (int(x_n), int(y_n)), size, (0, 0, 0), -1)
x = x_n
y = y_n
else:
cv2.circle(img_paint, (int(x_n), int(y_n)), size, (0, 0, 0), -1)
x = x_n
y = y_n
cv2.imwrite(self.save_path, img_paint)
def get_prob(self, x, y):
x = int(x)
y = int(y)
b = self.img[y, x, 0]
g = self.img[y, x, 1]
r = self.img[y, x, 2]
prob = 0.299 * r + 0.587 * g + 0.114 * b
prob /= 255
prob = 1 - prob
prob = prob ** 5
return prob
if __name__ == '__main__':
img_path = './data/lena.png'
save_path = './data/lena_dot.jpg'
mdp = MetropolistDotPainting(img_path, save_path)
mdp.draw(100000, 1)
마지막으로
이를 적용하고 도트를 컬러로 만들거나 도트 크기를 난수로 생성하거나 도트가 아닌 다각형으로 만들면 재미있는 이미지가 생길 수 있습니다.
틀린 부분 등 있으면 댓글 주시면 다행입니다.
Reference
이 문제에 관하여(Metropolis 알고리즘을 사용하여 이미지에서 난수를 생성하여 도트 그림을 생성합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Rio_physics/items/5304ccf0584c8f372eae
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
T(z'|z) = min(1, \frac{p(z')}{p(z)})
\begin{align}
p(z)T(z'|z) &= min(p(z), p(z')) \\
&= p(z')T(z|z')
\end{align}
\begin{align}
p'(z') &= \sum_{z} p(z)T(z'|z) \\
&= \sum_{z} p(z')T(z|z') \\
&= p(z')\sum_{z} T(z|z') \\
&= p(z')
\end{align}
z = random(0, 1) * maxZ
for i in range(n):
z_next = random(0, 1) * maxZ
if p(z_next) < p(z):
p(z_next)/p(z)の確率で、z = z_next
else:
z_next = z
코드는 간단하고 다음과 같습니다.
import random
import cv2
import numpy as np
class MetropolistDotPainting:
def __init__(self, img_path, save_path):
self.img = cv2.imread(img_path)
self.save_path = save_path
def draw(self, n, size):
img_paint = np.ones(self.img.shape)
img_paint *= 255
img_width = self.img.shape[1]
img_height = self.img.shape[0]
x = img_width * random.random()
y = img_height * random.random()
for i in range(n):
x_n = img_width * random.random()
y_n = img_height * random.random()
prob = self.get_prob(x, y)
prob_n = self.get_prob(x_n, y_n)
if prob_n < prob:
ratio = prob_n / prob
rand = random.random()
if ratio > rand:
cv2.circle(img_paint, (int(x_n), int(y_n)), size, (0, 0, 0), -1)
x = x_n
y = y_n
else:
cv2.circle(img_paint, (int(x_n), int(y_n)), size, (0, 0, 0), -1)
x = x_n
y = y_n
cv2.imwrite(self.save_path, img_paint)
def get_prob(self, x, y):
x = int(x)
y = int(y)
b = self.img[y, x, 0]
g = self.img[y, x, 1]
r = self.img[y, x, 2]
prob = 0.299 * r + 0.587 * g + 0.114 * b
prob /= 255
prob = 1 - prob
prob = prob ** 5
return prob
if __name__ == '__main__':
img_path = './data/lena.png'
save_path = './data/lena_dot.jpg'
mdp = MetropolistDotPainting(img_path, save_path)
mdp.draw(100000, 1)
마지막으로
이를 적용하고 도트를 컬러로 만들거나 도트 크기를 난수로 생성하거나 도트가 아닌 다각형으로 만들면 재미있는 이미지가 생길 수 있습니다.
틀린 부분 등 있으면 댓글 주시면 다행입니다.
Reference
이 문제에 관하여(Metropolis 알고리즘을 사용하여 이미지에서 난수를 생성하여 도트 그림을 생성합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Rio_physics/items/5304ccf0584c8f372eae
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Metropolis 알고리즘을 사용하여 이미지에서 난수를 생성하여 도트 그림을 생성합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Rio_physics/items/5304ccf0584c8f372eae텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)