前言
我们很多人都有每天用手机刷朋友圈的习惯,最近微信朋友圈、微博可能注意到已经发布了九宫格照片。
可以说将单个图片,或者说单个动图亦或视频分割成9份发在朋友圈,感觉很有趣。
今天,博主就通过Python、OpenCV、pyqt5的知识,来帮助大家实现任意图像,视频,动图的9宫格原理。
文末还有配套生成9宫格的pyqt5的源代码以及exe可运行文件奉上。
生成9宫格图片
一般来说,我们生成的9宫格原图必须是正方形的,毕竟朋友圈与微博整体的9宫格就是正方形的。
但是博主为了9宫格的完备,只需要删除下面一段代码就可以完成任意图形的9宫格,只是大多数平台不支持非正方形的9宫格图片。
下面,我们直接将一张图片分割成9份,代码如下:
# 生成9宫格图片
def grid9_image(imageFileName):
if not os.('image'):
os.makedirs('image')
image = cv2.imread(imageFileName, 1)
#删除代码段头
height, width, n = image.shape
if width >= height:
image = cv2.resize(image, (width, width))
height=width
else:
image = cv2.resize(image, (height, height))
width = height
#删除代码段尾
height = int(height / 3)
width = int(width / 3)
x = 1
for i in range(0, 3):
for j in range(0, 3):
print(i * height, height * (i + 1), j * width, width * (j + 1))
result = image[i * height:height * (i + 1), j * width:width * (j + 1)]
print('image/' + str(x) + ".png")
cv2.imwrite('image/' + str(x) + ".png", result)
x += 1
这里,我们是横切分算法,首先i在j循环结束之前是不会变化的,那么就可以保证前面的切分一直就是三分之一。
后面的是宽度切分,第1份j=0,后面就是j+1=1为前三分之一,循环一次后j=1,也就是(width,widht*2),最后j=2时,(width*2,width*3)。(把注释中间的代码删除,得到的是任意图形的均分9份)
i与j的算法同理,原理如下图。记得这里是width,height是整体宽度高度除于3后得到的。
当然,使用画图工具分割的有点不规则该请见谅,读者可以把其想象成规整的看。同时如果i,j调换位置,那么图片就是竖切分算法。会从左到右,从上到下依次切分。
生成9宫格动图
动图可以由两种形式生成:一种是提供一个短视频转换为动图;一种是直接提供一个GIF动图,直接切分。
短视频生成动图9宫格
首先,我们来看看,提供一个短视频后切分动图,代码如下:
# 短视频生成9宫格动图
def grid9_gif(srcVideoFileName):
if not os.('gif'):
os.makedirs('gif')
all_frames = []
cap = cv2.VideoCapture(srcVideoFileName)
fps = cap.ge)
for i in range(9):
list = []
all_(list)
while ()):
ret, frame = cap.read()
if ret:
height, width, n =
if width >= height:
frame = cv2.resize(frame, (width, width))
height = width
else:
frame = cv2.resize(frame, (height, height))
width = height
height = int(height / 3)
width = int(width / 3)
frame_list = []
for i in range(0, 3):
for j in range(0, 3):
result = frame[i * height:height * (i + 1), j * width:width * (j + 1)]
(result)
for index, image in zip(range(9), frame_list):
all_frames[index].append(image)
else:
break
for index, frames in zip(range(9), all_frames):
imageio.mimsave("gif/" + str(index + 1) + ".gif", frames, 'GIF', duration=float(1 / fps))
cap.release()
其实,可以看出来,中间的切分算法与图片的一模一样。因为视频本身就是由单一的图片构成的。
这里,我们只要将视频每个图片切分,然后分别存储,等到读取完成之后,将每个部分转换为GIF即可。(至于动图的每帧间隔时间,就是1/视频的FPS)
GIF直接生成动图9宫格
对于GIF,OpenCV并没有直接处理动图的函数。所以,最简单的方式,就是通过将动图转换为视频后,在通过上面的代码进行处理。
代码如下:
# GIF生成9宫格动图
def grid9_gif2(srcGIFFileName):
clip = mp.VideoFileClip(srcGIFFileName)
clip.write_videofile("gi;)
grid9_gif('gi;)
这里就是使用moviepy库将GIF转换为视频后,再通过上面的grid9_gif处理。
需要注意的是,目前各大平台并不支持动图自动播放,比如微博必须点击动图才能动,如果后续支持动图自动播放,那么这种动图9宫格的切分也能完美实现。目前效果与静态图片一样,只能看到每个动图的第1帧。
生成9宫格视频
生成9宫格视频,我们就不必切分了。因为视频本身就是一个整体,没有哪个社交软件,可以同一条朋友圈或者微博发9个视频的。
所以,我们只需要将视频中间画上4条分割线,就完成了9宫格视频的生成。代码如下:
#生成9宫格视频
def gird9_Video(srcVideoFileName, outputVideoFilename):
cap = cv2.VideoCapture(srcVideoFileName)
fps = cap.ge)
width = in))
height = in))
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
videoWriter = cv2.VideoWriter(outputVideoFilename + ".avi", fourcc, fps, (width, height))
i = 1
while ()):
ret, frame = cap.read()
if ret:
cv2.line(frame, (0, int(height / 3)), (width, int(height / 3)), (255, 255, 255), 3)
cv2.line(frame, (0, int(height / 3 * 2)), (width, int(height / 3 * 2)), (255, 255, 255), 3)
cv2.line(frame, (int(width / 3), 0), (int(width / 3), height), (255, 255, 255), 3)
cv2.line(frame, (int(width / 3 * 2), 0), (int(width / 3 * 2), height), (255, 255, 255), 3)
videoWri(frame)
else:
break
cap.release()
代码很简单,就是对每个视频的图片画4条分割线。运行之后,效果如下:
使用pyqt5打包成exe界面
对于我们程序员来说,部署的Python环境可以直接运行上面的代码生成你想要的任何9宫格素材。但是对于不是程序员的小伙伴,提供一个可运行的程序,往往体验更加友好。
这里,博主将通过pyqt5打包上述功能成为GUI界面程序。因为代码过多,对pyqt5感兴趣的可以直接前往github网址下载。
引用链接
[1] 点击下载:
[2] 点击下载: