OpenCV-Python graphics and image processing: making snowflakes fall special effects

☞ ░LaoYuanPython blog post directory: https://blog.csdn.net/LaoYuanPython

Insert picture description here

I. Introduction

A few days ago, a blogger asked if the effect of falling snow can be achieved in the video, the answer is yes. The old ape had a simple idea the day before yesterday. Using OpenCV-Python on the weekend, it realized the effect of adding dynamic snowflakes to the image display through the image loop display. After continuous optimization, the effect is still good. It took half a day to achieve The process is summarized and written for your reference.

2. Case background

This snowflake comes from the following picture (file name: f:\pic\snow.jpg):

The background can be any picture, the following is an image of Mount Everest (file name:) found on the Internet by the old ape f:\pic\Qomolangma2.jpg:

The sky in the background of Mount Everest is falling with snow flakes. Isn't it a good mood?

Three, realization of ideas

To realize the falling of snowflakes, a single display of a single picture is definitely not enough. It is necessary to continuously display the picture in a loop, and each time the picture is displayed, a new snowflake is generated and the position of the existing snowflake in the picture is updated. The position of each snowflake is accurately managed.

The size of snowflakes in nature is different, so in order to improve the realistic effect, it is also necessary to make the size of the snowflakes randomly change and rotate within a certain range.

The snowflakes of different sizes are constantly produced. If the snowflakes are transformed each time the snowflakes are generated, the system resources are wasted. Therefore, in order to improve the processing performance, only batches of different sizes and different rotation angles are produced at one time when the program is initialized. Plant snowflakes, when the subsequent program generates snowflakes, directly select one of the snowflakes generated in batches as the snowflake to be generated, instead of starting from the basic snowflake image every time.

Fourth, the key implementation code

4.1. Generate various snowflake shapes

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)

4.2, produce a row of snowflakes

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

4.3, merge all snowflake objects into the background image

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.4, the main function

The main function reads in the background image, initializes the snowflake shape list, and then loops to generate a row of new snowflakes from the top, and dynamically adjusts the position of all snowflake objects and merges them into the background image, looping once every 200 milliseconds until you press ESC to exit.

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

4.5. Other instructions

The execution of the program can be directly directly to the main function. In addition, this program also uses some common functions that are often used by the old ape. This part of the function includes readImgFile, addImgToLargeImg, rotationImg. For its functions, please refer to " https://blog.csdn.net/ LaoYuanPython/article/details/111351901 OpenCV-Python graphics and image processing: Introduction to some of the functions and calling syntax of some tools for personal use . According to the introduction, it is not difficult for you to implement the relevant code by yourself.

Five, the complete code of the main program and the effect of falling snowflakes

5.1, the complete code of the main program

# -*- 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()

5.2 Special effects of falling snow

Insert picture description here

Six, summary

This article introduces the realization ideas, key functions, and the complete code of the main program for making snowflakes with specific images as the background through OpenCV-Python. The special effects of falling snowflakes actually belong to the operation of image fusion. As long as you master the basic knowledge of image fusion and the implementation ideas after design, the realization is relatively fast and the effect is quite good. Combining the above code, you can also adjust the size of the snowflakes and the density of the snow.

With the introduction of the above content, it is very easy to realize the video plus snowflake special effect. As long as the key steps used in the above process are superimposed on the Moviepy audio and video processing and synthesis, it can be realized. The old monkey adjusted the code of this article slightly, and then wrote a The function of three lines of code completes the relevant processing. I believe that those who have studied Moviepy can realize it quickly. I won't introduce it here. After a while, the old ape will publish the relevant implementation in the Moviepy related column.

Pay attention to the above implementation process:

  1. Snowflake pictures are generally larger than the picture. You need to try more about how to reduce it to a suitable size. The following is the effect after only abbreviating half of the original picture.
    Insert picture description here
    It can be seen that the effect is not very satisfactory.

  2. Control the speed and amplitude of the snowflakes moving left and right and falling. Too fast, too slow, and too large or too small are not like falling snowflakes.

For more image processing introduction, please refer to the column " OpenCV-Python graphics and image processing https://blog.csdn.net/laoyuanpython/category_9979286.html " and " https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV -Python Beginners Difficult Questions Collection " related articles.

Blogging is not easy, please support:

If you have gained something from reading this article, please like, comment, and bookmark. Thank you for your support!

Paid column about the old ape

  1. The paid column " https://blog.csdn.net/laoyuanpython/category_9607725.html Using PyQt to Develop Graphical Interface Python Applications" specifically introduces the basic tutorials of Python-based PyQt graphical interface development. The corresponding article directory is " https://blog.csdn .net/LaoYuanPython/article/details/107580932 Use PyQt to develop a graphical interface Python application column directory ";
  2. The paid column " https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy audio and video development column ) details the related methods of moviepy audio and video editing and synthesis processing and the use of related methods to process related editing and synthesis scenes, corresponding to the article The directory is " https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy audio and video development column article directory ";
  3. The paid column " https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python Difficult Questions for Beginners " is " https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python graphics and image processing "The companion column" is an integration of the author’s personal perceptions of some of the problems encountered in the learning of OpenCV-Python graphics and image processing. The relevant information is basically the result of repeated research by the old ape, which helps OpenCV-Python beginners to more in-depth To understand OpenCV, the corresponding article directory is " https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python Beginners Difficult Question Collection Column Directory "
  4. The paid column " https://blog.csdn.net/laoyuanpython/category_10762553.html Introduction to Python Crawlers" introduces the content of crawler development from the perspective of an Internet front-end developer, including the basic knowledge of crawler introduction and crawling Take CSDN article information, blogger information, like articles, comments and other actual content.

The first two columns are suitable for novice readers who have a certain Python foundation but no relevant knowledge. The third column, please combine " https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python graphics and image processing " Learning to use.

For those who lack Python foundation, you can learn Python from scratch through Lao Yuan’s free column " https://blog.csdn.net/laoyuanpython/category_9831699.html column: Python basic tutorial directory ).

If you are interested and willing to support the readers of the old ape, welcome to buy the paid column.

If you have any questions about the content of the article, you can leave a message in the blog comment area, or follow: Laoyuan Python WeChat public account to send a message for consultation.
Insert picture description here

Learn Python from the old ape!

☞ ░Go to LaoYuanPython blog post directory https://blog.csdn.net/LaoYuanPython

Guess you like

Origin blog.csdn.net/LaoYuanPython/article/details/115298737