shikibu9419's picture
Add production codes
f1d6080
raw
history blame
5.27 kB
import cv2
import numpy as np
import tensorflow as tf
from sklearn.linear_model import LinearRegression
from src.get_patch_rgb import get_patch_rgb
class Cyanotype():
def __init__(self):
### set for patch ###
patch_img_path = './colorpatches/cyanotype_full.png'
self.update_patch(cv2.imread(patch_img_path, cv2.IMREAD_COLOR))
def update_patch(self, patch_img):
self.rgb_cyano = [[0,0,0]]
self.patch_img = patch_img
self.patch_img_height, self.patch_img_width, _ = self.patch_img.shape
self.crop_img()
self.patch_rgb = get_patch_rgb()
self.patch_rgb = np.array(self.patch_rgb)
# self.patch_rgb = self.patch_rgb/255.0
self.rgb_cyano = np.array(self.rgb_cyano)
# self.rgb_cyano = self.rgb_cyano/255.0
print(self.patch_rgb.shape)
print(self.rgb_cyano.shape)
self.fit_model()
def crop_img(self):
# 対象範囲を切り出し
h_pix = 14
w_pix = 21
w_ = round(self.patch_img_width/w_pix)
h_ = round(self.patch_img_height/h_pix)
for i in range(h_pix):
for j in range(w_pix):
boxFromX = j*w_+5 #対象範囲開始位置 X座標
boxFromY = i*h_+5 #対象範囲開始位置 Y座標
boxToX = ((j+1)*w_)-7 #対象範囲終了位置 X座標
boxToY = ((i+1)*h_)-7 #対象範囲終了位置 Y座標
# y:y+h, x:x+w の順で設定
imgBox = self.patch_img[boxFromY: boxToY, boxFromX: boxToX]
# RGB平均値を出力
# flattenで一次元化しmeanで平均を取得
b = imgBox.T[0].flatten().mean()
g = imgBox.T[1].flatten().mean()
r = imgBox.T[2].flatten().mean()
self.rgb_cyano.append([r,g,b])
del self.rgb_cyano[0]
def fit_model(self):
self.reg = LinearRegression().fit(self.patch_rgb, self.rgb_cyano)
self.reg.score(self.patch_rgb, self.rgb_cyano)
print('self.reg.coef_: ', self.reg.coef_)
print('self.reg.intercept_: ', self.reg.intercept_)
def predict_img(self, img):
print(img.shape)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# img = cv2.resize(img, dsize=None, fx=0.2, fy=0.2)
# img = cv2.resize(img, dsize=(100, 100))
# img = cv2.resize(img, dsize=(500, 500))
img_cyano = img @ self.reg.coef_.T + self.reg.intercept_
img_cyano = img_cyano.astype(np.uint8)
img_cyano = cv2.cvtColor(img_cyano, cv2.COLOR_RGB2BGR)
img_cyano = np.array(img_cyano)
print(img_cyano.shape)
return img_cyano
def MSE(self, imageA, imageB):
err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
err /= float(imageA.shape[0] * imageA.shape[1] * imageA.shape[2])
return err
# ---------- Optimization with Tensorflow ---------- #
def tf_optimize(self, img):
print('\n---------- Start Optimization ----------')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
x = self.reg.coef_
A = img
target = img
A_height = A.shape[0]
A_width = A.shape[1]
cnt = A_height*A_width
print(A.shape)
print(cnt)
param_tf = tf.Variable(A, dtype=tf.float64)
coef_tf = tf.constant(x.T, dtype=tf.float64)
intercept_tf = tf.constant(self.reg.intercept_, dtype=tf.float64)
target_tf = tf.constant(target, dtype=tf.float64)
opt = tf.keras.optimizers.Adam(learning_rate=5.0)
# opt = tf.keras.optimizers.Adam(learning_rate=0.1)
def loss():
x0 = param_tf
x0 = tf.where(x0 > 255.0, 255.0, x0)
x0 = tf.where(x0 < 0.0, 0.0, x0)
x0 = tf.reshape(x0, [cnt, 3])
t_tf = target_tf
t_tf = tf.reshape(t_tf, [cnt, 3])
pred = tf.linalg.matmul(x0, coef_tf) + intercept_tf
diff = pred - t_tf
diff_2 = diff**2
pix_cnt = tf.size(t_tf)
pix_cnt = tf.cast(pix_cnt, dtype=tf.float64)
loss_val = tf.math.reduce_sum(diff_2) / pix_cnt
print('loss_val: ', loss_val)
return loss_val
for i in range(50):
step_count = opt.minimize(loss, [param_tf]).numpy()
# if step_count==10:
# break
print(step_count)
# ----- check optimized result ----- #
x0 = param_tf
x0 = tf.where(x0 > 255.0, 255.0, x0)
x0 = tf.where(x0 < 0.0, 0.0, x0)
x0 = x0.numpy()
x0 = x0.reshape((cnt, 3))
sim_opt = x0 @ x.T + self.reg.intercept_
sim_opt = sim_opt.reshape((A_height, A_width, 3))
sim_opt = sim_opt.astype(np.uint8)
sim_opt = cv2.cvtColor(sim_opt, cv2.COLOR_RGB2BGR)
return (x0, sim_opt)
if __name__ == '__main__':
img = cv2.imread('samples/input/00.jpg', cv2.IMREAD_COLOR)
cy = Cyanotype()
cy.fit_model()
cy.predict_img(img)
cy.tf_optimize(img)