研究3:遺伝的アルゴリズムを活用した風景画の複製
・背景と目的
・アプローチ手法
・原理
・可視化方法
・可視化結果
・考察
下記のコードを実行し、出力として遺伝的アルゴリズムを利用した絵画の複製を行いました。
使用言語はPythonで、CPUによる演算で2日くらいで画像が出力されました。GPUを使用した演算をすればより大きな画像データを扱うことができるため精度を上げられますが、下記のコードではGPUは使わない前提でコーディングしたので、下記のコードをGPU用に修正する必要があります。
import cv2 import numpy as np import numpy.random as nr from copy import deepcopy import matplotlib.pyplot as plt from vcopt import vcopt #画像サイズ(200×200以上のサイズの画像は処理に莫大な時間がかかるため非推奨です) w_aim = 200 h_aim = 200 #画像読み込みと表示 img = cv2.imread('オリジナル画像.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.resize(img, (w_aim, h_aim)) #マスター画像 img_master = np.ones((h_aim, w_aim, 3), np.uint8) * 128 #マスター遺伝子 para_master = np.array([]) #半径列 w = max(w_aim, h_aim) rs = np.linspace(0, w/2, w*10)[::-1] rs_ = np.zeros(w) rs = np.append(rs, rs_) rs = rs.astype(int) #確定した遺伝子をすべて貼る関数 def make_img(para): #定義 num = len(para)//5 img_tmp= np.ones((h_aim, w_aim, 3), int) * 128 para_tmp = deepcopy(para) rs_tmp = deepcopy(rs) #遺伝子の変形 para_tmp = para_tmp.reshape(-1, 5) #遺伝子の分離 points = para_tmp[:, :2] points[:, 0] *= w_aim points[:, 1] *= h_aim points = points.astype(int) #print(points) colors = para_tmp[:, 2:] * 255 colors = colors.astype(int) #print(colors) #貼り付け for i in range(num): if i < len(rs_tmp): point = points[i] color = colors[i] tmp = deepcopy(img_tmp) cv2.circle(tmp, (point[0], point[1]), int(rs_tmp[i]), (int(color[0]), int(color[1]), int(color[2])), thickness=-1) img_tmp = 0.5 * tmp + 0.5 * img_tmp img_tmp = img_tmp.astype(int) return img_tmp #適当な遺伝子を作成して画像を確認 para = nr.rand(5*3) para_master = np.append(para_master, para) img_master = make_img(para_master) #ある部分遺伝子を貼ってスコアを返す関数 def paste_score(para, visible=False): #定義 num = len(para)//5 img_tmp = deepcopy(img_master) para_tmp = deepcopy(para) rs_tmp = rs[step:min(step + num, len(rs))] #遺伝子の変形 para_tmp = para_tmp.reshape(-1, 5) #遺伝子の分離 points = para_tmp[:, :2] points[:, 0] *= w_aim points[:, 1] *= h_aim points = points.astype(int) #print(points) colors = para_tmp[:, 2:] * 255 colors = colors.astype(int) #print(colors) #貼り付け for i in range(num): point = points[i] color = colors[i] tmp = deepcopy(img_tmp) cv2.circle(tmp, (point[0], point[1]), int(rs_tmp[i]), (int(color[0]), int(color[1]), int(color[2])), thickness=-1) img_tmp = 0.5*tmp + 0.5*img_tmp img_tmp = img_tmp.astype(int) #スコア diff = (img - img_tmp)**2 diff = np.mean(diff)**0.5 return diff #新しい遺伝子を貼り込み step = 3 para = nr.rand(5*3) score = paste_score(para, True) #マスター遺伝子とマスター画像を更新 para_master = np.append(para_master, para) img_master = make_img(para_master) #また新しい遺伝子を貼り込み step = 6 para = nr.rand(5*3) score = paste_score(para, True) def GA_step(img_master, para_master, step): #パラメータ範囲 para_range = np.zeros((5*3, 2)) para_range[:, 0] = 0 para_range[:, 1] = 1 #print(para_range) #GAで最適化 para, score = vcopt().rcGA(para_range, #パラメータ範囲 paste_score, #評価関数 0, #目標値 pool_num=50, #個体数 max_gen=10000, #進化世代数 show_pool_func='bar') #バー出力を使う #ステップを更新 step += 3 print(step) #マスター遺伝子を更新 para_master = np.append(para_master, para) #print(para_master) #マスター画像を更新 img_master = make_img(para_master) return img_master, para_master, step #ステップの初期化 step = 0 generation = 0 # 世代数のカウンタを追加 #多段階GA開始 while step < len(rs) - 3: #1段階進める img_master, para_master, step = GA_step(img_master, para_master, step) # 世代数をインクリメント generation += 1 # 世代数を表示 print(f"Generation: {generation}") # 生成した画像をファイルに保存するパス output_image_path = "遺伝的アルゴリズムで複製した画像.png" # 保存先のパスを指定してください # 画像をファイルに保存 cv2.imwrite(output_image_path, img_master)