【视频图片生成素描并重新合成】

一短好玩的代码,视频图片转素描图片视频

使用的工具

1、Pycharm python3.8
2、图片类 PIL numpy ffmepg
3、视频提取音频 moviepy
4、视频转图片 cv2
5、音视频合成 subprocess

图片转素描

from PIL import Image
import numpy as np
import os
import time

for i in range(0, len(os.listdir('./image1'))):
    img = os.listdir('./image1')[i]
    img_number = img.split('.')[0]
    a = np.asarray(Image.open("./image1/%s" % img).convert('L')).astype('float')
    time.sleep(0.5)
    depth = 10.  # (0-100)
    grad = np.gradient(a)  # 取图像灰度的梯度值
    grad_x, grad_y = grad  # 分别取横纵图像梯度值
    grad_x = grad_x * depth / 100.
    grad_y = grad_y * depth / 100.
    A = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1.)
    uni_x = grad_x / A
    uni_y = grad_y / A
    uni_z = 1. / A

    vec_el = np.pi / 2.2  # 光源的俯视角度,弧度值
    vec_az = np.pi / 4.  # 光源的方位角度,弧度值
    dx = np.cos(vec_el) * np.cos(vec_az)  # 光源对x 轴的影响
    dy = np.cos(vec_el) * np.sin(vec_az)  # 光源对y 轴的影响
    dz = np.sin(vec_el)  # 光源对z 轴的影响

    b = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)  # 光源归一化
    b = b.clip(0, 255)

    im = Image.fromarray(b.astype('uint8'))  # 重构图像
    im.save(f"./img1/{
      
      img_number}.jpg")
print("保存成功,请到D:/Python/目录下查看")

视频提取音频

from moviepy.editor import *

"""
extensions_dict = { "mp4":  {'type':'video', 'codec':['libx264','libmpeg4', 'aac']},
                    'ogv':  {'type':'video', 'codec':['libtheora']},
                    'webm': {'type':'video', 'codec':['libvpx']},
                    'avi':  {'type':'video'},
                    'mov':  {'type':'video'},

                    'ogg':  {'type':'audio', 'codec':['libvorbis']},
                    'mp3':  {'type':'audio', 'codec':['libmp3lame']},
                    'wav':  {'type':'audio', 'codec':['pcm_s16le', 'pcm_s24le', 'pcm_s32le']},
                    'm4a':  {'type':'audio', 'codec':['libfdk_aac']}
                  }
"""
path = r'C:\Users\admin\Desktop\interface1\test_case\douying\video\下载.mp4'
path = eval(repr(path).replace('\\', '/'))
video = VideoFileClip(path)
audio = video.audio
path_img, path_sound = './%s/img' % path.split('/')[-1].split('.')[0], './%s/sound' % path.split('/')[-1].split('.')[0]
if os.path.exists(path_img) == False:
    os.makedirs(path_img)

if os.path.exists(path_sound) == False:
    os.makedirs(path_sound)

path_sound_mp3 = path_sound + "/" + path.split('/')[-1].split('.')[0] + '.mp3'
print(path_sound_mp3)

视频转图片

import cv2

vc = cv2.VideoCapture('./video/艾尔登法环.mp4')  # 读入视频文件
c = 0
rval = vc.isOpened()
# timeF = 1  #视频帧计数间隔频率
while rval:  # 循环读取视频帧
    c = c + 1
    rval, frame = vc.read()
    #    if(c%timeF == 0): #每隔timeF帧进行存储操作
    #        cv2.imwrite('smallVideo/smallVideo'+str(c) + '.jpg', frame) #存储为图像
    if rval:
        # img为当前目录下新建的文件夹
        cv2.imwrite('./image1/' + str(c) + '.jpg', frame)  # 存储为图像
        cv2.waitKey(1)
    else:
        break
vc.release()
print("完成")

图片转视频

import os
import re

from PIL import Image
import cv2

