Chinese new year, firecrackers set off, the atmosphere is in place! 100 lines of Python code to make dynamic firecrackers

Respect original copyright: https://www.gewuweb.com/hot/17874.html

Chinese new year, firecrackers set off, the atmosphere is in place! 100 lines of Python code to make dynamic firecrackers

Write 0 first

Setting off firecrackers to celebrate the Spring Festival has a history of more than 2000 years in China. There is an interesting legend about the origin of firecrackers.

In the west, there are mountains, more than feet long, one foot, and the nature is not afraid of people. The crime was so cold and hot that it was called Nian Jing'an. Later generations took its shape and used gunpowder—— "Supernatural Sutra"

At first, people burned bamboo and exploded in order to scare away mandrills that harmed people. It is said that mandrills are most afraid of fire and sound, so every new year's Eve, people "burn bamboo and explode" to scare mandrills away. In this way, year after year, the custom of setting off firecrackers, lighting red candles, beating gongs and drums to celebrate the new year has formed.

New year's new weather, today we use the code to make a dynamic firecracker. The effect is as follows.

The basic principle of dynamic firecracker is to reproduce a recorded firecracker video in the form of character painting. The basic steps are frame sampling → frame by frame conversion to character painting → character painting synthesis video. Let's start now!

1 video frame sampling

The function is as follows. The main function is to save the video image stream frame by frame to a specific cache folder (it will be created automatically if the folder does not exist). The function input vp is the openCV video handle, and the output number is the number of converted pictures.

def video2Pic(vp):
    number = 0
    if vp.isOpened():
        r,frame = vp.read()
        if not os.path.exists('cachePic'):
            os.mkdir('cachePic')
        os.chdir('cachePic')
    else:
        r = False
    while r:
        number += 1
        cv2.imwrite(str(number)+'.jpg',frame)
        r,frame = vp.read()
    os.chdir("..")
    return number

2 convert picture to character picture

2.1 create pixel character index

Function inputs the RGBA value of the pixel and outputs the corresponding character code. The principle is that the characters are evenly distributed in the whole gray range, and the pixel gray value corresponds to which character code in which interval. The character code can refer to ASCII code

ASCII code uses the specified 7-bit or 8-bit binary array combination to represent 128 or 256 possible characters. Standard ascii code, also known as basic ASCII code, uses 7
Bit binary number (the remaining 1 bit binary is 0) to represent all uppercase and lowercase letters, and the number 0
To 9, punctuation, and special control characters used in American English. Among them, 0 ~ 31 and 127 (33 in total) are control characters or special characters for communication (the rest are displayable characters), such as control characters: LF (line feed), CR (enter), FF (page feed), DEL (delete), BS (backspace), BEL (ring), etc; Special characters for communication: SOH (text beginning), EOT (text end), ACK (confirmation), etc; ASCII values are 8, 9, 10
And 13 are converted to backspace, tab, line feed, and carriage return characters, respectively. They have no specific graphic display, but they will have different effects on text display according to different applications.

RGBA is the color space representing red, green, blue and alpha. Alpha channel is generally used as opacity parameter. If the alpha channel value of a pixel is 0%, it is completely transparent, while a value of 100% means a completely opaque pixel (traditional digital image). gray=0.2126

  • r + 0.7152 * g + 0.0722 * b is the empirical formula for converting RGB to gray value, and human eyes are more sensitive to green.

    def color2Char(r,g,b,alpha = 256):
    imgChar= list("#RMNHQODBWGPZ*@$C&98?32I1>!:-;. ")
    if alpha:
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
    unit = 256 / len(imgChar)
    return imgChar[int(gray / unit)]
    else:
    return ''

2.2 convert pictures to characters pixel by pixel

The core code is as follows, traversing each pixel of the picture

    img = Image.open(imagePath).convert('RGB').resize((imgWidth, imgHeight),Image.NEAREST)
    for i in range(imgHeight):
        for j in range(imgWidth):
            pixel = img.getpixel((j, i))
            color.append((pixel[0],pixel[1],pixel[2]))
            txt = txt + color2Char(pixel[0], pixel[1], pixel[2], pixel[3]) if len(pixel) == 4 else \
                  txt + color2Char(pixel[0], pixel[1], pixel[2]) 
        txt += '\n'
        color.append((255,255,255))

3 synthesize character images into video

The input parameter vp is the openCV video handle, number is the number of frames, savePath is the video saving path, and MP42 in the function
It is an encoding method that can generate smaller and smaller video files. Other similar methods include isom, mp41, avc1, qt, etc., indicating which format is "best" to parse the current file.

def img2Video(vp, number, savePath):
    videoFourcc = VideoWriter_fourcc(*"MP42")  # Set up video encoder
    asciiImgPathList = ['cacheChar' + r'/{}.jpg'.format(i) for i in range(1, number + 1)]
    asciiImgTemp = Image.open(asciiImgPathList[1]).size
    videoWritter= VideoWriter(savePath, videoFourcc, vp.get(cv2.CAP_PROP_FPS), asciiImgTemp)
    for imagePath in asciiImgPathList:
        videoWritter.write(cv2.imread(imagePath))
    videoWritter.release()

