python实现蒙太奇马赛克效果

1. 实验简介

相片马赛克(Photomosaic),或称蒙太奇照片、蒙太奇拼贴,是一种影像处理的艺术技巧,利用这个方式做出来的图片,近看时是由许多张小照片合在一起的,但远看时,每张照片透过光影和色彩的微调,组成了一张大图的基本像素,就叫做相片马赛克技巧。最先是由一个美国大学生发明的,但当时限于计算机性能,无法大量应用。

 

2. 实验效果

初始图片:

python实现蒙太奇马赛克效果_第1张图片

若干小图片:

由这些小图片根据相应的算法拼成初始图片:

python实现蒙太奇马赛克效果_第2张图片

 

3. 代码实现

import os
import cv2
import numpy as np

# 小图片集合的路径
smallPicPath = r"E:\Material\Pic"
# 大图片的路径
bigPicPath = r"E:\Material\Origin\1.jpg"
# 用来看图片的处理进度
n = 0
# 存放每个小图片的平均RGB值
smallPicRGBDic = []
# 小图片压缩像素
smallPicPixel = 20
# 大图片压缩像素
bigPicPixel = 1000


# 读出图片并压缩
def readImg(path, pixel):
    img = cv2.imread(path)
    # 更改图片的大小,方便处理
    img = cv2.resize(img, (pixel, pixel))
    return img


# 计算图片RGB的平均值
def computeAverageRGB(img, pixel, i, j):
    aveRGB = []
    picR = picG = picB = 0
    for l in range(i, i + pixel):
        for m in range(j, j + pixel):
            picR += img[l, m, 0]
            picG += img[l, m, 1]
            picB += img[l, m, 2]
    picAveR = picR / (pixel * pixel)
    picAveG = picG / (pixel * pixel)
    picAveB = picB / (pixel * pixel)
    aveRGB = [picAveR, picAveG, picAveB]
    return aveRGB


if __name__ == '__main__':
    smallPicFiles = os.listdir(smallPicPath)
    for file in smallPicFiles:
        picPath = smallPicPath + "\\" + file
        img = readImg(picPath, smallPicPixel)

        smallPicRGB = computeAverageRGB(img, smallPicPixel, 0, 0)
        smallPicRGBDic.append((file, smallPicRGB))
        # 更改之后写入文件
        cv2.imwrite(picPath, img)
        n += 1
        print(n)

    # 为方便操作,重新设置大图片的大小
    img = readImg(bigPicPath, bigPicPixel)
    # 可不必写回原文件
    # cv2.imwrite(bigPicPath, img)

    # 存放新图片的矩阵
    bigPic = np.zeros((bigPicPixel, bigPicPixel, 3))

    for i in range(0, bigPicPixel, smallPicPixel):
        for j in range(0, bigPicPixel, smallPicPixel):
            minDistance = np.inf
            mini = ""
            bigPicRGB = computeAverageRGB(img, smallPicPixel, i, j)

            # 从小图片集合中找出与大图片的一部分欧式距离最小的图片,并记录
            for key, value in smallPicRGBDic:
                distance = abs(bigPicRGB[0] - value[0]) + abs(bigPicRGB[1] - value[1]) \
                           + abs(bigPicRGB[2] - value[2])
                if distance < minDistance:
                    minDistance = distance
                    mini = key
            # 读取小图片
            small = cv2.imread(smallPicPath + "\\" + mini)
            # bigPic[i * 10:(i + 1) * 10, j * 10:(j + 1) * 10] = small
            # 把图片画到大图的相应位置
            bigPic[i:i + smallPicPixel, j:j + smallPicPixel] = small
    # 输出大图到文件中
    cv2.imwrite(r"E:\Material\big.jpg", bigPic)

 

4. 算法思路

使用RGB分量相近的小图片去替换初始图片中对应像素区域。实现步骤:

  1. 将若干小图片先转化为20*20的图片,分别计算RGB三个分量的平均值,保存在三元组中。
  2. 取初始图片中的20*20像素区域,计算这一区域中RGB三个分量的平均值,并从小图片集合中找出与这一像素区域的RGB平均值欧式距离最小的图片,进行替换。
  3. 循环进行步骤2直到整个初始图片都替换完成。

 

参考:

https://www.cnblogs.com/FZfangzheng/p/10852575.html

https://blog.csdn.net/Phoenix_wang_cheng/article/details/52840142

你可能感兴趣的:(图像处理,计算机视觉,opencv,计算机视觉,python,图像处理)