"""
'M', 'J', 'P', 'G' = avi
'M', 'P', '4', 'V' = mp4
"""
if __name__ == '__main__':
    ims_folder = './image1'
    video_path = './out_video_艾尔登法环.mp4'

    ims_path_list = os.listdir(ims_folder)
    ims_path_list.sort()
    fps = 30
    im_path = os.path.join(ims_folder, ims_path_list[0])

    def tryint(s):  # 将元素中的数字转换为int后再排序
        try:
            return int(s)

        except ValueError:
            return s


    def str2int(v_str):  # 将元素中的字符串和数字分割开
        return [tryint(sub_str) for sub_str in re.split('([0-9]+)', v_str)]


    def sort_humanly(v_list):  # 以分割后的list为单位进行排序
        return sorted(v_list, key=str2int)


    wk = sort_humanly(ims_path_list)

    im_size = Image.open(os.path.join(ims_folder, wk[0])).size
    # fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
    fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', 'V')
    videoWriter = cv2.VideoWriter(video_path, fourcc, fps, im_size)

    for i, im_path in enumerate(wk):
        im_path = os.path.join(ims_folder, im_path)
        frame = cv2.imread(im_path)
        videoWriter.write(frame)
        print(im_path)
    videoWriter.release()
    print('finish')
import cv2
import glob

fps = 20  # 保存视频的FPS,可以适当调整

#可以用(*'DVIX')或(*'X264'),如果都不行先装ffmepg: sudo apt-get install ffmepg
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
#saveVideo.avi是要生成的视频名称,(384,288)是图片尺寸
videoWriter = cv2.VideoWriter('saveVideo111.avi', fourcc, fps, (384, 288))  # 括号可能是中文的,改一下,384,288需要改成你的图片尺寸,不然会报错
#imge存放图片
imgs = glob.glob('imge/*.jpg')
for imgname in imgs:
    frame = cv2.imread(imgname)
    videoWriter.write(frame)
    videoWriter.release()

音视频合成

import subprocess


def video_add_mp3(file_name, mp3_file):
    """

    视频添加音频

    :param file_name: 传入视频文件的路径

    :param mp3_file: 传入音频文件的路径

    :return:

    """

    outfile_name = file_name.split('/')[2].split('.')[0] + '.mp4'
    print(file_name.split('/'))
    print(file_name.split('/')[2])
    print(file_name.split('/')[2].split('.'))
    print(file_name.split('/')[2].split('.')[0])
    print(outfile_name)
    subprocess.call('D:\\FFmpeg\\bin\\ffmpeg.exe -i ' + file_name

                    + ' -i ' + mp3_file + ' -strict -2 -f mp4 '

                    + outfile_name, shell=True)


if __name__ == '__main__':
    # video2mp3(file_name='data-a.mp4')
    mp4_f = './video_processing/video/video_下载.mp4'  # 类似这样"F:/xxx/xxxxx.webm"  视频文件
    mp3_f = './video_processing/sound/下载.mp3'  # 类似这样"F:/xxx/xxxxx.webm"  音频文件
    video_add_mp3(file_name=mp4_f, mp3_file=mp3_f)

以上就是基础的代码内容

单py文件实现

当时完成以上的功能后,发现py文件太多了,导致一次转换需要执行多次才能成功的转出我想要的内容,太过于累赘,于是新的代码就出来了

  1. 新增目录创建 ,视频转换的时候回有很多的图片、音频、素描图的产生,为了归类;
  2. 新增循环操作, 用来实现单次执行多次使用;

具体代码

import re
import threading
import time

import numpy as np
from moviepy.editor import *
import cv2, os
from PIL import Image
import subprocess

