Python generates character video

Python generates character video

1, Foreword

The video output of the Caton command line is not very good, but the effect of using the Caton command line is not good. So I intend to directly generate an mp4 character video. The general idea is the same as before: Python 20 lines of code to realize video character.

Let's take a look at an effect picture:

2, Operation image of OpenCV

Let's first look at some basic operations. First, we need to install OpenCV and execute the following statement:

pip install opencv-python

Then you can use it.

2.1 reading and display

Let's look directly at the code:

import cv2
# Read picture
img = cv2.imread("1.jpg")
# display picture
cv2.imshow("img", img)
cv2.waitKey()
cv2.destroyAllWindows()

waitKey is a function waiting for input. Because it is displayed for a moment after imshow, we need to call it. destroyAllWindows is the release window.

2.2 gray conversion

Gray conversion is to convert the picture into black-and-white picture (gray), which is convenient for us to process pixels. The code is as follows:

import cv2
img = cv2.imread("1.jpg")
# Gray conversion
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

We can also directly read in grayscale form:

import cv2
# Read in as grayscale
img = cv2.imread("1.jpg", 0)

2.4. Obtain the picture size and modify the size

Let's look directly at the code:

import cv2
img = cv2.imread("1.jpg", 0)
# Get the height and width of the picture
h, w = img.shape
# Zoom picture
res = cv2.resize(img, (w//2, h//2))

Because the shape attribute of img is a tuple, we can unpack it directly and automatically.

Then call cv2.. Resize function, the first parameter is passed into the picture, and the second parameter is passed into the modified size.

2.5. Draw text

To draw text, we need to call CV2 Puttext function, the code is as follows:

import cv2
img = cv2.imread('1.jpg')
# Draw text
cv2.putText(
    # Back drawn picture
    img, 
    # Text to draw
    'Hello',
    # Coordinates of the lower left corner of the text
    (100, 500),
    # typeface
    cv2.FONT_HERSHEY_SIMPLEX,
    # Font size scaling
    20, 
    # Text color
    (0, 0, 0),
    # Text thickness
    10
)

We just need to pay attention to these parameters.

2.6. Read video

The operation of reading video is generally general, and the code is as follows:

import cv2
# Read video
cap = cv2.VideoCapture('1.mp4')
# Gets the frame rate of the video
fps = cap.get(cv2.CAP_PROP_FPS)
# Cycle through each frame of the picture
while True:
    # Read next frame
    ret, frame = cap.read()
    if not ret:
        break
    else:
        pass
cap.release()

We need to use the frames of the video we obtained above when writing the video.

2.7. Write video

The operation of writing video is also a regular code:

import cv2
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
writer = cv2.VideoWriter('11.mp4', fourcc, fps, (w, h))
# Write video
writer.write(frame)
***
write.release()

With this knowledge, we can start the next step.

3, Mapping pixels to characters

For a picture with only one channel, we can think of it as a rectangle. The smallest unit of this rectangle is one pixel. The process of characterization is the process of replacing pixels with characters. So we have to traverse every pixel of the image, but what characters should we replace?

We have a color reference table, and opencv cuts this parameter table into 256 copies, representing different degrees. We can also make a reference table, but the content in the table is not color, but characters.

The above figure shows the color table. We can establish a mapping relationship between the color table and the character table. If the character table is as follows:

mqpka89045321@#$%^&*()_=||||}

We can get the following formula:

After transformation, the characters in the character table corresponding to the corresponding color can be obtained:

It doesn't matter if you don't understand this formula. You just need to be able to use it. Here is our code for converting pixels to characters:

def pixel2char(pixel):
    char_list = "@#$%&erytuioplkszxcv=+---.     "
    index = int(pixel / 256 * len(char_list))
    return char_list[index]

This character table can be defined by itself.

4, Generate character picture

Now we just need to convert pixels into characters one by one. The code is as follows:

def get_char_img(img, scale=4, font_size=5):
    # size pictures
    h, w = img.shape
    re_im = cv2.resize(img, (w//scale, h//scale))
    # Create a picture to fill in characters
    char_img = np.ones((h//scale*font_size, w//scale*font_size), dtype=np.uint8)*255
    font = cv2.FONT_HERSHEY_SIMPLEX
    # Traverse picture pixels
    for y in range(0, re_im.shape[0]):
        for x in range(0, re_im.shape[1]):
            char_pixel = pixel2char(re_im[y][x])
            cv2.putText(char_img, char_pixel, (x*font_size, y*font_size), font, 0.5, (0, 0, 0))
    return char_img

Here we use an NP The ones function, whose function we understand as generating a black picture.

How can we multiply the generated size by font instead of scale_ size. Scale is the reduction of the original image. Because there are many pixels, we need to reduce the image first. In order to make our font display clearer, we need to enlarge the generated character image.

Therefore, it should be noted that although the image we generated looks monotonous, when font_ When the size is set to 5, the image obtained is already relatively large. Therefore, when you generate long-time videos, it will take more time and generate large videos.

Let's test the above function:

import cv2
import numpy as np


def pixel2char(pixel):
    char_list = "@#$%&erytuioplkszxcv=+---.     "
    index = int(pixel / 256 * len(char_list))
    return char_list[index]


def get_char_img(img, scale=4, font_size=5):
    # size pictures
    h, w = img.shape
    re_im = cv2.resize(img, (w//scale, h//scale))
    # Create a picture to fill in characters
    char_img = np.ones((h//scale*font_size, w//scale*font_size), dtype=np.uint8)*255
    font = cv2.FONT_HERSHEY_SIMPLEX
    # Traverse picture pixels
    for y in range(0, re_im.shape[0]):
        for x in range(0, re_im.shape[1]):
            char_pixel = pixel2char(re_im[y][x])
            cv2.putText(char_img, char_pixel, (x*font_size, y*font_size), font, 0.5, (0, 0, 0))
    return char_img


if __name__ == '__main__':
    img = cv2.imread('dl.jpg', 0)
    res = get_char_img(img)
    cv2.imwrite('d.jpg', res)

The effect is as follows:

You can see that the effect is still very good.

5, Generate character video

With the above code, we can convert the whole video. The code for converting video into character video is as follows:

def generate(input_video, output_video):
    # 1. Read video
    cap = cv2.VideoCapture(input_video)

    # 2. Get video frame rate
    fps = cap.get(cv2.CAP_PROP_FPS)

    # Read the first frame and obtain the size of the picture converted into characters
    ret, frame = cap.read()
    char_img = get_char_img(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), 4)

    # Create a VideoWriter to save videos
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    writer = cv2.VideoWriter(output_video, fourcc, fps, (char_img.shape[1], char_img.shape[0]))
    while ret:
        # Read the current frame of the video. If not, jump out of the loop
        ret, frame = cap.read()
        if not ret:
            break
        # Convert the current frame into a character graph
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        char_img = get_char_img(gray, 4)

        # Convert to BGR mode for easy video writing
        char_img = cv2.cvtColor(char_img, cv2.COLOR_GRAY2BGR)
        writer.write(char_img)
    writer.release()

The following is a character video clip of the classic battle of Kakashi:

The complete code is as follows:

import cv2
import numpy as np


def pixel2char(pixel):
    char_list = "@#$%&erytuioplkszxcv=+---.     "
    index = int(pixel / 256 * len(char_list))
    return char_list[index]


def get_char_img(img, scale=4, font_size=5):
    # size pictures
    h, w = img.shape
    re_im = cv2.resize(img, (w//scale, h//scale))
    # Create a picture to fill in characters
    char_img = np.ones((h//scale*font_size, w//scale*font_size), dtype=np.uint8)*255
    font = cv2.FONT_HERSHEY_SIMPLEX
    # Traverse picture pixels
    for y in range(0, re_im.shape[0]):
        for x in range(0, re_im.shape[1]):
            char_pixel = pixel2char(re_im[y][x])
            cv2.putText(char_img, char_pixel, (x*font_size, y*font_size), font, 0.5, (0, 0, 0))
    return char_img


def generate(input_video, output_video):
    # 1. Read video
    cap = cv2.VideoCapture(input_video)

    # 2. Get video frame rate
    fps = cap.get(cv2.CAP_PROP_FPS)

    # Read the first frame and obtain the size of the picture converted into characters
    ret, frame = cap.read()
    char_img = get_char_img(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), 4)

    # Create a VideoWriter to save videos
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    writer = cv2.VideoWriter(output_video, fourcc, fps, (char_img.shape[1], char_img.shape[0]))
    while ret:
        # Read the current frame of the video. If not, jump out of the loop
        ret, frame = cap.read()
        if not ret:
            break
        # Convert the current frame into a character graph
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        char_img = get_char_img(gray, 4)

        # Convert to BGR mode for easy video writing
        char_img = cv2.cvtColor(char_img, cv2.COLOR_GRAY2BGR)
        writer.write(char_img)
    writer.release()


if __name__ == '__main__':
    generate('in.mp4', 'out.mp4')

We just need to modify the parameters of generate. The full effect video is as follows:

Python generated character video - Kakashi VS tape

Keywords: Python OpenCV Computer Vision

Added by Master Zen on Thu, 10 Feb 2022 19:51:02 +0200