opencv+python 程序员的浪漫:蒙太奇照片制作

opencv+python 程序员的浪漫:蒙太奇照片制作_第1张图片

前言:所谓的蒙太奇效果,就是指用很多张小图片「拼组」成一张全新的图片。当然,也有人把他叫做马赛克拼图。这种图片看起来感觉非常特别,非常神奇!你是否也想自己做一张像这样的照片呢?可别以为真的要用PS手工一张一张去拼凑哦,那可会累死人的。本文展示利用python+opencv来完成马赛克图的制作,效果图如下:
opencv+python 程序员的浪漫:蒙太奇照片制作_第2张图片

文章目录

  • 一、思路
  • 二、代码解析
    • 1. 思路1.代码:
    • 2. 思路2.代码:
    • 3. 思路3.代码:
    • 4. 思路4.代码:
    • 5. 思路5.代码:
  • 三、源代码
  • 四、运行结果

一、思路

  1. 修改那些提前准备的一堆图片的大小到马赛克般大小。
  2. 放大目标图片的长宽,使之长宽都是马赛克大小的整数倍。
  3. 计算每一张图片的直方图,建立索引字典。
  4. 以马赛克大小为单位遍历目标图片同时计算这个区域的直方图,然后和提前准备的用于替换的马赛克图片的直方图的索引字典进行比较,用直方图相关性最大的替换目标图片。
  5. 用全替换好的图片和2. 产生的图片做一个融合,效果更加逼真。

二、代码解析

1. 思路1.代码:

# 预处理填充图片
def before_handle_imgs():
    print("正在预处理填充图片:")
    readPath = "C:\\Users\\ASUS\\Desktop\\data0"
    savePath = "C:\\Users\\ASUS\\Desktop\\data1"

    files = os.listdir(readPath)

    for file in files:
        imgPath = readPath + "\\" + file
        img = cv.imread(imgPath)
        img = cv.resize(img, (size, size))
        cv.imwrite(savePath + "\\" + file, img)
    print("预处理填充图片已完成!")

2. 思路2.代码:

# 预处理待填充图片
def before_handle_img():
    print("正在预处理待填充图片:")
    width, height = 10800*n, 13900*n
    readPath = "C:\\Users\\ASUS\\Desktop\\girl_0.jpg"
    savePath = "C:\\Users\\ASUS\\Desktop\\girl_1.jpg"
    img = cv.imread(readPath)
    img = cv.resize(img, (width, height))
    cv.imwrite(savePath, img)
    print("预处理待填充图片已完成!")

3. 思路3.代码:

# 用字典存储每一图及其直方图
def build_index():
    print("正在计算各图片直方图:")
    readPath = "C:\\Users\\ASUS\\Desktop\\data1"
    files = os.listdir(readPath)
    dist = {
     }

    for file in files:
        imgPath = readPath + "\\" + file
        img = cv.imread(imgPath)
        hist = []
        for i in range(3):
            ht = cv.calcHist([img], [i], None, [256], [0, 256])
            hist.append(ht)
        dist[file] = hist

    print("各图片直方图计算已完成!")
    return dist

4. 思路4.代码:

# 用最相近的图代替原图
def match_replace(dist):
    print("正在替换图片:")
    width, height = 10800 * n, 13900 * n
    image = cv.imread("C:\\Users\\ASUS\\Desktop\\girl_1.jpg")

    for i in range(0, height, size):
        for j in range(0, width, size):
            img = image[i:i+size, j:j+size, 0:3]

            hist = []
            for k in range(3):
                ht = cv.calcHist([img], [k], None, [256], [0, 256])
                hist.append(ht)

            sim = 0.0
            for key in dist:
                match0 = cv.compareHist(hist[0], dist[key][0], cv.HISTCMP_CORREL)
                match1 = cv.compareHist(hist[1], dist[key][1], cv.HISTCMP_CORREL)
                match2 = cv.compareHist(hist[2], dist[key][2], cv.HISTCMP_CORREL)
                match = match0 + match1 + match2

                if match > sim:
                    sim = match
                    rename = key
            image[i:i+size, j:j+size, 0:3] = cv.imread("C:\\Users\\ASUS\\Desktop\\data1\\" + rename)

    cv.imwrite("C:\\Users\\ASUS\\Desktop\\girls_0.jpg", image)
    print("图片替换已完成!")

