用python把視頻變成字符樣式

我們將這樣的視頻
在這裏插入圖片描述
變成這個樣子
在這裏插入圖片描述
變得又難看,又看不清,搞這幹啥?
閒的咯,下面我們來看看是如何實現的

1、思路

我參考了網上很多人的實現方法,最終我的思路是這樣的
1、我們先準備好一個視頻,想辦法把這個視頻變成很多很多的圖片
2、接着我們把每一張圖片都變成字符串的樣式(是把彩色圖片變成字符串填充的圖片,不是變成一堆字符串)
3、最後,再把轉換好的圖片變成一個視頻
下面我們看看每一步如何利用python實現呢

第一步:視頻->圖片

嘿嘿,要是一張一張去截圖,好像可以滿足我們的需求哦,但那肯定不行,我們知道視頻都是又一幅幅圖片構成的,或者叫一幀一幀的圖片構成的,那麼在所有的幀中有的幀是關鍵幀,按道理似乎只要知道關鍵幀,就可以把前面和後面的圖片推導出來,以此似乎可以起到壓縮視頻的目的,這次我們不管那麼多,直接把視頻一幀一幀全部保存爲圖片,不管是不是關鍵幀。利用opencv-python,實現如下(截取)

    def getFrame(self,videoPath, svPath):
        cap = cv2.VideoCapture(videoPath)
        numFrame = 0
        nums = 0
        while True:
            nums +=1
            if cap.grab():
                flag, frame = cap.retrieve()
                if not flag:
                    continue
                else:
                    numFrame += 1
                    newPath = svPath + str(numFrame) + ".jpg"
                    cv2.imencode('.jpg', frame)[1].tofile(newPath)
            if nums >= self.g_frame_num:
                break
            if cv2.waitKey(10) == 27:
                break 

看到在while循環中,我們視頻的幀全部保存下來爲jpg圖片,g_frame_num是一個類成員變量,可以讓我們定取多少幀數據,以此,我們完成第一步

第二步:彩色圖片->字符串圖片

這部分稍微麻煩一點點,我的思路是這樣的,將圖片的每個像素點,都用同樣色彩的字符代替,然後生成一幅新圖片,但是注意,一個字符串佔得像素點可不是一個,所以在轉換時我們還需要進行一些處理,看看圖片應該用多少個像素來填充

ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
def get_char(r,g,b,alpha = 256):#獲取對應的字符
    if alpha == 0:
        return ' '
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
    unit = (256.0 + 1)/length
    return ascii_char[int(gray/unit)]
def image_to_strimage(self,isgray=False):
      for k in range(1, self.g_frame_num+1):
          path = './img/' + str(k) + '.jpg'
          im = Image.open(path).convert('RGB')
          raw_width = int(im.width)
          raw_height = int(im.height)
          font = ImageFont.truetype('consola.ttf', 10, encoding='unic')
          font_x, font_y = font.getsize(' ')
          block_x = int(font_x)
          block_y = int(font_y)
          w = int(raw_width / block_x)
          h = int(raw_height / block_y)
          im = im.resize((w, h), Image.NEAREST)
          txts = []
          colors = []
          for i in range(h):  # 遍歷行
              line = ''
              lineColor = []
              for j in range(w):  # 遍歷列
                  pixel = im.getpixel((j, i))
                  lineColor.append((pixel[0], pixel[1], pixel[2]))
                  line += get_char(pixel[0], pixel[1], pixel[2])
              txts.append(line)
              colors.append(lineColor)
          im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255))
          draw_handle = ImageDraw.Draw(im_txt)
          for j in range(len(txts)):
              for i in range(len(txts[j])):
                  if isgray:
                      draw_handle.text((i * block_x, j * block_y), txts[j][i], (50, 50, 50))
                  else:
                      draw_handle.text((i * block_x, j * block_y), txts[j][i], colors[j][i])
          # name = path + str(k) + '.jpg'
          im_txt.save(path, 'JPEG')

第三步:圖片->視頻

利用opencv庫實現,在循環中順便吧那些沒用的圖片刪掉(這種方法出來的視頻文件較大)

    def show(self):
        img = Image.open('./img/1.jpg')
        w = img.width
        h = img.height
        print('視頻格式',w,'*',h)
        videoWriter = cv2.VideoWriter('test.avi', cv2.VideoWriter_fourcc(*'MJPG'), 25, (w, h))
        path_file_number = glob.glob(pathname='./img/*.jpg')
        for i in range(1,len(path_file_number)+1):
            path = './img/' + str(i) + '.jpg'
            img = cv2.imread(path)
            videoWriter.write(img)
            os.remove(path)
        videoWriter.release()

效果大概就是這麼個樣子

在這裏插入圖片描述
在這裏插入圖片描述
沒有聲音,可以想辦法用python去取一下,問題應該不大吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章