当前位置: 首页 > 科技观察

快来放松一下吧!使用Python制作可缩放的圣诞老人

时间:2023-03-18 15:00:59 科技观察

圣诞节又要来了。虽然我们中国人不提倡西方节日,但商人还是很喜欢的。估计有兴趣的男生女生也会喜欢的。.今天的主题是给大家介绍如何用python制作一个成长中的圣诞老人,就像西游记中的仙女怪兽一样,可以随意改变大小,算是给大家的小礼物吧,先上张图吧!别担心,盯着图片看5秒钟。思路点:通过缩放得到一组大小相等的图片。将以上图片叠加在固定大小的底图上。组合图片以生成动态图片。1.图片缩放本文大部分工作是基于opencv实现的,opencv对图片进行缩放非常容易,但是这次我们要生成一组按比例缩放的图片,所以使用cv2.resize方法可能与以往略有不同。我们先来看功能。原型:cv2.resize(src,dsize[,dst[,fx[,fy[,interpolation]]]])其中src是原始图像,dsize是目标图像大小,当dsize为0时,我们可以通过fx和fy两个参数分别设置横轴和纵轴的缩放比例。这个可能有点抽象,我们举个例子来说明:foriinrange(1,40,1):img=cv2.resize(image,(0,0),fx=i/30,fy=i/30)cv2.imwrite(str(i)+'.png',img)运行上面的代码会生成39张不同比例的图片,目标图片的大小由缩放比例fx和fy控制,最小图片的边长是原图的1/30,最大图的边长是原图的1.3倍(下图):有了缩放后的图片,是不是可以选择一个坐标原点,直接合成动画呢?答案是否定的,因为常规的动画生成方式要求素材图片必须大小相同(像素),下面我们将着重解决这个问题。2.底图叠加python中叠加两张图片的方法有很多种,但都存在缺陷——要么叠加图片必须大小相同,要么难以控制图片叠加的具体位置。对此,小编采用的方法是在两张图片之间进行“像素级”的替换。1).在生成基础图像要叠加的图像中,上层图像使用刚刚得到的一系列按比例缩放的图像,下层图像我们生成固定大小的空白图像。需要注意的是,这里生成的空白图片一定要大于放大后的最大图片。生成空白底图分两步完成。第一步,生成一个固定大小(纵轴和横轴的长度)的二维数组;第二步是使用cv2.cvtColor进行颜色空间转换。代码如下:blank=np.ones((blankh,blankw),dtype=np.uint8)*255ret=cv2.cvtColor(blank,cv2.COLOR_GRAY2BGR)其实上面代码中的ret本质上就是一个三维数组,我们可以把它打印出来供查看(下图),但是通过cv2.imshow方法显示出来的是一张空白图片。这里涉及到一些比较底层的内容,有利于大家理解,文中不再赘述。2).像素替换前面说过,opencv中一张图片其实就是一个三维数组。其实也可以看做是一个二维数组。数组中的每个元素都是一个形如[255,255,255]的列表,里面存储了图像每个像素点的颜色参数。也就是说,如果我们想要实现一张图片叠加在另一张图片上的视觉效果,我们可以对叠加图片对应的像素进行替换赋值。代码形式如下图所示,其中i和j分别为图片的纵坐标和横坐标。ret[i,j,0]=图像[i,j,0]ret[i,j,1]=图像[i,j,1]ret[i,j,2]=图像[i,j,2]]对于一张图片,坐标原点在左上角(如下图)。另外,为了保证动画的最终效果,不能简单的根据坐标原点来叠加图片。更好的方法是将叠加原点设置在基础图像下边缘的中心。理清原理后,就可以开始图像叠加操作了。这期间需要计算一些像素对应的位置。虽然有点绕,但也不复杂。具体的转换公式就不写了。我们直接看代码:上面代码中的图像是缩放后的圣诞老人图像,blankh和blankw分别是空白图像的高和宽。这个尺寸可以根据你的需要来设置。下图为缩放比例为1/2左右的图片与底图的叠加效果。为了方便观察,我给图片加了边框。3、在生成动画之前,我们已经解决了单图和基础图的叠加问题。为了准备动画合成所需的素材,我们还需要对多张按比例缩放的图片进行基础图片叠加操作。缩放间隔越小,准备的图片素材越多,生成的动画就越流畅。当然,动画的效果要综合考虑多种因素。在这里,小编依旧采用了39张图片来组合动画。其中,最小图高为原图的1/30,最大图高为原图的1.3倍。与底图叠加的图像如下所示。再来说说动画的合成。使用imageio库可以实现将多个相同大小的图像组合成动画。核心代码只有一个:imageio.mimwrite('目标文件名.gif',gifList,duration=0.15)第一个参数是git目标文件名;gifList是一组要合成的图片,也就是上图所示的图片;最后一个参数duration表示屏幕切换的时间间隔,单位秒。现在使用下面一段代码进行动画合成。file_path='pic'imgList=os.listdir(file_path)imgList=['pic/'+imgforimginimgList]gifList=[imageio.imread(img)forimginimgList]imageio.mimwrite('gif.gif',gifList,duration=0.15)我们来看看合成后的动画效果(下图)。仔细一看,好像哪里不对劲。图中的圣诞老人为什么会由大变小?这与我们的预期不同。其实问题出在合成图像的顺序上。我们尝试在上面的代码中打印imgList变量,结果如下:可以看到,素材图片并没有按照我们预期的顺序排序。这也是python文件处理中比较常见的问题。解决方案之一是根据图片的创建时间对图片进行排序。具体操作是在上面第二行代码后插入语句:imgList=sorted(imgList,key=lambdax:os.path.getmtime(os.path.join(file_path,x)))现在再次进行动画合成实现文章开头的效果。当然,这种动画制作方式并不仅限于圣诞老人,任何画面理论上都是可以的。例如,我们还可以制作一棵不断生长的圣诞树!