马赛克(蒙太奇)图片生成--Python实现

马赛克(蒙太奇)图片生成

马赛克(蒙太奇)图片生成--Python实现_第1张图片

观察上面一张图我们可以发现,图片大致为一个蒙娜丽莎的画像,但是又有些不太一样。图片由一个个块组成,每一个块都是一张另外的图片,那么要实现这样的效果,我们应该怎样做呢?用一句话来概括就是将计算目标图片中的不同的数据集中源图片的相似度,选择相似度最高的进行替换。

假设图片是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)

我们可以选择一张图片来看看效果

原本的图片:

马赛克(蒙太奇)图片生成--Python实现_第2张图片

生成的马赛克图片:

马赛克(蒙太奇)图片生成--Python实现_第3张图片

从效果来看还是不错的

你可能感兴趣的:(日常总结,python,图像处理)