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

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

在这里插入图片描述

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

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

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

原本的图片:

在这里插入图片描述

生成的马赛克图片:

在这里插入图片描述

从效果来看还是不错的😁

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值