前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV-Python图形图像处理:制作雪花飘落特效

OpenCV-Python图形图像处理:制作雪花飘落特效

作者头像
AI算法与图像处理
发布2021-04-21 15:12:21
9920
发布2021-04-21 15:12:21
举报

导读

Hi,大家好,今天给各位读者分享一个比较酷炫的特效。

其中汇集了很多opencv的常用操作,一套组合拳,秀的头皮发麻

来源:https://blog.csdn.net/LaoYuanPython/article/details/115298737

编辑:AI算法与图像处理

效果展示

首先看一下目标效果:

素材准备 & 思路分析

本次雪花来源于如下图片(文件名:f:\pic\snow.jpg):

背景可以是任意图片,下面是老猿在网上找到的一张珠峰图像(文件名:f:\pic\Qomolangma2.jpg):

珠峰背景的天空飘落着纷纷扬扬的雪花,意境不错吧?

实现思路

要实现雪花飘落,单张图片的单次显示肯定不够,需要不停循环显示图片,并且在每次图片显示时,生成新的雪花并更新图片中已有雪花的位置,这就需要将图片中每个雪花的位置精确管理。

自然界的雪花大小是不同的,因此为了提升逼真效果,还需要使得雪花大小在一定范围内随机变化和旋转。

不停产生大小不同的雪花,如果每次产生雪花都对雪花进行变换其实浪费了系统的资源,因此为了提升处理性能,只在程序开始初始化时一次批量生产各种不同大小、不同旋转角度的各种雪花,后续程序生成雪花时,直接从批量生成的雪花中取一个作为要生成的雪花,而不用每次从基本的雪花图像开始进行变换。

关键实现代码

1、生成各种雪花形状
代码语言:javascript
复制
def initSnowShapes():
    """
    从文件中读入雪花图片,并进行不同尺度的缩小和不同角度的旋转从而生成不同的雪花形状,这些雪花形状保存到全局列表中snowShapesList
    """
    global snowShapesList
    imgSnow = readImgFile(r'f:\pic\snow.jpg') 
    imgSnow = cv2.resize(imgSnow, None, fx=0.2, fy=0.2) #图片文件中的雪花比较大,需要缩小才能象自然的雪花形象
    minFactor,maxFactor = 50,100  #雪花大小在imgSnow的0.5-1倍之间变化

    for factor in range(minFactor,maxFactor,5): #每次增加5%大小
        f = factor*0.01
        imgSnowSize = cv2.resize(imgSnow, None, fx=f, fy=f)
        for ange in range(0,360,5):#雪花0-360之间旋转
            imgRotate = rotationImg(imgSnowSize,ange)
            snowShapesList.append(imgRotate)
2、产生一排雪花
代码语言:javascript
复制
def generateOneRowSnows(width,count):
    """
    产生一排雪花对象,每个雪花随机从snowShapesList取一个、横坐标位置随机、纵坐标初始为0
    :param width: 背景图像宽度
    :param count: 希望的雪花数
    :return:一个包含产生的多个雪花对象信息的列表,每个列表的元素代表一个雪花对象,雪花对象包含三个信息,在snowShapesList的索引号、初始x坐标、初始y坐标(才生成固定为0)
    """
    global snowShapesList
    line = []
    picCount = len(snowShapesList) 
    for loop in range(count):
        imgId = random.randint(0,picCount-1)
        xPos = random.randint(0,width-1)
        line.append((imgId,xPos,0))
    return line
3、将所有雪花对象融合到背景图像
代码语言:javascript
复制
def putSnowObjectToImg(img):
    """
    将所有snowObjects中的雪花对象融合放到图像img中,融合时y坐标随机下移一定高度,x坐标左右随机小范围内移动
    """
    global snowShapesList,snowObjects
    horizontalMaxDistance,verticalMaxDistance = 5,20 #水平方向左右漂移最大值和竖直方向下落最大值
    snowObjectCount = len(snowObjects)
    rows,cols = img.shape[0:2]
    imgResult = np.array(img)
    for index in range(snowObjectCount-1,-1,-1):
        imgObj = snowObjects[index] #每个元素为(imgId,x,y)
        if imgObj[2]>rows: #如果雪花的起始纵坐标已经超出背景图像的高度(即到达背景图像底部),则该雪花对象需进行失效处理
            del(snowObjects[index])
        else:
            imgSnow = snowShapesList[imgObj[0]]
            x,y = imgObj[1:] #取该雪花上次的位置
            x = x+random.randint(-1*horizontalMaxDistance,horizontalMaxDistance) #横坐标随机左右移动一定范围
            y = y+random.randint(1,verticalMaxDistance) #纵坐标随机下落一定范围
            snowObjects[index] = (imgObj[0],x,y) #更新雪花对象信息
            imgResult = addImgToLargeImg(imgSnow,imgResult,(x,y),180) #将所有雪花对象图像按照其位置融合到背景图像中
    return imgResult #返回融合图像
4、主函数

主函数读入背景图片,初始化雪花形状列表,然后循环自顶部产生一排新的雪花,并将所有雪花对象动态调整位置后融合到背景图像,每200毫秒循环一次,直至按ESC退出。

代码语言:javascript
复制
def main():
    global snowShapesList,snowObjects
    bg = readImgFile(r'f:\pic\Qomolangma2.jpg')
    initSnowShapes()
    rows,cols = bg.shape[:2]
    maxObjsPerRow = int(cols/100)

    while(True):
        snowObjects += generateOneRowSnows(cols,random.randint(0,maxObjsPerRow))
        result = putSnowObjectToImg(bg)
        cv2.imshow('result',result)
        ch = cv2.waitKey(200)
        if ch==27:break

主程序完整代码及雪花飘落效果

