Python+OpenCV4马赛克图片合成

前言

看了一篇c++通过opencv中sift算子寻找相似点然后拼接全景图片的一张文章,有点意思。寻找图片的相似特征,我好想在以前写过一篇文章吧,快速指路=>O.

想起来b站何同学做过600万粉丝名称合照的视频,属于360度全景拼接,也比较有意思,给个链接,感兴趣的看。
有点意思之后就是,我要做什么了。出门的世界经典海报,浅模仿一下吧。

在这里插入图片描述

思路

前面是图像特征点相似匹配,后者是图像色彩特征匹配。本篇文章说说后者:将目标图片划分为m * n的特征点,每张特征点足够小就可以得到一个像素单元的色彩特征,多个m * n的特征点可以构成一幅图片。

在这里插入图片描述


再将目标图片色彩平均特征点用其他图片的平均色彩特征点去替换:

在这里插入图片描述

实现

在这里插入图片描述

环境

每次都得先对环境呀,安装还是没安装,先对齐一下版本,这样可以避免无谓的摔跤。

mac os + jupyter notebook + python3.9.12 + opencv 4.6.0

pip install opencv-python
pip install opencv-contrib-python

源码

相关python运行示例:https://gitee.com/cungudafa/Python-notes

方便学习,从百度根据关键词下载图片(如果有下载的图片imread读不出来,那就删掉就好了,图片格式存的有可能不支持读取)

import requests
# 从网络获取图片(保存图片路径,图片名称,数量)
def getPicFromBaidu(imgPath,name,count):
    #进行UA伪装
    header = {
        'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
    }
    url = 'https://image.baidu.com/search/acjson?'
    param = {
        'tn': 'resultjson_com',
        'logid': '11941270206720072198',
        'ipn': 'rj',
        'ct': '201326592',
        'is': '',
        'fp': 'result',
        'queryWord': '猫',
        'cl': '2',
        'lm': '-1',
        'ie': 'utf-8',
        'oe': 'utf-8',
        'adpicid': '',
        'st': '',
        'z':'',
        'ic':'',
        'hd': '',
        'latest': '',
        'copyright': '',
        'word': '猫',
        's':'',
        'se':'',
        'tab': '',
        'width': '',
        'height': '',
        'face': '',
        'istype': '',
        'qc': '',
        'nc': '1',
        'fr': '',
        'expermode': '',
        'force': '',
        'pn': str(count),
        'rn': str(count),
        'gsm': '1e',
    }
    #将编码形式转换为utf-8
    page_text = requests.get(url=url,headers=header,params=param)
    page_text.encoding = 'utf-8'
    page_text = page_text.json()

    # 先取出所有链接所在的字典,并将其存储在一个列表当中
    info_list = page_text['data']
    # 由于利用此方式取出的字典最后一个为空,所以删除列表中最后一个元素
    del info_list[-1]
    # 定义一个存储图片地址的列表
    img_path_list = []
    for info in info_list:
        img_path_list.append(info['thumbURL'])

    #再将所有的图片地址取出,进行下载
    #n将作为图片的名字
    for i, img_path in enumerate(img_path_list):
        img_data = requests.get(url=img_path,headers=header).content        # .content获取真正的图片内容
        img_path = str(imgPath)+'cat_' + str(i+120) + '.jpg'
        with open(img_path,'wb') as fp:
            print(img_path)
            fp.write(img_data)
    print('ok')
    
folder_name = '/Users/admin/Desktop/project/python/pic/'
name = "猫猫"
count = 50
getPicFromBaidu(folder_name,name,count)

根据图片色彩内容匹配相关联的图片并拼接:

import cv2
import glob
import argparse
import matplotlib.pyplot as plt
import numpy as np
from tqdm import tqdm  # 进度条
from itertools import product  # 迭代器
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']#mac 中文


def parseArgs(tagetImg, showImg, filePath):
    parser = argparse.ArgumentParser('拼接马赛克图片')
    parser.add_argument('--targetpath', type=str,
                        default=tagetImg, help='目标图像路径')
    parser.add_argument('--outputpath', type=str,
                        default=showImg, help='输出图像的路径')
    parser.add_argument('--sourcepath', type=str,
                        default=filePath, help='用来拼接图像的所有源图像文件路径')
    parser.add_argument('--blocksize', type=int, default=40, help='马赛克快的大小')

#     args = parser.parse_args() # 其他编译器
    args = parser.parse_known_args()[0]  # jupyter 编译器

    return args


def readSourceImages(sourcepath, blocksize):
    print('开始读取图像')
    sourceimages = []  # 图像
    avgcolors = []  # 平均颜色列表
    files = []#图片路径
    for path in tqdm(glob.glob("{}/*.jpg".format(sourcepath))):
#         print(path)
        image = cv2.imread(path, cv2.IMREAD_COLOR)
        if image.shape[-1] != 3:
            continue
        # 缩放尺寸
        image = cv2.resize(image, (blocksize, blocksize))
        # 图像颜色平均值
        avgcolor = np.sum(np.sum(image, axis=0), axis=0) / \
            (blocksize * blocksize)
        sourceimages.append(image)
        avgcolors.append(avgcolor)
        files.append(path)
        
    print('结束读取')
    return sourceimages, np.array(avgcolors) ,files


def getLists(args):
    targetimage = cv2.imread(args.targetpath)
    targetimage = cv2.resize(targetimage, (1000, 1000))# 原始画布尺寸越大,渲染时间越长
    # int8 int16 int32 int64
    outputimage = np.zeros(targetimage.shape, np.uint8)
    sourceimages, avgcolors, files = readSourceImages(args.sourcepath, args.blocksize)
    
    print('开始制作')
    for i, j in tqdm(product(range(int(targetimage.shape[1]/args.blocksize)), range(int(targetimage.shape[0]/args.blocksize)))):
        block = targetimage[j * args.blocksize: (
            j + 1) * args.blocksize, i * args.blocksize: (i + 1) * args.blocksize, :]#目标单cell
        avgcolor = np.sum(np.sum(block, axis=0), axis=0) / \
            (args.blocksize * args.blocksize)#目标单cell的平均颜色
        distances = np.linalg.norm(avgcolor - avgcolors, axis=1)
        idx = np.argmin(distances)#取平均颜色最接近的值
        outputimage[j * args.blocksize: (j + 1) * args.blocksize, i * args.blocksize: (i + 1) * args.blocksize, :] = \
            sourceimages[idx]#取出符合此cell的图片
        
    cv2.imwrite(args.outputpath, outputimage)#所有cell替换原图

    plt.figure(num=1, figsize=(200, 200))
    plt.subplot(1,2,1)
    plt.xlabel("原始图片")
    plt.imshow(cv2.cvtColor(targetimage, cv2.COLOR_BGR2RGB))  # BGR转RGB
    plt.subplot(1,2,2)
    plt.xlabel("target")
    image = cv2.imread(args.outputpath, cv2.IMREAD_COLOR)
    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))  # BGR转RGB
    plt.show()
    
    
if __name__ == '__main__':
    tagetImg = 'pic/cat_55.jpg'
    showImg = '1.jpg'
    filePath = 'pic'
    getLists(parseArgs(tagetImg, showImg, filePath))
    
    getLists(parseArgs('pic/cat_30.jpg', '2.jpg', filePath))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340