观察上面一张图我们可以发现,图片大致为一个蒙娜丽莎的画像,但是又有些不太一样。图片由一个个块组成,每一个块都是一张另外的图片,那么要实现这样的效果,我们应该怎样做呢?用一句话来概括就是将计算目标图片中的不同的块
和数据集中源图片
的相似度,选择相似度最高的进行替换。
假设图片是RGB三通道的,我们可以分别求出来块
的三个通道的均值,然后再比较块
和源图片
三通道数值之间的欧式距离,卡方距离或者其它距离,最终完成比较和替换。
import cv2
import os
import matplotlib.pyplot as plt
import numpy as np
import math
from scipy.spatial.distance import jensenshannon
from scipy.spatial.distance import euclidean
from scipy.spatial.distance import hamming
from scipy.spatial.distance import correlation
from tqdm import trange
# get the pic to be compared
def load_comp_image(img_path, step1, step2):
this_source_comp_img = []
for filename in os.listdir(img_path):
img = np.array(cv2.imread(img_path + "/" + filename))
comp_img = cv2.resize(img, (step1, step2))
this_source_comp_img.append(comp_img)
this_source_comp_img = np.array(this_source_comp_img)
return this_source_comp_img
# get the source image
def load_src_image(img_path, step1, step2):
this_source_img = []
for filename in os.listdir(img_path):
img = cv2.imread(img_path + "/" + filename)
this_source_img.append(cv2.resize(img, (step1, step2)))
this_source_img = np.array(this_source_img)
return this_source_img
# get the target image
def load_target_image(img_path, num_row, num_col):
img = np.array(cv2.imread(img_path))
img_reshaped = cv2.resize(img, (num_row, num_col))
return img_reshaped
# down sampling
def down_sampling_graph(image):
image = cv2.pyrDown(image)
return image
# calculate the distance of the source picture and target picture
def get_dis_pic(src_pic, tar_pic):
src_pic_2 = np.zeros((500, step1, step2, 3))
count = 0
big_pic = np.zeros((my_num_row, my_num_col, 3))
for i in trange(0, my_num_row, step1):
for j in range(0, my_num_col, step2):
dist = float('inf')
tmp = np.array(tar_pic[i:i + step1, j:j + step2])
for k in range(0, len(src_pic)):
means1, stddev1 = cv2.meanStdDev(tmp)
means2, stddev2 = cv2.meanStdDev(src_pic[k])
# euclidean
# distance = abs(means1[0] - means2[0]) + abs(means1[1] - means2[1]) \
# + abs(means1[2] - means2[2])
# Chi Square
distance = abs(means1[0] - means2[0]) ** 2 / (means1[0] + means2[0]) \
+ abs(means1[1] - means2[1]) ** 2 / (means1[1] + means2[1]) \
+ abs(means1[2] - means2[2]) ** 2 / (means1[2] + means2[2])
# hamming
# distance = jensenshannon(means1, means2)
if dist > distance:
dist = distance
big_pic[i:i + step1, j:j + step2] = src_pic[k]
return big_pic
if __name__ == "__main__":
my_num_row = 1500
my_num_col = 1500
step1 = 10
step2 = 10
tar_img = load_target_image('natural_test.jpg', my_num_row, my_num_col)
source_img = load_src_image("./assignment1/CS303 Dataset for assignment 1/natural_training", step1, step2)
final_pic = get_dis_pic(source_img, tar_img)
final_pic = cv2.resize(final_pic, (1698, 1131))
cv2.imwrite('natural_chisquare_avg.jpg', final_pic)
我们可以选择一张图片来看看效果
原本的图片:
生成的马赛克图片:
从效果来看还是不错的