jjjzw 发表于 2021-4-17 12:55

【python】opencv实战 处理bad apple视频

本帖最后由 jjjzw 于 2021-4-17 13:02 编辑

bad apple是这种黑白风格的视频,正适合拿来opencv练手{:1_918:}
选用的视频是b站1440x1080 30fps的素材,下载后将其改名为bad apple.mp4

目标效果是把视频中黑色的部分变为像素点颗粒,(造成锯齿感很强的样子。。

一、提取视频帧
div_frame.py
import cv2
import os

path = "pic/"


# 将视频按帧抽取出图像
def div(path_video):
    cap = cv2.VideoCapture(path_video)

    def save_image(image, addr, num):
      address = addr + str(num) + '.jpg'
      cv2.imwrite(address, image)

    if os.path.exists(path):
      pass
    else:
      os.makedirs(path)

    success, frame = cap.read()
    i = 0

    while success:
      i = i + 1
      save_image(frame, path, i)
      print("已抽取:" + str(i))
      success, frame = cap.read()

视频的每一帧就会被提取出来保存到pic文件夹中

二、图像转视频
对一个文件夹中的图像文件,排序后按帧率、分辨率组合成视频
re_video.py
import os
import cv2


# 将图像按帧重新制作成视频
def remake(path_pic, name, fps, a, b):
    file_list = os.listdir(path_pic)
    # 列表排序
    file_list.sort(key=lambda x: int(x[:-4]))

    count = 0
    size = (a, b)
    # 可以使用cv2.resize()进行修改

    video = cv2.VideoWriter(name + ".avi", cv2.VideoWriter_fourcc('P', 'I', 'M', '1'), fps, size)
    """
    cv2.VideoWriter_fourcc('I','4','2','0')---未压缩的YUV颜色编码,4:2:0色度子采样。兼容性好,但文件较大,注意是很大!!!(50M视频拆出的帧转换后大约15G)文件扩展名.avi。   
    cv2.VideoWriter_focurcc('P','I','M','1')---MPEG-1编码类型,文件扩展名.avi。
    随机访问,灵活的帧率、可变的图像尺寸、定义了I帧、P帧和B帧、运动补偿
    可跨越多个帧、半像素精度的运动向量、量化矩阵、GOF结构、slice结构、技术细节、输入视频格式。
   
    cv2.VideoWriter_fourcc('X','V','I','D')---MPEG-4编码类型,视频大小为平均值,MPEG4所需要的空间是MPEG1或M-JPEG的1/10,
    它对运动物体可以保证良好的清晰度,间/时间/画质具有可调性。文件扩展名.avi。
   
    cv2.VideoWriter_fourcc('T','H','E','O')---OGGVorbis,音频压缩格式,有损压缩,类似于MP3等的音乐格式。
    兼容性差,文件扩展名为.ogv。
   
    cv2.VideoWriter_focurcc('F','L','V','1')---FLV是FLASH VIDEO的简称,FLV流媒体格式是一种新的视频格式。
    由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效的解决了视频文件导入Flash后,使导出的SWF文件体积庞大,
    不能在网络上很好的使用等缺点。文件扩展名为.flv
    """

    for item in file_list:
      count = count + 1
      item = path_pic + item
      img = cv2.imread(item)
      video.write(img)
      print("已加载: " + str(count))

    video.release()
    cv2.destroyAllWindows()


三、调制每一帧的图像
由于不确定原素材是否为完全的二值图像,对每一帧都进行灰度化、二值化后在处理像素
threshold_.py
import cv2


# 图像灰度化、二值化
def grey(path):
    img = cv2.imread(path)
    e1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thr = cv2.threshold(e1, 100, 255, cv2.THRESH_BINARY)
    return thr

cv2.imgread默认读取RGB三通道,因此需要转化为灰度图的单通道后才能进行二值化

接下来是对图像进行处理
思路是:将1440x1080完全拆分为4x4的像素块区域,对每一个像素块里黑色(0)的个数进行判断,如果个数超过一定数值(阈值),则认为区域有效,否则无效
对于有效像素块,将中间2x2的像素块画成黑色(0),周围画成白色(255)
对于无效像素块,全部画成白色(255)
这样设置的好处是白色和黑色均匀间隔,比较美观(当然猎奇一点也可以用其他规则:lol)

main.py
from div_frame import div, path
from threshold_ import grey
from re_vedio import remake
import cv2
import os


def save_image(image, addr):
    address = addr
    cv2.imwrite(address, image)


def change(img_path):
    ig = grey(img_path)

    def num(m, n):
      count_pix = 0
      for ii in range(0, 4):
            for jj in range(0, 4):
# 像素值只有0和255,因此这里设置10和0和其它什么数都一样
                if ig <= 10:
                  count_pix = count_pix + 1
      return count_pix

    def draw_black(m, n):
      for ii in range(0, 4):
            for jj in range(0, 4):
                ig = 255
      for ii in range(1, 3):
            for jj in range(1, 3):
                ig = 0

    def draw_white(m, n):
      for ii in range(0, 4):
            for jj in range(0, 4):
                ig = 255

# 遍历所有的像素块
    for j in range(0, 360):
      for i in range(0, 270):
            if num(i, j) >= 8:
                draw_black(i, j)
            else:
                draw_white(i, j)
    return ig


if __name__ == "__main__":
    path_video = "bad apple.mp4"
    print("————开始抽取视频帧————")
    div(path_video)
    print("————视频帧抽取完毕————")
    file_list = os.listdir(path)
# 对列表元素进行从小到大排序
    file_list.sort(key=lambda x: int(x[:-4]))
    print("————开始转换帧图像————")
    for file in file_list:
      file_path = path + file
      print("已转换:" + file_path)
      save_image(change(file_path), file_path)
    print("————帧图像转换完毕————")
    print("————开始制作视频————")
# 转换为视频,路径、名字、帧率、分辨率
    remake(path, "BadApple", 30, 1440, 1080)

四、最后运行main.py开始处理视频
(每一帧处理的时间约为4秒)
在长达7小时的运行后,视频终于转换完了{:1_907:}
用多线程应该能处理得更快,不过写完正好是凌晨,睡一觉起来就差不多了,就没用线程
这是第318帧的图像:
视频效果:https://www.bilibili.com/video/BV1Cp4y1t7ot/

对每一帧的图像还可以采用其他的处理方式,比如对于有效像素块,可以不填充黑色,而填充其他随机颜色但是这样需要将单通道重新转换为3通道(重新imread也可以)
def random_color():
    global color
    a = random.randint(0, 5)
    if a == 0:
      color =
    elif a == 1:
      color =
    elif a == 2:
      color =
    elif a == 3:
      color =
    elif a == 4:
      color =
    elif a == 5:
      color =
    return color


def change(img_path):
    ig = cv2.imread(img_path, 1)

    def draw_black(m, n):
      for ii in range(0, 4):
            for jj in range(0, 4):
                ig =
      b = random_color()
      for ii in range(1, 3):
            for jj in range(1, 3):
                ig = b

    for j in range(0, 360):
      for i in range(0, 270):
            if (numpy.array(ig) == numpy.array()).all():
                draw_black(i, j)
    return ig


效果
(有彩色雪花屏那味了:lol)

jjjzw 发表于 2021-4-17 13:47

完整代码:https://github.com/Icingworld/opencv-badapple

jjjzw 发表于 2021-4-19 11:25

beginnerzero 发表于 2021-4-18 09:09
谢谢楼主,这个也可以用来制作图片吧

可以的,opencv对图像处理还是很强的

woflant 发表于 2021-4-17 14:22

好文,顶一下学习学习:lol

mengdong 发表于 2021-4-17 15:44

好文,正在学习,需要用,谢谢了

First丶云心 发表于 2021-4-17 15:55

xsjqq123 发表于 2021-4-17 16:28

学习学习{:1_893:}

gutiejun 发表于 2021-4-17 16:44

学习一下,谢谢

beginnerzero 发表于 2021-4-18 09:09

谢谢楼主,这个也可以用来制作图片吧

Chenmozero 发表于 2022-10-4 10:17

强啊,bad apple还能这么玩
页: [1] 2
查看完整版本: 【python】opencv实战 处理bad apple视频