Graphiques et traitement d'images OpenCV-Python: faire tomber des flocons de neige avec des effets spéciaux

☞ ░LaoYuanPython le blog répertoire post: https://blog.csdn.net/LaoYuanPython

Insérez la description de l'image ici

Introduction

Il y a quelques jours, un blogueur a demandé si l'effet de la chute de neige pouvait être obtenu dans la vidéo, la réponse est oui. Le vieux singe a eu une idée simple avant-hier. En utilisant OpenCV-Python le week-end, il a réalisé l'effet d'ajouter des flocons de neige dynamiques à l'affichage de l'image via l'affichage de la boucle d'image. Après une optimisation continue, l'effet est toujours bon. Il a fallu une demi-journée pour y parvenir Le processus est résumé et rédigé pour votre référence.

2. Contexte de l'affaire

Ce flocon de neige provient de l'image suivante (nom de fichier:) f:\pic\snow.jpg:

L'arrière-plan peut être n'importe quelle image, ce qui suit est une image du mont Everest (nom de fichier :) trouvée sur Internet par le vieux singe f:\pic\Qomolangma2.jpg:

Le ciel en arrière-plan du mont Everest est couvert de flocons de neige, n'est-ce pas de bonne humeur?

Troisièmement, réalisation d'idées

Pour réaliser la chute de flocons de neige, un seul affichage d'une seule image n'est certainement pas suffisant. Il est nécessaire d'afficher en continu l'image en boucle, et chaque fois que l'image est affichée, un nouveau flocon de neige est généré et la position de l'existant flocon de neige dans l'image est mis à jour. La position de chaque flocon de neige est gérée avec précision.

La taille des flocons de neige dans la nature est différente, donc afin d'améliorer l'effet réaliste, il est également nécessaire de faire changer la taille des flocons de neige de manière aléatoire et de tourner dans une certaine plage.

Les flocons de neige de différentes tailles sont constamment produits. Si les flocons de neige sont transformés à chaque fois que les flocons de neige sont générés, les ressources du système sont gaspillées. Par conséquent, afin d'améliorer les performances de traitement, seuls des lots de différentes tailles et différents angles de rotation sont produits à la fois lorsque le programme est initialisé Planter des flocons de neige, lorsque le programme suivant génère des flocons de neige, sélectionnez directement l'un des flocons de neige générés par lots comme flocon de neige à générer, au lieu de lancer la transformation à partir de l'image de base du flocon de neige à chaque fois.

Quatrièmement, le code de mise en œuvre clé

4.1. Générer diverses formes de flocon de neige

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, produire une rangée de flocons de neige

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, fusionner tous les objets flocon de neige dans l'image d'arrière-plan

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, la fonction principale

La fonction principale lit l'image d'arrière-plan, initialise la liste des formes de flocon de neige, puis effectue une boucle pour générer une rangée de nouveaux flocons de neige à partir du haut, ajuste dynamiquement la position de tous les objets flocon de neige et les fusionne dans l'image d'arrière-plan, en boucle une fois tous les 200 millisecondes jusqu'à ce que vous appuyiez sur ESC pour quitter.

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. Autres instructions

L'exécution du programme peut se faire directement à la fonction principale. De plus, ce programme utilise également certaines fonctions courantes qui sont souvent utilisées par l'ancien singe. Cette partie de la fonction comprend readImgFile, addImgToLargeImg, rotationImg. Pour ses fonctions, veuillez voir " https://blog.csdn.net/ LaoYuanPython / article / details / 111351901 Graphiques et traitement d'images OpenCV-Python: Introduction à certaines des fonctions et syntaxe d'appel de certains outils à usage personnel . Selon l'introduction, il n'est pas difficile pour vous d'implémenter le code pertinent par vous-même.

Cinq, le code complet du programme principal et l'effet des flocons de neige qui tombent

5.1, le code complet du programme principal

# -*- 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 Effets spéciaux des chutes de neige

Insérez la description de l'image ici

Six, résumé

Cet article présente les idées de réalisation, les fonctions clés et le code complet du programme principal de création de flocons de neige avec des images spécifiques en arrière-plan via OpenCV-Python. Les effets spéciaux de la chute des flocons de neige appartiennent en fait à l'opération de fusion d'images. Tant que vous maîtrisez les connaissances de base de la fusion d'images et les idées de mise en œuvre après conception, la réalisation est relativement rapide et l'effet est plutôt bon. En combinant le code ci-dessus, vous pouvez également ajuster la taille des flocons de neige et la densité de la neige.