5. 思路5.代码:

# 混合图片
def mix_image():
    print("正在融合图片:")
    image1 = cv.imread("C:\\Users\\ASUS\\Desktop\\girls_0.jpg")
    image2 = cv.imread("C:\\Users\\ASUS\\Desktop\\girl_1.jpg")
    dst = cv.addWeighted(image1, 0.2, image2, 0.8, 3)
    cv.imwrite("C:\\Users\\ASUS\\Desktop\\girls_1.jpg", dst)
    print("图片融合已完成!")

三、源代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import cv2 as cv
import os

n = 1



# 预处理填充图片
def before_handle_imgs():
    print("正在预处理填充图片:")
    readPath = "C:\\Users\\ASUS\\Desktop\\data0"
    savePath = "C:\\Users\\ASUS\\Desktop\\data1"

    files = os.listdir(readPath)

    for file in files:
        imgPath = readPath + "\\" + file
        img = cv.imread(imgPath)
        img = cv.resize(img, (160, 90))
        cv.imwrite(savePath + "\\" + file, img)
    print("预处理填充图片已完成!")


# 预处理待填充图片
def before_handle_img():
    print("正在预处理待填充图片:")
    width, height = 25600*n, 14400*n
    readPath = "C:\\Users\\ASUS\\Desktop\\img1.jpg"
    savePath = "C:\\Users\\ASUS\\Desktop\\img2.jpg"
    img = cv.imread(readPath)
    img = cv.resize(img, (width, height))
    cv.imwrite(savePath, img)
    print("预处理待填充图片已完成!")


# 用字典存储每一图及其直方图
def build_index():
    print("正在计算各图片直方图:")
    readPath = "C:\\Users\\ASUS\\Desktop\\data1"
    files = os.listdir(readPath)
    dist = {
     }

    for file in files:
        imgPath = readPath + "\\" + file
        img = cv.imread(imgPath)
        hist = []
        for i in range(3):
            ht = cv.calcHist([img], [i], None, [256], [0, 256])
            hist.append(ht)
        dist[file] = hist

    print("各图片直方图计算已完成!")
    return dist


# 用最相近的图代替原图
def match_replace(dist):
    print("正在替换图片:")
    width, height = 25600 * n, 14400 * n
    image = cv.imread("C:\\Users\\ASUS\\Desktop\\img2.jpg")

    for i in range(0, height, 90):
        for j in range(0, width, 160):
            img = image[i:i+90, j:j+160, 0:3]

            hist = []
            for k in range(3):
                ht = cv.calcHist([img], [k], None, [256], [0, 256])
                hist.append(ht)

            sim = 0.0
            for key in dist:
                match0 = cv.compareHist(hist[0], dist[key][0], cv.HISTCMP_CORREL)
                match1 = cv.compareHist(hist[1], dist[key][1], cv.HISTCMP_CORREL)
                match2 = cv.compareHist(hist[2], dist[key][2], cv.HISTCMP_CORREL)
                match = match0 + match1 + match2

                if match > sim:
                    sim = match
                    rename = key
            image[i:i+90, j:j+160, 0:3] = cv.imread("C:\\Users\\ASUS\\Desktop\\data1\\" + rename)

    cv.imwrite("C:\\Users\\ASUS\\Desktop\\img3.jpg", image)
    print("图片替换已完成!")


# 混合图片
def mix_image():
    print("正在融合图片:")
    image1 = cv.imread("C:\\Users\\ASUS\\Desktop\\img3.jpg")
    image2 = cv.imread("C:\\Users\\ASUS\\Desktop\\img2.jpg")
    dst = cv.addWeighted(image1, 0.2, image2, 0.8, 3)
    cv.imwrite("C:\\Users\\ASUS\\Desktop\\img4.jpg", dst)
    print("图片融合已完成!")


if __name__ == "__main__":
    before_handle_imgs()
    before_handle_img()
    dist = build_index()
    match_replace(dist)
    mix_image()

四、运行结果

原图:

替代后:

混合后:

细节:

码文不易,如果觉得对你有用的话,点个赞再走吧,谢谢宁!

(才疏学浅,如果有什么说的不对的地方,欢迎大家在评论区或者私信进行指正。)

你可能感兴趣的:(opencv,学习笔记,opencv,python)