0
\$\begingroup\$

This is a Python script that I wrote completely by myself. Basically it scans a giant picture to make a video.

They say one picture is worth more than a thousand words. Since a video contains thousands of pictures, a video is worth more than millions of words, so I will let the video outputs do the descriptions for me (because I am not a native speaker of English and I can't even describe the process in my native language or any natural language for that matter, but I can describe it in code).

vertical image

Vertical video (Google Drive)

horizontal image

Horizontal video Output (Google Drive)

For more context, see this question.

The code:

import cv2
import numpy as np
from fractions import Fraction
from pathlib import Path

def resize_guide(image_size, target_area):
    aspect_ratio = Fraction(*image_size).limit_denominator()
    horizontal = aspect_ratio.numerator
    vertical = aspect_ratio.denominator
    unit_length = (target_area/(horizontal*vertical))**.5
    return (int(horizontal*unit_length), int(vertical*unit_length))

fourcc = cv2.VideoWriter_fourcc(*'mp4v')
FRAME = np.zeros((1080, 1920, 3), dtype=np.uint8)

def new_frame():
    return np.ndarray.copy(FRAME)

def center(image):
    frame = new_frame()
    h, w = image.shape[:2]
    yoff = round((1080-h)/2)
    xoff = round((1920-w)/2)
    frame[yoff:yoff+h, xoff:xoff+w] = image
    return frame

def image_scanning(file, fps=60, pan_increment=64, horizontal_increment=8, vertical_increment=24):
    image = cv2.imread(file)
    height, width = image.shape[:2]
    if width < 1920:
        frame = np.zeros([height, 1920, 3], dtype=np.uint8)
        frame[0:height, 0:width] = image
        image = frame
        width = 1920
    assert width*height >= 1920*1080
    video_writer = cv2.VideoWriter(file+'.mp4', fourcc, fps, (1920, 1080))
    fit_height = True
    if height < 1080:
        width = width*1080/height
        image = cv2.resize(image, (width, 1080), interpolation = cv2.INTER_AREA)
    aspect_ratio = width / height
    not_thin = False
    if 4/9 <= aspect_ratio <= 16/9:
        new_width = round(width*1080/height)
        fit = cv2.resize(image, (new_width, 1080), interpolation = cv2.INTER_AREA)
        not_thin = True
    
    elif 16/9 < aspect_ratio <= 32/9:
        new_height = round(height*1920/width)
        fit = cv2.resize(image, (1920, new_height), interpolation = cv2.INTER_AREA)
        fit_height = False
        not_thin = True
    
    if not_thin:
        centered = center(fit)
        for i in range(fps):
            video_writer.write(centered)
        if fit_height:
            xoff = round((1920 - new_width)/2)
            while xoff:
                if xoff - pan_increment >= 0:
                    xoff -= pan_increment
                else:
                    xoff = 0
                frame = new_frame()
                frame[0:1080, xoff:xoff+new_width] = fit
                video_writer.write(frame)
        else:
            yoff = round((1080 - new_height)/2)
            while yoff:
                if yoff - pan_increment >= 0:
                    yoff -= pan_increment
                else:
                    yoff = 0
                frame = new_frame()
                frame[yoff:yoff+new_height, 0:1920] = fit
                video_writer.write(frame)
    
    if not_thin:
        if fit_height:
            width_1, height_1 = new_width, 1080
        else:
            width_1, height_1 = 1920, new_height
        new_area = width_1 * height_1
        original_area = width * height
        area_diff = original_area - new_area
        unit_diff = area_diff / fps
        for i in range(1, fps+1):
            zoomed = cv2.resize(image, resize_guide((width_1, height_1), new_area+unit_diff*i), interpolation=cv2.INTER_AREA)
            zheight, zwidth = zoomed.shape[:2]
            zheight = min(zheight, 1080)
            zwidth = min(zwidth, 1920)
            frame = new_frame()
            frame[0:zheight, 0:zwidth] = zoomed[0:zheight, 0:zwidth]
            video_writer.write(frame)
    
    if (width - 1920) % horizontal_increment:
        new_width = ((width - 1920) // horizontal_increment + 1) * horizontal_increment + 1920
        frame = np.zeros([height, new_width, 3], dtype=np.uint8)
        frame[0:height, 0:width] = image
        width = new_width
        image = frame
    
    if not_thin:
        if height % 1080:
            new_height = (height // 1080 + 1) * 1080 + 8
            frame = np.zeros([new_height, width, 3], dtype=np.uint8)
            frame[0:height, 0:width] = image
            height = new_height - 8
            image = frame
        
        y, x = 0, 0
        for y in range(0, height, 1080):
            for x in range(0, width-1920, horizontal_increment):
                frame = image[y:y+1080, x:x+1920]
                video_writer.write(frame)
            x = width - 1920
            frame = image[y:y+1080, x:x+1920]
            for i in range(round(fps/3)):
                video_writer.write(frame)
    
    else:
        if (height - 1080) % vertical_increment:
            new_height = ((height - 1080) // vertical_increment + 1) * vertical_increment + 1088
            frame = np.zeros([new_height, width, 3], dtype=np.uint8)
            frame[0:height, 0:width] = image
            height = new_height - 8
            image = frame
        
        y, x = 0, 0
        for y in range(0, height-1080, vertical_increment):
            for x in range(0, width-1920, vertical_increment):
                frame = image[y:y+1080, x:x+1920]
                video_writer.write(frame)
            x = width - 1920
            frame = image[y:y+1080, x:x+1920]
            for i in range(round(fps/3)):
                video_writer.write(frame)
        y = height - 1080
        for x in range(0, width-1920, vertical_increment):
            frame = image[y:y+1080, x:x+1920]
            video_writer.write(frame)
            x = width - 1920
            frame = image[y:y+1080, x:x+1920]
            for i in range(round(fps/3)):
                video_writer.write(frame)
    cv2.destroyAllWindows()
    video_writer.release()
    del video_writer

It is in need of refactoring.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ All criticism is welcome as long as it is constructive, because your criticism points out what I did wrong, so that I will not make the same mistake next time, and that's how I improve. \$\endgroup\$ Apr 27, 2022 at 7:42
  • 4
    \$\begingroup\$ A warning. You say most if not all questions posted by my previous Stack Overflow accounts were downvoted and/or closed, and the accounts eventually got blocked from asking questions. I encourage you to read the official guidance on sockpuppet accounts. If you make a new account to circumvent post restrictions on your old account, that constitutes abuse. \$\endgroup\$
    – Reinderien
    Apr 27, 2022 at 15:21

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.