前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python图片合成

python图片合成

作者头像
py3study
发布2020-01-10 11:26:51
2.2K0
发布2020-01-10 11:26:51
举报
文章被收录于专栏:python3python3

python的PIL库简直好用的不得了,PIL下面的Image库更是封装了很多对图片处理的函数,关于Image库的介绍和使用,看这里:http://effbot.org/imagingbook/image.htm

这里用我半个月前看到的一篇博客写的demo作为背景,做一下图片的合成

图片可以看作是很多像素点组成的,每个像素点都是一个RGB颜色,(red, green, blue), 那么合成两张照片就有办法了,我们可以在一张新的RGB色的图片里一个像素点取图片一的对应位置的像素,下一个像素点取图片二的像素,直到遍历完成,代码如下:

代码语言:javascript
复制
from PIL import Image

##这里采用传入图片地址调用此函数

#这个方法目前不支持按比例合成,默认为1:1
#各取一个像素点合并,传入的参数为两张图片的地址
def merge1(img1_address,img2_addess):
    status=100
    #状态码100为正常
    #      200为地址错误
    try:
        img1=Image.open(img1_address)
        img2=Image.open(img2_address)
    except:
        status=200
        img_new=""
    else:
        width=min(img1.size[0],img2.size[0])
        height=min(img1.size[1],img2.size[1])
        print(width,height)
        img_new = Image.new('RGB',(width,height))
        for x in range(width):
            for y in range(height):
                if y%2==0:
                    pixel=img1.getpixel((x,y))
                    img_new.putpixel((x,y),pixel)
                else:
                    pixel=img2.getpixel((x,y))
                    img_new.putpixel((x,y),pixel)
    finally:
        return img_new,status

上述代码会返回一张新的图片和一个状态码,接受的时候用两个变量接受

另一种方法是每个像素点各取%50的原图片的颜色,然后把像素点放置在对应位置,为了功能更加强大,我把两者的混合比例设为可调,默认是50%的比例,代码如下:

代码语言:javascript
复制
from PIL import Image

#将像素点按比例取色,然后合成一个新像素点
#传入的参数为两张图片的地址和比例
#如果两者之和不为1则以第一个图片的比例为准
def merge2(img1_address,img2_address,percent1=0.50,percent2=0.50):
    status=100
    #状态码100为正常
    #      200为地址错误
    try:
        img1=Image.open(img1_address)
        img2=Image.open(img2_address)
    except:
        status=200
        img_new=""
    else:
        if percent1+percent2!=1:
            percent2=1-percent1
        width = min(img1.size[0],img2.size[0])
        height = min(img1.size[1],img2.size[1])
        img_new = Image.new('RGB',(width,height))
        for x in range(width):
            for y in range(height):
                r1,g1,b1=img1.getpixel((x,y))
                r2,g2,b2=img2.getpixel((x,y))
                r=int(percent1*r1+percent2*r2)
                g=int(percent1*g1+percent2*g2)
                b=int(percent1*b1+percent2*b2)
                img_new.putpixel((x,y),(r,g,b))
    finally:
        return img_new,status

返回的参数与上述相同 如果想要保存图片可用image.save()函数保存

总的代码如下:

代码语言:javascript
复制
from PIL import Image

##这里采用传入图片地址调用此函数

#这个方法目前不支持按比例合成,默认为1:1
#各取一个像素点合并,传入的参数为两张图片的地址
def merge1(img1_address, img2_addess, direct):
    status=100
    #状态码100为正常
    #      200为地址错误
    try:
        img1=Image.open(img1_address)
        img2=Image.open(img2_address)
    except:
        status=200
        img_new=""
    else:
        width=min(img1.size[0], img2.size[0])
        height=min(img1.size[1], img2.size[1])
        print(width,height)
        img_new = Image.new('RGB',(width, height))
        for x in range(width):
            for y in range(height):
                if y%2 == 0:
                    pixel = img1.getpixel((x,y))
                    img_new.putpixel((x,y), pixel)
                else:
                    pixel = img2.getpixel((x,y))
                    img_new.putpixel((x,y), pixel)
    finally:
        return status

#将像素点按比例取色,然后合成一个新像素点
#传入的参数为两张图片的地址和比例
#如果两者之和不为1则以第一个图片的比例为准
def merge2(img1_address, img2_address, direction, percent1):

    status = 100
    #状态码100为正常
    #   200为地址错误
    try:
        img1 = Image.open(img1_address)
        img2 = Image.open(img2_address)
    except:
        status = 200
        img_new = ""
    else:
        percent2 = 1 - percent1
        width = min(img1.size[0], img2.size[0])
        height = min(img1.size[1], img2.size[1])
        img_new = Image.new('RGB', (width,height))
        for x in range(width):
            for y in range(height):
                r1,g1,b1=img1.getpixel((x,y))
                r2,g2,b2=img2.getpixel((x,y))
                r = int(percent1 * r1 + percent2 * r2)
                g = int(percent1 * g1 +percent2 * g2)
                b = int(percent1 * b1 +percent2 * b2)
                img_new.putpixel((x,y),(r,g,b))
        img_new.save(direction)
        #img_new.show()
    finally:
        return status
    #切记在接受返回信息时先判断状态码是否异常,如果正确再执行相应操作
if __name__=='__main__':

    img1_address = "B:\Picture\YourName\1.jpg"
    img2_address = "B:\Picture\YourName\2.jpg"
    direction = "D:/Python/PyQt/课程设计/merges/merge9.png"
    status = merge2(img1_address, img2_address, direction, 0.30)
    print(status)

当然,我发现Image库中有Image.blend(image1, image2, alpha)这个混合图片的函数,还没看源码,不知道他是用什么方法实现的。

原先的两张照片:

这里写图片描述
这里写图片描述

合成后的照片:

这里写图片描述
这里写图片描述

左图是方法一,右图是方法二

优劣: 方法一不易造成曝光过度,因为实际的像素点并没改动,只是间隔变大了,但这样可能会造成轮廓不清晰 方法二在比例适当时效果是优于方式一的,但比例不合适就会看起来像曝光过度一样,示例中方法二用的比例是0.3:0.7,又是比例不当效果会很糟糕,孰优孰劣请按效果好坏使用。

找时间我会分析一下Image中blend的源码,到时候会更新在博客上。 2017.12.13更新: Image库中的blend函数确实出色,前几天做课设看到知乎上的一段代码有人用过它,简直就是一个滤镜一样,找时间一定看看它的源码。

这个功能就当是课设中的一个小demo,到时候会集成在一起。

其实很想知道参考博客中那个示例中的妹子照片是不是他的女朋友,好漂亮!!!可惜我还没有女朋友(⊙﹏⊙)。

2017.12.22更新: 最近还在忙课设,看了一下PIL.Image中的blend函数,结果它是写在PIL._imaging.cp35-win_amd64.pyd中的,这个是二进制文件,要看源代码的话只能反编译。

参考: http://www.cnblogs.com/ThrEcho/p/4979193.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图片处理
图片处理(Image Processing,IP)是由腾讯云数据万象提供的丰富的图片处理服务,广泛应用于腾讯内部各产品。支持对腾讯云对象存储 COS 或第三方源的图片进行处理,提供基础处理能力(图片裁剪、转格式、缩放、打水印等)、图片瘦身能力(Guetzli 压缩、AVIF 转码压缩)、盲水印版权保护能力,同时支持先进的图像 AI 功能(图像增强、图像标签、图像评分、图像修复、商品抠图等),满足多种业务场景下的图片处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档