|
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): |
|
|
|
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.rgb_cyano = np.array(self.rgb_cyano) |
|
|
|
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 |
|
boxFromY = i*h_+5 |
|
boxToX = ((j+1)*w_)-7 |
|
boxToY = ((i+1)*h_)-7 |
|
|
|
imgBox = self.patch_img[boxFromY: boxToY, boxFromX: boxToX] |
|
|
|
|
|
|
|
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_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 |
|
|
|
|
|
|
|
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) |
|
|
|
|
|
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() |
|
|
|
|
|
print(step_count) |
|
|
|
|
|
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) |
|
|