当前位置: 首页 > 后端技术 > Python

Python实现图片转字符画,静态图片和GIF可以转成

时间:2023-03-26 12:02:54 Python

字符图是由字母、标点或其他字符组成的图片。它产生于互联网时代,广泛应用于聊天软件中。下面介绍如何将您喜欢的图片转换为人物画。静态图首先,我们来演示如何将静态图转换为人物画。实现该功能主要使用的Python库是OpenCV,可以使用pipinstallopencv-python命令安装。功能实现的基本思路是:利用聚类将像素信息聚类成3或5类,最暗的类别用数字密度表示,阴影的类别用横条(-)表示,亮的部分表示由一个空白。主要代码实现如下:defimg2strimg(frame,K=5):iftype(frame)!=np.ndarray:frame=np.array(frame)height,width,*_=frame.shapeframe_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)frame_array=np.float32(frame_gray.reshape(-1))criteria=(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,10,1.0)flags=cv2.KMEANS_RANDOM_CENTERS#获取标签(ids)(center)compactness,labels,centroids=cv2.kmeans(frame_array,K,None,criteria,10,flags)centroids=np.uint8(centroids)#labels的质心是随机排列的,所以需要对质心进行处理simplycentroids=centroids.flatten()centroids_sorted=sorted(centroids)#获取不同质心的亮度,0为最暗centroids_index=np.array([centroids_sorted.index(value)forvalueincentroids])bright=[abs((3*i-2*K)/(3*K))foriinrange(1,1+K)]bright_bound=bright.index(np.min(bright))shadow=[abs((3*i-K)/(3*K))foriinrange(1,1+K)]shadow_bound=影子.index(np.min(shadow))labels=labels.flatten()#将标签转换为实际的明暗列表labels=centroids_index[labels]#解析列表labels_picked=[labels[rows*width:(rows+1)*width:2]forrowsinrange(0,height,2)]canvas=np.zeros((3*height,3*width,3),np.uint8)#创建一个白色画布,其长度和宽度是原始图像canvas.fill(255)y=8forrowsinlabels_picked:x=0forcolsinrows:ifcols<=shadow_bound:cv2.putText(canvas,str(random.randint(2,9)),(x,y),cv2.FONT_HERSHEY_PLAIN,0.45,1)elifcols<=bright_bound:cv2.putText(canvas,"-",(x,y),cv2.FONT_HERSHEY_PLAIN,0.4,0,1)x+=6y+=6returncanvas原图如下:效果图如下:GIF动画下面我们来演示如何将GIF转成人物画。主要用于功能实现的Python库有imageio和Pillow,可以使用pipinstallimageio/Pillow命令进行安装。功能实现的基本思路如下:将gif图片的每一帧分割成一张静态图片,将所有静态图片转为人物画,将所有人物画重新组合成gif。主要代码实现如下:#splitgifandprocesseachframeintocharactersDrawdefgif2pic(file,ascii_chars,isgray,font,scale):'''file:giffileascii_chars:灰度值isgray对应的字符串:黑白字体:ImageFontobjectscale:scaling'''im=Image.open(file)path=os.getcwd()if(notos.path.exists(path+"/tmp")):os.mkdir(path+"/tmp")os.chdir(path+"/tmp")#清除os.listdir(path+"/tmp")中f的tmp目录中的内容:os.remove(f)try:while1:current=im.tell()name=file.split('.')[0]+'_tmp_'+str(current)+'.png'#保存每一帧图像im.save(name)#将每一帧处理成字符图img2ascii(name,ascii_chars,isgray,font,scale)#继续处理一帧im.seek(current+1)except:os.chdir(path)#将不同的灰度值映射为ASCII字符defget_char(ascii_chars,r,g,b):length=len(ascii_chars)gray=int(0.2126*r+0.7152*g+0.0722*b)返回ascii_chars[int(gray/(256/length))]#将图片处理成字符画defimg2ascii(img,ascii_chars,isgray,font,scale):scale=scale#将图片转成RGB模式im=Image.open(img).convert('RGB')#设置处理后字符绘图的大小raw_width=int(im.width*scale)raw_height=int(im.height*scale)#获取设置字体的大小font_x,font_y=font.getsize('')#确定单位大小block_x=int(font_x*scale)block_y=int(font_y*scale)#确定长宽各有多少个单位w=int(raw_width/block_x)h=int(raw_height/block_y)#将每个单元缩小为一个像素im=im.resize((w,h),Image.NEAREST)#txts和colors分别存储对应块的ASCII字符和RGB值txts=[]colors=[]foriinrange(h):line=''lineColor=[]forjinrange(w):pixel=im.getpixel((j,i))lineColor.append((像素[0],pixel[1],pixel[2]))line+=get_char(ascii_chars,pixel[0],pixel[1],pixel[2])txts.append(line)colors.append(lineColor)#创建一个新的canvasimg_txt=Image.new('RGB',(raw_width,raw_height),(255,255,255))#创建要用ASCII写入的ImageDraw对象draw=ImageDraw.Draw(img_txt)forjinrange(len(txts)):foriinrange(len(txts[0])):如果是灰色:draw.text((i*block_x,j*block_y),txts[j][i],(119,136,153))else:draw.text((i*block_x,j*block_y),txts[j][i],colors[j][i])img_txt.save(img)#读取tmp目录下的文件并合成gifdefpic2gif(dir_name,out_name,duration):path=os.getcwd()os.chdir(dir_name)dirs=os.listdir()images=[]num=0fordindirs:images.append(imageio.imread(d))num+=1os.chdir(path)imageio.mimsave(out_name+'_ascii.gif',images,duration=duration)原图如下:黑白效果图如下:彩色效果图如下:总结本篇我们使用Python来演示将静态图片和GIF转为人物画的方法.如果大家有兴趣,可以用自己的转成自己喜欢的图片,如果对转出的效果不满意,也可以修改代码,改成自己满意的效果。本文未首发于个人账号