Avec l'introduction du contenu ci-dessus, il est très facile de réaliser l'effet spécial vidéo plus flocon de neige. Tant que les étapes clés utilisées dans le processus ci-dessus sont superposées au traitement et à la synthèse audio et vidéo de Moviepy, cela peut être réalisé. old monkey a légèrement ajusté le code de cet article, puis a écrit un La fonction de trois lignes de code complète le traitement pertinent. Je crois que ceux qui ont étudié Moviepy peuvent le réaliser rapidement. Je ne l'introduirai pas ici. Après un certain temps , l'ancien singe publiera l'implémentation appropriée dans la colonne relative à Moviepy.

Faites attention au processus de mise en œuvre ci-dessus:

  1. Les images de flocon de neige sont généralement plus grandes que l'image. Vous devez essayer de la réduire à une taille appropriée. Voici l'effet après avoir abrégé seulement la moitié de l'image d'origine.
    Insérez la description de l'image ici
    On voit que l'effet n'est pas très satisfaisant.

  2. Contrôlez la vitesse et l'amplitude des flocons de neige qui se déplacent à gauche et à droite et qui tombent. Trop vite, trop lentement, et trop gros ou trop petit ne sont pas comme des flocons de neige qui tombent.

Pour plus d'informations sur le traitement d'image, reportez-vous à la colonne " Graphiques et traitement d'images OpenCV-Python https://blog.csdn.net/laoyuanpython/category_9979286.html " et " https://blog.csdn.net/laoyuanpython/category_10581071 .html Articles relatifs à OpenCV -Python Débutants Difficult Questions Collection ».

Bloguer n'est pas facile, veuillez soutenir:

Si vous avez gagné quelque chose en lisant cet article, veuillez aimer, commenter et ajouter un signet. Merci pour votre soutien!

Colonne payée sur le vieux singe

  1. La colonne payante " https://blog.csdn.net/laoyuanpython/category_9607725.html Utilisation de PyQt pour développer des applications Python d'interface graphique" présente spécifiquement les didacticiels de base sur le développement d'interface graphique PyQt basée sur Python. Le répertoire d'articles correspondant est " https: //blog.csdn .net / LaoYuanPython / article / details / 107580932 Utilisez PyQt pour développer l'interface graphique Répertoire de colonnes d'application Python ";
  2. La colonne payante " https://blog.csdn.net/laoyuanpython/category_10232926.html colonne de développement audio et vidéo moviepy ) présente en détail les méthodes associées de traitement de synthèse et d'édition audio et vidéo moviepy et l'utilisation de méthodes associées pour les processus liés scènes d'édition et de synthèse, correspondant à l'article Le répertoire est " https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy audio and video development column article directory ";
  3. La colonne payante " https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python Difficult Questions for Beginners " est " https://blog.csdn.net/laoyuanpython/category_9979286.html Graphiques et image OpenCV-Python traitement "La colonne compagnon" est une intégration des perceptions personnelles de l'auteur de certains des problèmes rencontrés dans l'apprentissage des graphiques OpenCV-Python et du traitement d'image. Les informations pertinentes sont essentiellement le résultat de recherches répétées par l'ancien singe, ce qui aide OpenCV -Python débutants à plus en profondeur Pour comprendre OpenCV, le répertoire d'articles correspondant est " https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python Débutants Difficult Question Collection Column Directory "
  4. La colonne payante " https://blog.csdn.net/laoyuanpython/category_10762553.html Introduction to Python Crawler" présente le contenu du développement du robot d'exploration du point de vue d'un développeur Internet frontal, y compris les connaissances de base sur l'introduction et l'exploration de robots Prenez des informations sur les articles du CSDN, des informations sur les blogueurs, comme des articles, des commentaires et d'autres contenus réels.

Les deux premières colonnes conviennent aux lecteurs novices qui ont une certaine base Python mais aucune connaissance pertinente à apprendre. La troisième colonne, veuillez combiner " https://blog.csdn.net/laoyuanpython/category_9979286.html Graphiques et image OpenCV-Python traitement "Apprendre à utiliser.

Pour ceux qui n'ont pas de base Python, vous pouvez apprendre Python à partir de zéro grâce à la colonne gratuite de Lao Yuan " https://blog.csdn.net/laoyuanpython/category_9831699.html colonne: répertoire des didacticiels de base Python ).

Si vous êtes intéressé et disposé à soutenir les lecteurs du vieux singe, n'hésitez pas à acheter la colonne payante.

Si vous avez des questions sur le contenu de l'article, vous pouvez laisser un message dans la zone de commentaire du blog, ou suivre: Laoyuan Python WeChat compte public pour envoyer un message pour consultation.
Insérez la description de l'image ici

Apprenez Python du vieux singe!

☞ ░Go à LaoYuanPython le blog répertoire post https://blog.csdn.net/LaoYuanPython

Je suppose que tu aimes

Origine blog.csdn.net/LaoYuanPython/article/details/115298737
conseillé
Classement