将图片的每个点转为文字
1,选择视频展示:
2,最终效果展示:
import cv2 # cv2用于将视频按帧导出(pip install opencv-python)
import tkinter as tk
from tkinter import filedialog
from tkinter import simpledialog
import tkinter.colorchooser
import ttkbootstrap as ttk # tkinter部分,主模块/选择文件模块/获取输入模块/调色盘/美化界面(主要是美化按钮,完全可以不用,后面程序略微有变化)
from PIL import Image # 将图片转化为文字的核心模块,cv2也可以做到,pil更方便
import time
import os
from os import listdir # python内置模块 这里用来建立/读取文件夹
video_name = None # 全局变量:所选择的视频名称
txt_s = [] # 全局变量:最后用来展示的所有的文字
count = 0
count_ed = 0 # 计数:已经循环次数
ida = None # 全局变量:tkinter的循环使用after_cancel结束,需要一个id
c_name = None # 全局变量:新建文件夹的名称,为避免重复,后面使用time.time()作为名称
times = 0 # 计数:已经循环次数
per_frame = 25 # 帧率
# 可更改的变量 分别是:帧数比例,即原视频多少帧截取1次,默认2,不能小于1,帧比过大,最后的视频不流畅,帧比过小,会使得裁取很多图,耗时间耗内存
# 最后的播放速度
# 展示出来的前景色
# 展示出来的背景色
freq = 2
speed = 1
tag_fg = "#000026"
tag_bg = "#ff770f"
# # # 1111111111111111111111111111111111111111111111111111111111111111111111111111
# 这里是4个函数,列在主界面的菜单栏,用于更改上述4个变量
def change_freq():
global freq
input_s = simpledialog.askstring("帧比", "输入2-10整数")
if input_s: # 直接关闭输入框,没有输入值会报错,加上这里就不会
q = eval(input_s)
if type(q) == int: # 如果没有这个条件,那么不管输入的什么值,都会改变帧比,如果是文字就会出错。 加上此甄别可避免
freq = q
def change_speed():
global speed
input_s = simpledialog.askstring("倍速", "输入2(只支持2倍速)")
if input_s:
q = eval(input_s)
if type(q) == 2:
speed = q
def change_fg():
global tag_fg
color = tkinter.colorchooser.askcolor() # 打开tkinter的调色盘
tag_fg = str(color)[-9:-2] # 切片rgb
def change_bg():
global tag_bg
color = tkinter.colorchooser.askcolor()
tag_bg = str(color)[-9:-2]
# # # 1111111111111111111111111111111111111111111111111111111111111111111111111111
# 这里是第一个按钮功能:即读取视频进行分帧
def cut_video():
global video_name, c_name, times, per_frame
video_name = filedialog.askopenfilename(title="选择一个视频进行读取", initialdir=r'D:\a', filetypes=[("", ".mp4")])
c_name = str(time.time()).replace(".", "")
os.mkdir("{}".format(c_name))
if video_name: # 不加这个条件的话,在前面选择视频文件时,如果直接关闭,后面就会报错
video_cap = cv2.VideoCapture(video_name) # cv2读取视频
frame_count = video_cap.get(7) # 帧数计数
per_frame = video_cap.get(5)
while True:
times += 1
ret, frame = video_cap.read()
tag1.config(text="{} 进度:{}/{}".format(video_name, times, frame_count)) # 进度值 缓解焦虑
window1.update() # 如果没有这里,会因为while的循环过快导致上一句config没反应
if not ret: # 当帧数取完时跳出循环
break
if times % freq == 0: # 当帧数/帧比为0时保存图片,说明白点就是当帧比为2时,每两帧保存一次
cv2.imwrite("{0:}/{1:0>8}.jpg".format(c_name, times), frame)
video_cap.release() # 释放视频
tag1.config(text="{}分帧完成".format(video_name)) # 改变标签信息 这句话少一个缩进的话即使没有选择视频也会出现
bu2.config(text="开始读取")
# 提示:上面的config只是为了缓解焦虑,仅供好看。但是会增加耗时
# # # 1111111111111111111111111111111111111111111111111111111111111111111111111111
# 这个是核心功能,可以 单独拿出来将图片转化为txt文档
def picture_to_txt(picture):
img = Image.open("{}/{}".format(c_name, picture)) # 使用Image模块,打开我们刚刚新建的文件夹(里的图片)或者我们选取的文件夹
s = "一二三中目丢丽事秉厜亀隔鄢匔鄹龖" # 用16个字代替灰度值为0-255的像素点,即 像素越黑 所替换的字越丰盈
img = img.convert("L") # 转化为灰度图
x, y = int(19 * img.width / 48), int(7 * img.height / 18)
img = img.resize((x, y)) # 将图片进行缩放,不要太大不然屏幕挤。并且文字有行间距,所以横竖缩放不一样
pix = img.load() # 加载(灰度)
ss = ""
for n in range(y):
for m in range(x):
nt = pix[m, n]
nnt = nt // 16
ss += s[nnt]
ss += "\n"
return ss
# # # 1111111111111111111111111111111111111111111111111111111111111111111111111111
# 有了所有的文字,展示即可
def end():
global ida, count
if ida:
window1.after_cancel(ida)
tag2.place_forget()
bu4.place_forget()
count = 0
window1.geometry("300x200")
ida = None
def show(per_t):
global count, ida
if count == len(txt_s):
window1.after_cancel(ida)
tag2.place_forget()
bu4.place_forget()
window1.geometry("300x200")
count = 0
ida = None
else:
print(count)
tag2.config(text=txt_s[count], font=("等线", 1), bg=tag_bg, fg=tag_fg)
window1.update()
ida = window1.after(per_t, lambda: show(per_t))
count += 1
def start():
window1.geometry("1800x1000+0+0")
bu4.place(x=50, y=600)
tag2.place(x=0, y=0)
per_t = int(1000 * freq / per_frame / speed)
show(per_t)
# # # 1111111111111111111111111111111111111111111111111111111111111111111111111111
# 有了所有的图片,现在用上述的核心功能,把所有的图片转化为文字
def read_files():
global txt_s, c_name
images = None
if video_name and c_name:
images = listdir(c_name)
else:
images_choose = filedialog.askdirectory(title="选择文件夹") # 如果进行了分帧就打开新件文件夹 否则直接选取文件夹
c_name = images_choose
if images_choose:
images = listdir(images_choose)
if images:
for i in range(len(images)):
picture_name = images[i]
txt = picture_to_txt(picture_name)
txt_s.append(txt) # 装起来
tag1.config(text="加载进度{}/{}".format(i+1, len(images)))
window1.update()
tag1.config(text="加载完成")
time.sleep(1)
bu3.pack(pady=5)
# # # 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111
window1 = tk.Tk()
window1.geometry('300x200+0+0')
window1.attributes("-topmost", 1)
window1.title("T")
try:
window1.iconbitmap("001.ico")
except:
pass
window1.resizable(False, False)
tag1 = tk.Label(window1, text="{}NO FILE!{}".format(10*" ", 10*" "), font=("等线", 10))
tag1.pack(pady=5)
bu1 = ttk.Button(window1, text="视频分帧", bootstyle=('INFO', 'OUTLINE'), command=cut_video)
bu1.pack(pady=5)
bu2 = ttk.Button(window1, text="读取文件夹", bootstyle=('INFO', 'OUTLINE'), command=read_files)
bu2.pack(pady=5)
bu3 = ttk.Button(window1, text="开始播放", bootstyle=('INFO', 'OUTLINE'), command=start)
tag2 = tk.Label(window1, font=1)
bu4 = tk.Button(window1, text=" S T O P ", font=("DS-Digital", 30), command=end)
# # # 111111111111111111111111111111111111111111111111111111111111111111111111111111111111
# 菜单
meu = tk.Menu(window1)
meu_group = tk.Menu(meu)
meu.add_cascade(label="修改", menu=meu_group, font=10)
meu_group.add_command(label="【帧率比】", font=("times", 10), command=change_freq)
meu_group.add_separator()
meu_group.add_command(label="【播放速度】", font=("times", 10), command=change_speed)
meu_group.add_separator()
meu_group.add_command(label="【前景色】", font=("times", 10), command=change_fg)
meu_group.add_separator()
meu_group.add_command(label="【后景色】", font=("times", 10), command=change_bg)
window1.config(menu=meu)
window1.update()
window1.mainloop()
菜鸡分享,大佬勿喷