print('请输入图片/视频的绝对路径, 并以英文","隔开进行输入文件夹名称(切记不可输入中文), 切记文件夹名称不可重复哦, 如有重复后果自理, 概不负责哦 !!!')
while True:
    path = input(r'请输入:')
    path_list_0, path_list_1 = '', ''

    if ',' in path:
        path = path.split(',')
        path_list_0 = path[0]
        path_list_1 = path[1]
    else:
        print('您输入的不合法哦 !!!')

    path = eval(repr(path_list_0).replace('\\', '/'))  # 将\\ 转换为 /
    if u'\u4e00' <= path.split('/')[-1].split('.')[0] <= u'\u9fff':
        path_img, path_Sketch, path_sound, path_video, path_SketchVideo = './%s/img' % path_list_1, './%s/Sketch' % path_list_1, './%s/sound' % path_list_1, './%s/video' % path_list_1, './%s/SketchVideo' % path_list_1
    else:
        path_img, path_Sketch, path_sound, path_video, path_SketchVideo = './%s/img' % path_list_1, './%s/Sketch' % path_list_1, './%s/sound' % path_list_1, './%s/video' % path_list_1, './%s/SketchVideo' % path_list_1

    if path.split('/')[-1].split('.')[1] != 'mp4':
        if os.path.exists(path_Sketch) == False:  # 处理后素描图片
            os.makedirs(path_Sketch)
    else:
        if os.path.exists(path_img) == False:  # 初始视频图片
            os.makedirs(path_img)
        if os.path.exists(path_Sketch) == False:  # 处理后素描图片
            os.makedirs(path_Sketch)
        if os.path.exists(path_sound) == False:  # 视频音频
            os.makedirs(path_sound)
        if os.path.exists(path_video) == False:  # 素描视频
            os.makedirs(path_video)
        if os.path.exists(path_SketchVideo) == False:  # 合成音视频
            os.makedirs(path_SketchVideo)


    # 处理视频mp3
    def Sound_mp3():
        print('<----------------------------- 开始提取音频并生成MP3 ----------------------------->')
        """
        extensions_dict = { "mp4":  {'type':'video', 'codec':['libx264','libmpeg4', 'aac']},
                            'ogv':  {'type':'video', 'codec':['libtheora']},
                            'webm': {'type':'video', 'codec':['libvpx']},
                            'avi':  {'type':'video'},
                            'mov':  {'type':'video'},

                            'ogg':  {'type':'audio', 'codec':['libvorbis']},
                            'mp3':  {'type':'audio', 'codec':['libmp3lame']},
                            'wav':  {'type':'audio', 'codec':['pcm_s16le', 'pcm_s24le', 'pcm_s32le']},
                            'm4a':  {'type':'audio', 'codec':['libfdk_aac']}
                          }
        """
        video = VideoFileClip(path)
        audio = video.audio
        path_sound_mp3 = path_sound + "/" + path.split('/')[-1].split('.')[0] + '.mp3'
        audio.write_audiofile(path_sound_mp3)
        print(f'<--------- 音频提取成功已生成MP3 存储位置: {
      
      path_list_1}\sound --------->' + '\n')


    # 处理视频拆解图片
    def Picture():
        print('<----------------------------- 开始拆解视频帧图片 ----------------------------->')
        vc = cv2.VideoCapture(path)  # 读入视频文件
        c = 0
        rval = vc.isOpened()
        while rval:  # 循环读取视频帧
            c = c + 1
            rval, frame = vc.read()
            if rval:
                # img为当前目录下新建的文件夹
                path_picture = path_img + "/" + str(c) + '.jpg'
                cv2.imwrite(path_picture, frame)  # 存储为图像
                cv2.imencode('.jpg', frame)[1].tofile(path_picture)  # 存储成功
                cv2.waitKey(1)
            else:
                break
        vc.release()
        print(f'<--------- 拆解视频帧图片完成 存储位置: {
      
      path_list_1}\img --------->' + '\n')


    # 原图转素描
    def Sketch():
        print('<----------------------------- 开始原图转素描 ----------------------------->')
        if path.split('.')[-1] == 'mp4':
            print(f'图片实在太多了,{
      
      len(os.listdir(path_img))}张, 转换的时间有点长哦,请稍等 !!!')
            for i in range(0, len(os.listdir(path_img))):
                img = os.listdir(path_img)[i]
                img_number = img.split('.')[0]
                a = np.asarray(Image.open(path_img + "/%s" % img).convert('L')).astype('float')
                time.sleep(0.5)
                depth = 10.  # (0-100)
                grad = np.gradient(a)  # 取图像灰度的梯度值
                grad_x, grad_y = grad  # 分别取横纵图像梯度值
                grad_x = grad_x * depth / 100.
                grad_y = grad_y * depth / 100.
                A = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1.)
                uni_x = grad_x / A
                uni_y = grad_y / A
                uni_z = 1. / A

                vec_el = np.pi / 2.2  # 光源的俯视角度, 弧度值
                vec_az = np.pi / 4.  # 光源的方位角度, 弧度值
                dx = np.cos(vec_el) * np.cos(vec_az)  # 光源对x 轴的影响
                dy = np.cos(vec_el) * np.sin(vec_az)  # 光源对y 轴的影响
                dz = np.sin(vec_el)  # 光源对z 轴的影响

                b = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)  # 光源归一化
                b = b.clip(0, 255)

                im = Image.fromarray(b.astype('uint8'))  # 重构图像
                im.save(path_Sketch + f"/{
      
      img_number}.jpg")

                # src = cv2.imread(path_Sketch + f"/{img_number}.jpg", 100)
                # cv2.imwrite(path_Sketch + f"/{img_number}.jpg", src, [cv2.IMWRITE_JPEG_QUALITY, 100])
            print(f'<--------- 原图转素描成功 存储位置: {
      
      path_list_1}\Sketch --------->' + '\n')
        else:
            img_number = path.split('/')[-1].split('.')[0]
            a = np.asarray(Image.open(path).convert('L')).astype('float')
            time.sleep(0.5)
            depth = 10.  # (0-100)
            grad = np.gradient(a)  # 取图像灰度的梯度值
            grad_x, grad_y = grad  # 分别取横纵图像梯度值
            grad_x = grad_x * depth / 100.
            grad_y = grad_y * depth / 100.
            A = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1.)
            uni_x = grad_x / A
            uni_y = grad_y / A
            uni_z = 1. / A

            vec_el = np.pi / 2.2  # 光源的俯视角度, 弧度值
            vec_az = np.pi / 4.  # 光源的方位角度, 弧度值
            dx = np.cos(vec_el) * np.cos(vec_az)  # 光源对x 轴的影响
            dy = np.cos(vec_el) * np.sin(vec_az)  # 光源对y 轴的影响
            dz = np.sin(vec_el)  # 光源对z 轴的影响

            b = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)  # 光源归一化
            b = b.clip(0, 255)

            im = Image.fromarray(b.astype('uint8'))  # 重构图像
            im.save(path_Sketch + f"/{
      
      img_number}.jpg")

            # src = cv2.imread(path_Sketch + f"/{img_number}.jpg", 100)
            # cv2.imwrite(path_Sketch + f"/{img_number}.jpg", src, [cv2.IMWRITE_JPEG_QUALITY, 100])
            print(f'<--------- 原图转素描成功 存储位置: {
      
      path_list_1}\Sketch --------->' + '\n')


    # 合成素描视频
    def PictureVideo():
        print('<----------------------------- 开始合成素描视频 ----------------------------->')

        """
        'M', 'J', 'P', 'G' = avi
        'M', 'P', '4', 'V' = mp4
        """
        ims_path_list = os.listdir(path_Sketch)
        ims_path_list.sort()
        fps = 30

        def tryint(s):  # 将元素中的数字转换为int后再排序
            try:
                return int(s)

            except ValueError:
                return s

        def str2int(v_str):  # 将元素中的字符串和数字分割开
            return [tryint(sub_str) for sub_str in re.split('([0-9]+)', v_str)]

        def sort_humanly(v_list):  # 以分割后的list为单位进行排序
            return sorted(v_list, key=str2int)

        wk = sort_humanly(ims_path_list)

        im_size = Image.open(os.path.join(path_Sketch, wk[0])).size
        # fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
        fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', 'V')
        videoWriter = cv2.VideoWriter(path_video + '/video_' + path.split('/')[-1].split('.')[0] + '.mp4', fourcc, fps,
                                      im_size)

        for i, im_path in enumerate(wk):
            im_path = os.path.join(path_Sketch, im_path)
            frame = cv2.imread(im_path)
            videoWriter.write(frame)
        videoWriter.release()
        print(f"<--------- 合成素描视频成功 存储位置: {
      
      path_list_1}\video --------->" + '\n')


    # 合成音视频
    def video_add_mp3(file_name, mp3_file):
        print('<----------------------------- 开始合成素描视频+背景音乐 ----------------------------->')

        """

        视频添加音频

        :param file_name: 传入视频文件的路径

        :param mp3_file: 传入音频文件的路径

        :return:

        """

        outfile_name = path_SketchVideo + "/new_video.mp4"

        subprocess.call('D:\\FFmpeg\\bin\\ffmpeg.exe -i ' + file_name

                        + ' -i ' + mp3_file + ' -strict -2 -f mp4 '

                        + outfile_name, shell=True)

        print(f"<--------- 合成素描视频+背景音乐完成 存储位置: {
      
      path_list_1}\SketchVideo --------->" + '\n')


    # 压缩视频
    def SaveVideo():
        print('<----------------------------- 开始压缩素描视频 ----------------------------->')
        fpsize = os.path.getsize(path_SketchVideo + "/new_video.mp4") / 1024
        if fpsize >= 100.0:  # 大于等于100KB的视频需要压缩
            if path_SketchVideo + "/new_video_ys.mp4":
                compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(
                    path_SketchVideo + "/new_video.mp4", path_SketchVideo + "/new_video_ys.mp4")
                isRun = os.system(compress)

                print('<----------------------------- 压缩素描视频完成 ----------------------------->' + '\n')
            else:
                compress = "ffmpeg -i {} -r 10 -pix_fmt yuv420p -vcodec libx264 -preset veryslow -profile:v baseline -crf 23 -acodec aac -b:a 32k -strict -5 {}".format(
                    path_SketchVideo + "/new_video.mp4", path_SketchVideo + "/new_video.mp4")
                isRun = os.system(compress)

                print('<----------------------------- 压缩素描视频完成 ----------------------------->' + '\n')
            if isRun != 0:
                return ('isRun', isRun, "没有安装ffmpeg")


    # 视频处理
    def StartProcessingVideo():
        print('<`---------- 您上传的是视频哦, 处理可能需要些时间, 尽情期待 ----------`>' + '\n')
        Sound_mp3()  # 音频MP3
        Picture()  # 视频切原图
        Sketch()  # 原图转素描
        PictureVideo()  # 合成素描视频
        mp3_f = path_sound + "/" + path.split('/')[-1].split('.')[0] + '.mp3'
        mp4_f = path_video + "/video_" + path.split('/')[-1].split('.')[0] + '.mp4'
        video_add_mp3(file_name=mp4_f, mp3_file=mp3_f)  # 合成素描音视频
        SaveVideo()


    # 图片处理
    def StartProcessingPictures():
        print('<`---------- 您上传的是图片哦, 处理起来很快的, 尽情期待 ----------`>' + '\n')
        Sketch()


    if path.split('/')[-1].split('.')[1] == 'mp4':
        StartProcessingVideo()
    else:
        StartProcessingPictures()

    operation = input('请问是否继续,继续请输入“是”: ')
    if operation != '是':
        exit()

作品信息

抖音:抖音中发布的是素描音视频合成
https://www.douyin.com/user/MS4wLjABAAAANtLRNzfIQBaWgzev17EdTs0X_1JTszXdDCUc657AqvWv9GzGUVleCgwmmQ7OcCwV
微博:超话4Mango中发布的是图片转素描在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43603846/article/details/125180275
今日推荐