4 complete code

import cv2 
from PIL import Image,ImageFont,ImageDraw
import os
from cv2 import VideoWriter, VideoWriter_fourcc
'''
* @breif: Convert pixel colors to ASCII character
* @param[in]: pixel RGBA value
* @retval: character
'''
def color2Char(r,g,b,alpha = 256):
    imgChar = list("#RMNHQODBWGPZ*@$C&98?32I1>!:-;. ")
    if alpha:
      gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
      unit = 256 / len(imgChar)
      return imgChar[int(gray / unit)]
    else:
      return ''
 
'''
* @breif: Convert video frame by frame to picture
* @param[in]: vp -> openCV Video handle
* @retval: number -> Number of pictures converted
'''
def video2Pic(vp):
    number = 0
    if vp.isOpened():
        r,frame = vp.read()
        if not os.path.exists('cachePic'):
            os.mkdir('cachePic')
        os.chdir('cachePic')
    else:
        r = False
    while r:
        number += 1
        cv2.imwrite(str(number)+'.jpg',frame)
        r,frame = vp.read()
    os.chdir("..")
    return number
 
'''
* @breif: Convert pictures pixel by pixel to ASCII character
* @param[in]: imagePath -> Picture path
* @param[in]: index -> Picture index
* @retval: None
'''
def img2Char(imagePath, index):
    # initialization
    txt, color, font = '', [], ImageFont.load_default().font
    imgWidth, imgHeight = Image.open(imagePath).size
    asciiImg = Image.new("RGB",(imgWidth, imgHeight), (255,255,255))
    drawPtr = ImageDraw.Draw(asciiImg)
    imgWidth, imgHeight = int(imgWidth / 6), int(imgHeight / 15)
    # Convert the image frame pixel by pixel into ASCII characters and record the RGB value
    img = Image.open(imagePath).convert('RGB').resize((imgWidth, imgHeight),Image.NEAREST)
    for i in range(imgHeight):
        for j in range(imgWidth):
            pixel = img.getpixel((j, i))
            color.append((pixel[0],pixel[1],pixel[2]))
            txt = txt + color2Char(pixel[0], pixel[1], pixel[2], pixel[3]) if len(pixel) == 4 else \
                  txt + color2Char(pixel[0], pixel[1], pixel[2]) 
        txt += '\n'
        color.append((255,255,255))
    
    # Draw ASCII characters and save
    x, y = 0,0
    fontW, fontH = font.getsize(txt[1])
    fontH *= 1.37
    for i in range(len(txt)):
        if(txt[i]=='\n'):
            x += fontH
            y = -fontW
        drawPtr.text((y,x), txt[i], fill=color[i])
        y += fontW
    os.chdir('cacheChar')
    asciiImg.save(str(index)+'.jpg')
    os.chdir("..")
'''
* @breif: Convert video to ASCII Image set
* @param[in]: number -> Number of frames
* @retval: None
''' 
def video2Char(number):
    if not os.path.exists('cacheChar'):
        os.mkdir('cacheChar')
    img_path_list = ['cachePic' + r'/{}.jpg'.format(i) for i in range(1, number + 1)] 
    task = 0
    for imagePath in img_path_list:
        task += 1
        img2Char(imagePath, task)
'''
* @breif: Synthesize images into video
* @param[in]: vp -> openCV Video handle
* @param[in]: number -> Number of frames
* @param[in]: savePath -> Video save path
* @retval: None
'''  
def img2Video(vp, number, savePath):
    videoFourcc = VideoWriter_fourcc(*"MP42")  # Set video encoder
    asciiImgPathList = ['cacheChar' + r'/{}.jpg'.format(i) for i in range(1, number + 1)]
    asciiImgTemp = Image.open(asciiImgPathList[1]).size
    videoWritter= VideoWriter(savePath, videoFourcc, vp.get(cv2.CAP_PROP_FPS), asciiImgTemp)
    for imagePath in asciiImgPathList:
        videoWritter.write(cv2.imread(imagePath))
    videoWritter.release()
    
if __name__ == '__main__': 
  videoPath = 'test.mp4'
  savePath = 'new.avi'
  vp = cv2.VideoCapture(videoPath)
  number = video2Pic(vp)
  video2Char(number)
  img2Video(vp, number, savePath)
  vp.release()

last

There is always a windy morning, a warm afternoon, a brilliant evening, a meteor night, and someone praying that all the beauty in the world belongs to you! I wish you a happy year of the tiger and everything you want!

For more information: https://www.gewuweb.com/sitemap.html

Posted by lokesh_kumar_s on Wed, 11 May 2022 04:15:07 +0300