大家应该都见过字符照片吧,先来欣赏一下吧。例如,以下为我们turtle海龟库的标志图片小海龟。


图片1

通过将其转化为字符图片后,结果如下图所示。


字符串图片

Python中,我们可以利用图像处理的相关知识轻而易举的实现字符串图片的效果。接下来,我们来介绍一下。

01

用Python制作字符图片

先来介绍一下字符图片的制作原理。要了解如何制作字符图片,我们先要来了解灰度图。

(1). 灰度图

我们知道,对于一张“RGB”颜色模式的图片,其每个像素点对对应一组RGB值。为了实现数据的降维处理,

要制作字符图片,我们首先先要将原图片转化成灰度图。

什么叫灰度图呢?我们知道,任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:

浮点算法:Gray=R*0.3+G*0.59+B*0.11

整数方法:Gray=(R*30+G*59+B*11)/100

移位方法:Gray =(R*76+G*151+B*28)>>8;

平均值法:Gray=(R+G+B)/3;

仅取绿色:Gray=G;

通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜色RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。

例如。对于图1,我们通过利用R、G、B变换,可以获得它的灰度图如下图。


图1的灰度图

以上灰度图片的R、G、B颜色值如下表:

[[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
[255 255 255 ... 255 255 255]
...
[253 253 253 ... 254 254 254]
[252 252 253 ... 253 253 253]
[252 252 253 ... 253 253 253]]

像素表

需要说明的是,由于灰度图片的R、G、B值均一样,所以,计算机在表示每一像素点颜色时,均用一个数值来表示。例如,上表中,第一行第一列的值为255,实际上对应的该点像素RGB值为(255,255,255)

(2). 对灰度图进行映射获得其字符图片

要生成字符图片,首先要做一个字符串,用于去映射以上灰度图片的像素表。我们这里定义的字符串为:

char_arr='''@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,"^`'. '''

该字符串中共含有69个字符。

接下来,通过编写代码,做映射,可以实现将像素列表中的每一个像素映射到相应字符串上,这样就可以达到获得字符图片的目的。

上一下映射像素值到字符串,从而产生字符图片方法的代码。

def transform(image_file):
code_Pic = ''
for h in range(0, image_file.size[1]):
for w in range(0, image_file.size[0]):
g, r, b= image_file.getpixel((w, h))
gray = int(r * 0.299 + g * 0.587 + b * 0.114)
code_Pic = code_Pic + char_arr[int(((count - 1) * gray) / 256)]
code_Pic = code_Pic + '\r\n'
return code_Pic

以上函数方法中,image_file参数是由image模块产生的图像对象,以下语句实现的是由像素点到字符的映射。

code_Pic = code_Pic + char_arr[int(((count - 1) * gray) / 256)]

调用以上函数后,可以获得灰度图片映射后的字符图片。


图1的字符图片

02

用Python制作命令行视频播放器

掌握了字符图片的制作方法后,接下来,我们在此基础上难度增加,来制作一款基于命令行的视频播放器,让我们的字符跳动起来为您播放视频。

怎么做呢?其实很简单,我们知道,视频是由一帧一帧的图片构成的,那么我们是不是只需要将每帧的图片全部都转化为字符图片,然后 再连贯的打印出来是不是就可以形成视频播放的效果呢?对的,答案是肯定的。

那么,如何将视频中的图片读取出来呢?很简单,可以通过利用Python 的视频处理第三方拓展库python-OpenCV来实现。具体代码如下。

cap=cv2.VideoCapture(videoPath)
while True:
success,frame=cap.read()
if not success:
break
img=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
time.sleep(0.05)

其中的cv2是引入python-OpenCV库的具体模块名称。通过以上的无限while循环,我们就可以间隔一段时间将所有视频中的图片全部读取出来。此时我们只需要使用Pillow库中Image模块将读取的照片转化成Image对象,然后将其转化成灰度图片,带入到刚刚写好的transform函数中,就可以实现将每张读入图片转化成字符图片了。转化为字符图片后,我们只需要在命令行窗口里将字符图片连续打印出来,就可以实现播放视频的效果啦。为此,我们做了一个函数,具体代码如下。

def main(videoPath: str):
cap=cv2.VideoCapture(videoPath)
while True:
success,frame=cap.read()
if not success:
break
img=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
img=Image.fromarray(img)
transform(img)
time.sleep(0.05)
cap.release()

好了,这样的话,我们命令行播放器就做差不多了。等等,画面有了,还没有播放声音呢?怎么办?别着急,我们可以利用Pygame库的播放音乐的功能,让画面播放与字符图片播放同步。具体代码如下:

def playmusic():
track = pygame.mixer.music.load('4.mp3')
pygame.mixer.music.play()
pygame.mixer.music.set_volume(0.5)
pygame.time.delay(30000)

以上代码中"4.mp3'就是要播放的视频的声音文件,需要我们自己利用工具将其从视频中分离出来。大家可以利用Python的moviepy模块来实现,这里不做过多介绍。

最后上主程序代码。为了实现命令行播放器效果,主程序主要面向命令行编写,具体代码如下。

outputfile=''
if len(sys.argv)==1:
if os.path.exists(sys.argv[0]):
print("There is no parameters,the program excepted at least one parameter.")
else:
print("File not found.")
elif len(sys.argv)==2:
if os.path.exists(sys.argv[0]):
if os.path.exists(sys.argv[1]):
main(sys.argv[1])
else:
print("File not found.")
else:
print("File not found.")
else:
if os.path.exists(sys.argv[0]):
if os.path.exists(sys.argv[1]):
if sys.argv[2]=='--a':
t1 = Thread(target=playmusic)
t1.start()
main(sys.argv[1])
else:
print('the parameter is not proper!')
else:
print("File not found.")
else:
print("File not found.")

来实验一把吧。我在网上down了一个小姐姐跳舞的视频,视频的播放效果

具体

如下。

接下来,我们提取了该视频的背景音乐,然后,通过调用刚刚写好的python文件,在cmd窗口中运行,通过传递适当的参数,即可实现对该视频的命令行播放。具体效果如下。

好了,马上下载视频,你也来试一下吧!

-end-