Python编程生成马赛克画 很酷~

2018-09-1322:24:09后端程序开发Comments2,369 views字数 1730阅读模式

马赛克画是一张由小图拼成的大图,本文的封面就是我们的效果图,放大看细节,每一块都是一张独立的图片,拼在一起组成一张大图,感觉像是用马赛克拼出来的画,所以叫马赛克画。看到网上的一些马赛克画觉得很酷,于是自己用Python实现了一下将一张原图转换成马赛克画。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

封面的原图是这样的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

Python编程生成马赛克画 很酷~

实现的具体思路是这样文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

第一步:首先收集一组图片,这些图片会作为大图中的小方格图片。图片越多,最后生成的图片颜色越接近。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

第二步:将要转换的图片分割成一个一个小方格图片,像下面这样文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

Python编程生成马赛克画 很酷~

第三步:对于每一个小方格图片,取图片集里面最接近的图片替换。所有小方格都替换后,就生成了我们最终的马赛克画。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

听上去是不是很简单?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

我们来看一下具体的实现步骤,下面是一些核心代码。完整代码可在公众号【Python与数据分析】后台回复“mosaic”获取。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

我们的图片集存在images目录下,下面的代码加载目录下所有的图片,并缩放成统一的尺寸文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

import re
import os
import cv2
import numpy as np
from tqdm import tqdm

IMG_DIR = "images"

def load_all_images(tile_row, tile_col):
    img_dir = IMG_DIR
    filenames = os.listdir(img_dir)
    result = []
    print(len(filenames))
    for filename in tqdm(filenames):
        if not re.search(".jpg", filename, re.I):
            continue
        try:
            filepath = os.path.join(img_dir, filename)
            im = cv2.imread(filepath)
            row = im.shape[0]
            col = im.shape[1]
            im = resize(im, tile_row, tile_col)
            result.append(np.array(im))
        except Exception as e:
            msg = "error with {} - {}".format(filepath, str(e))
            print(msg)
    return np.array(result, dtype=np.uint8)

这里load_all_images函数的参数就是统一后的尺寸,tile_row和tile_col分别对应高和宽。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

下面的代码对要转换的图片进行分割文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

img = cv2.imread(infile)
tile_row, tile_col = get_tile_row_col(img.shape)
for row in range(0, img_shape[0], tile_row):
    for col in range(0, img_shape[1], tile_col):
        roi = img[row:row+tile_row,col:col+tile_col,:]

我们将要转换的图片分割成一个个小方格,tile_row和tile_col是小方格的高和宽,roi存取小方格中的图片数据。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

下面是计算两张图片相似度的函数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

from scipy.spatial.distance import euclidean
def img_distance(im1, im2):
    if im1.shape != im2.shape:
        msg = "shapes are different {} {}".format(im1.shape, im2.shape)
        raise Exception(msg)
    array1 = im1.flatten()
    array2 = im2.flatten()
    dist = euclidean(array1, array2)
    return dist

im1和im2是两张图片的数据,图片数据是一个三维的numpy数组,这里我们将三维数组转换成一维数组后,比较两者的欧式距离。之后要找出最相似的图片,只需遍历图片集中所有的图片,找到距离最短的那张图片,去替换原图中的小方格就可以了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

我们再来看一下最终实现的效果文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

Python编程生成马赛克画 很酷~

放大图中局部的细节如下文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

Python编程生成马赛克画 很酷~

如果对图片的画质不满意,想要更精细的画质,可以考虑在分割的时候把图片分割成更小的方格,不过这样也会增加程序运行的时间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

生成图片的过程比较耗时,考虑到性能原因,原程序中使用多进程的方式并行处理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/4622.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/4622.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定