5.1、 主程序完整代码
代码语言:javascript
复制
# -*- coding: utf-8 -*-
import cv2,random
import numpy as np

from opencvPublic import addImgToLargeImg,readImgFile,rotationImg
snowShapesList = [] #雪花形状列表
snowObjects=[]  #图片中要显示的所有雪花对象


def initSnowShapes():
    """
    从文件中读入雪花图片,并进行不同尺度的缩小和不同角度的旋转从而生成不同的雪花形状,这些雪花形状保存到全局列表中snowShapesList
    """
    global snowShapesList
    imgSnow = readImgFile(r'f:\pic\snow.jpg')
    imgSnow = cv2.resize(imgSnow, None, fx=0.2, fy=0.2) #图片文件中的雪花比较大,需要缩小才能象自然的雪花形象
    minFactor,maxFactor = 50,100  #雪花大小在imgSnow的0.5-1倍之间变化

    for factor in range(minFactor,maxFactor,5): #每次增加5%大小
        f = factor*0.01
        imgSnowSize = cv2.resize(imgSnow, None, fx=f, fy=f)
        for ange in range(0,360,5):#雪花0-360之间旋转,每次旋转角度增加5°
            imgRotate = rotationImg(imgSnowSize,ange)
            snowShapesList.append(imgRotate)

def generateOneRowSnows(width,count):
    """
    产生一排雪花对象,每个雪花随机从snowShapesList取一个、横坐标位置随机、纵坐标初始为0
    :param width: 背景图像宽度
    :param count: 希望的雪花数
    :y:当前行对应的竖直坐标
    :return:一个包含产生的多个雪花对象信息的列表,每个列表的元素代表一个雪花对象,雪花对象包含三个信息,在snowShapesList的索引号、初始x坐标、初始y坐标(才生成固定为0)
    """
    global snowShapesList
    line = []
    picCount = len(snowShapesList)
    for loop in range(count):
        imgId = random.randint(0,picCount-1)
        xPos = random.randint(0,width-1)
        line.append((imgId,xPos,0))
    return line

def putSnowObjectToImg(img):
    """
    将所有snowObjects中的雪花对象融合放到图像img中,融合时y坐标随机下移一定高度,x坐标左右随机小范围内移动
    """
    global snowShapesList,snowObjects
    horizontalMaxDistance,verticalMaxDistance = 5,20 #水平方向左右漂移最大值和竖直方向下落最大值
    snowObjectCount = len(snowObjects)
    rows,cols = img.shape[0:2]
    imgResult = np.array(img)
    for index in range(snowObjectCount-1,-1,-1):
        imgObj = snowObjects[index] #每个元素为(imgId,x,y)
        if imgObj[2]>rows: #如果雪花的起始纵坐标已经超出背景图像的高度(即到达背景图像底部),则该雪花对象需进行失效处理
            del(snowObjects[index])
        else:
            imgSnow = snowShapesList[imgObj[0]]
            x,y = imgObj[1:] #取该雪花上次的位置
            x = x+random.randint(-1*horizontalMaxDistance,horizontalMaxDistance) #横坐标随机左右移动一定范围
            y = y+random.randint(1,verticalMaxDistance) #纵坐标随机下落一定范围
            snowObjects[index] = (imgObj[0],x,y) #更新雪花对象信息
            imgResult = addImgToLargeImg(imgSnow,imgResult,(x,y),180) #将所有雪花对象图像按照其位置融合到背景图像中
    return imgResult #返回融合图像


def main():
    global snowShapesList,snowObjects

    initSnowShapes()
    bg = readImgFile(r'f:\pic\Qomolangma2.jpg')
    rows,cols = bg.shape[:2]
    maxObjsPerRow = int(cols/100)

    while(True):
        snowObjects += generateOneRowSnows(cols,random.randint(0,maxObjsPerRow))
        result = putSnowObjectToImg(bg)
        cv2.imshow('result',result)
        ch = cv2.waitKey(200)
        if ch==27:break

main()

总结

本文介绍了通过OpenCV-Python以特定图像为背景制作雪花飘落特效的实现思路、关键函数功能以及主程序的完整代码。雪花飘落特效实际上属于图像融合的操作,只要掌握图像融合的基础知识以及设计后实现思路,实现起来还是比较快的,效果也挺不错。结合上面代码,大家还可以调整雪花的大小以及飘雪的密集程度。

以上实现过程需要注意:

1、雪花图片一般会比图片需要的效果大,怎么缩小到合适的大小需要多试一下,下面是才开始将原始图片只缩写一半之后的效果。

可以看到该效果就不太让人满意。

2、控制好雪花左右移动以及下落的速度和幅度,太快、太慢以及幅度过大或过小都不太象在雪花飘落。

代码语言:javascript
复制
个人微信(如果没有备注不拉群!)请注明:地区+学校/企业+研究方向+昵称


下载1:何恺明顶会分享
在「AI算法与图像处理」公众号后台回复:何恺明,即可下载。总共有6份PDF,涉及 ResNet、Mask RCNN等经典工作的总结分析
下载2:终身受益的编程指南:Google编程风格指南
在「AI算法与图像处理」公众号后台回复:c++,即可下载。历经十年考验,最权威的编程规范!

下载3 CVPR2020
在「AI算法与图像处理」公众号后台回复:CVPR2020,即可下载1467篇CVPR 2020论文
觉得不错就点亮在看吧
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI算法与图像处理 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 效果展示
  • 素材准备 & 思路分析
  • 关键实现代码
    • 1、生成各种雪花形状
      • 2、产生一排雪花
        • 3、将所有雪花对象融合到背景图像
          • 4、主函数
            • 主程序完整代码及雪花飘落效果
              • 5.1、 主程序完整代码
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档