用 Python 实现长截图拼接

可能很多安卓手机都会自带拼接长截图的功能, 可是对于 iOS 只能通过第三方的 app 拼接了于是我想将拼接的功能做成微信小程序, 这样会比较方便, 无奈实现过程中发现用 JavaScript 实现性能存在很大问题, 识别率也很低, 于是打算先用 python 实现, 以测试算法的正确性

我写得可能不是很好, 欢迎指正!

要实现长截图, 可能的情况很多, 先介绍一下最简单的情况

长截图算法

获取截图

我们按照手工拼接的想法来考虑这个问题

首先得到两张截图

寻找相同部分

然后我们首先要考虑两张图相同的部分, 也就是找到相同的头部

删除相同头部

接着把第二张图中与图 1 重复的头部删掉

移动并拼接

然后第二张图从底至顶移动, 找到重合的地方, 拼接

这就是我们正常的手工拼接流程因此可以把算法总结一下:

step 1: 获取两张截图

step 2: 寻找相同的头部

step 3: 删除第二张中相同的头部

step 4: 从第一张的底部至顶部比较, 找到重合的地方, 拼接

实现前要知道

通常的图片为 RGB 模式, 即图片的每个像素由红 (red) 绿(green)蓝 (blue) 三个颜色组成, 它们的取值范围是 [0,255], 即(0,0,0) 表示黑色,(255,255,255)表示白色

在处理图片时, 我们可以对图片中的每个像素操作, 获取到图片的每个像素的 RGB 值, 对于一张 2*3 的纯白图片, 我们可以得到它的像素内容:[

[(255,255,255),(255,255,255)],

[(255,255,255),(255,255,255)],

[(255,255,255),(255,255,255)]

]

共 6 个像素点, 每个 tuple 包含了一个像素点的 RGB 内容

因此, 我们在 寻找相同的头部 的时候, 可以从头开始比较其中每个像素的信息

拼接图片 , 也就是将这些图片的像素信息重新拼接起来, 再显示即可

用 Python 实现

在 python 中我们可以用 PIL 的 getdata()方法获得图片的像素内容, 用 putdata()将像素内容转变成图片

打开图片

通过

img = Image.open(path)

我们可以打开一张图片

再通过 img.getdata()可以得到像素信息fromPILimportImage#引入 PIL

fromdatetimeimportdatetime#后续用于测试运行时间

classsewImage(object):#拼接图片的类

def__init__(self,imagePath=[]):

self.imgPath=imagePath#imgPath 是储存图片路径的数组

self.imgdatas=[]#imgdatas 是储存每张图片的像素信息的数组

self.width=-1#截图宽度

self.height=-1#截图高度

self.curr=0#当前图片的位置

#打开图片

defopenImages(self):

if(len(self.imgPath)<2):

raiseValueError("图片数量小于 2 张")

forpathinself.imgPath:

img=Image.open(path)#打开图片

img_RGB=img.convert("RGB")#转换成 RGB 模式

imgdata=img_RGB.getdata()#获取图片的像素信息

#判断尺寸是否一致, 要求每张图片的宽高一致(高度其实可以不一致, 不过稍微麻烦点)

if(self.width==-1):

self.width,self.height=img_RGB.size

else:

w,h=img_RGB.size

if(w!=self.widthorh!=self.height):

raiseValueError("图片尺寸不一致")

self.imgdatas.append(imgdata)#将获取的像素信息加入 imgdatas 数组

寻找相同的头部

在 iOS 中的导航栏通常是磨砂半透明的, 所以实际上无论微信还是其他 app 的导航栏, 两张截图的颜色通常是有差别的, 如图所示, 因此我们再比较是否两个像素是否相同的时候, 应该允许一定的误差范围, 我试验后发现 RGB 分别相差在 25 以内可以认为是相同的 (这个可根据需求自行调整) 同时, 截图时状态栏的图标可能也会发生细微变化, 比如信号强度不同, 因此我们也得设置一定的误差允许范围, 在此我设置了一行中超过 90% 的像素是相同的, 即认为该行相同

导航栏的颜色可能不同, 状态栏可能有细微差别

代码如下# 寻找相同的头部

deffindHead(self,hitRate=0.9):#hitRate: 一行中超过 hitRate*width 个相同的像素即认为该行相同

imgdatas=self.imgdatas

curr=self.curr

width=self.width

if(curr>=len(imgdatas)-1):

return

equalPixel=0

head=self.height#相同头的位置, 默认为 height

imgdata1=imgdatas[curr]

imgdata2=imgdatas[curr+1]

forhinrange(head):

forwinrange(width):#比对一行

r1,g1,b1=imgdata1[width*h+w]

r2,g2,b2=imgdata2[width*h+w]

if(abs(r1-r2)<25andabs(g1-g2)<25andabs(b1-b2)<25):

equalPixel+=1

if(equalPixel

head=h

break

equalPixel=0

self.curr+=1#当前位置后移一位

returnhead

拼接图片

拼接部分是按这样的顺序, 两张两张拼接:

-> [ 图 1 ] [ 图 2 ] [ 图 3 ] [ 图 4 ]

-> [ 图 1 图 2 ] [ 图 3 ] [ 图 4 ]

-> [ 图 1 图 2 图 3 ] [ 图 4 ]

-> [ 图 1 图 2 图 3 图 4 ]

先调用上面的函数寻找图 1 和图 2 的相同的头部, 将图 2 的头部的那一行与图 1 从底至顶依次比较每一行, 为了提高准确率, 我再同时比较图 2 头部的后 15 行, 与图 1 的对应位置的行# 拼接两张图

defgetNewImgData(self):

newHeight=self.height

newImgData=list(self.imgdatas[0])

width=self.width

height=self.height

foriinrange(len(self.imgdatas)-1):

equalPixel=0

tail=newHeight

imgdata2=list(self.imgdatas[i+1])

head=self.findHead()

offsetLine=15#同时检查 offsetLine 行是否一致

forhinrange(newHeight-offsetLine)[::-1]:

forwinrange(width):

r1,g1,b1=imgdata2[w+width*head]

r2,g2,b2=newImgData[w+width*h]

r3,g3,b3=imgdata2[w+width*(head+offsetLine)]

r4,g4,b4=newImgData[w+width*(h+offsetLine)]

if(r1==r2andg1==g2andb1==b2andr3==r4andg3==g4andb3==b4):

equalPixel+=1

if(h

break

if(equalPixel==width):

tail=h

break

equalPixel=0

newImgData=newImgData[:width*tail]

newImgData.extend(imgdata2[width*head:])

newHeight=tail+(height-head)

return(newImgData,newHeight)

完成拼图

最后再定义一个 sew 函数组织起来前面的函数, 拼图并保存defsew(self,imagePath=[]):

if(imagePath!=[]):

self.imgPath=imagePath

self.curr=0

self.openImages()#加载图片

newImgData,newHeight=self.getNewImgData()

newImg=Image.new('RGB',(self.width,newHeight))

newImg.putdata(newImgData)

newImg.save('new.png')

print('拼图完成!')

测试的时候只需要这样即可sewImg=sewImage(["pic1.png","pic2.png","pic3.png"])

begin=datetime.now()

sewImg.sew()

end=datetime.now()

total=end.timestamp()-begin.timestamp()

print("共耗时:%sms"%(total*1000))

源代码放在了 GitHub 上: https://github.com/ZitionChan/sewImage

效果

变成这个

优化

显然, 逐个像素比较还是比较慢的, 可以看到拼接上面的三张图, 需要 1.8 秒

因此我们需要寻找更好的方法来优化一下

来源: http://www.jianshu.com/p/b345a3689e3c

python实现长截图_用 Python 实现长截图拼接相关推荐

  1. python selenium截图_利用 Python + Selenium 实现对页面的指定元素截图(可截长图元素)...

    对WebElement截图 WebDriver.Chrome自带的方法只能对当前窗口截屏,且不能指定特定元素.若是需要截取特定元素或是窗口超过了一屏,就只能另辟蹊径了. WebDriver.Phant ...

  2. python 跳一跳辅助_使用Python制作微信跳一跳辅助

    1.  前言 微信的跳一跳相信大家都很熟悉了,而且现在各种外挂.辅助也是满天飞,反正本人的好友排行榜中已经是八九百都不足为奇了.某宝上一搜一堆结果,最低的居然只要3块多,想刷多少分就刷多少分,真是离谱 ...

  3. python出现的意义_[转]Python中下划线以及命名空间的意义

    Python 用下划线作为变量前缀和后缀指定特殊变量/方法. 主要存在四种情形 1. 1. object # public 2. __object__ # special, python system ...

  4. python中级项目下载_中级Python复习:教程,项目思想和技巧

    python中级项目下载 本文旨在向Python初学者和开发人员介绍Python中使用的一些关键概念,这些概念一开始就没有讲授. 如果您可以创建二次方根求解器,则可以理解本文. 这些是我一天之内没有学 ...

  5. python 运行程序代码_一些python程序

    <从问题到程序:用Python学编程和计算>--1.2 Python语言简介 本节书摘来自华章计算机<从问题到程序:用Python学编程和计算>一书中的第1章,第1.2节,作者 ...

  6. python大牛 关东升_《Python从小白到大牛》第4章 Python语法基础

    本章主要为大家介绍Python的一些语法,其中包括标识符.关键字.常量.变量.表达式.语句.注释.模块和包等内容. 标识符和关键字 任何一种计算机语言都离不开标识符和关键字,因此下面将详细介绍Pyth ...

  7. python之禅 中文_《Python之禅》中对于Python编程过程中的一些建议

    <Python之禅>中对于Python编程过程中的一些建议 来源:中文源码网    浏览: 次    日期:2018年9月2日 [下载文档:  <Python之禅>中对于Pyt ...

  8. Python按键精灵自动化_安装Python

    嘀嘀嘀!大家好,我是PY拓海. 前面和大家说了那么多,话不多说,我们开始吧! 要使用Python编程,我们需要在电脑上搭一个Python的编程环境,步骤非常简单,下面我给大家演示. 下载Python( ...

  9. 初学者先学python语音好吗_献给Python初学者 零基础学习Python能学会吗

    献给Python初学者 零基础学习Python能学会吗 时间:2018-01-08     来源:零基础学习Python方法讲解 零基础学习Python能学会吗?这个问题几乎是所有初学Python的小 ...

  10. python 还原九宫格图片_用Python做一个好玩的朋友圈九宫格抽奖

    最近在朋友圈看到个好玩的抽奖九宫格: 随便点开一个: 设计思路 以朋友圈中看到的1号图做参考,我们需要准备 300*900 的白色底图,搞笑表情图,广告语,中间一个醒目的数字编号,外加下方的嘲讽&qu ...

最新文章

  1. boost::graph模块实现一个只读隐式加权图的简单示例的测试程序
  2. 【算法竞赛学习】数字中国创新大赛智慧海洋建设-Task2数据分析
  3. python函数-函数进阶
  4. 多媒体计算机是多媒体教室的核心部件,浅析多媒体教室的设备配置
  5. jeecg集成积木报表错误_6688种玩法的电子积木,是什么体验?「中外玩具网测评」...
  6. 大数据之-Hadoop3.x_MapReduce_全排序案例---大数据之hadoop3.x工作笔记0115
  7. 智能一代云平台(二十四):已安装的Nginx上安装echo插件
  8. else列表推导式 if python_python3基础09列表推导式|迭代器|生成器|匿名函数
  9. FPGA实现任意分频 为所欲为——教你什么才是真正的任意分频
  10. 建立 arm-linux 交叉编译环境
  11. 小米/VIVO/OPPO全系列救砖+解锁+工具+教程+激活账户技术
  12. Visual C++ MSDEV.exe 应用程序错误
  13. 忘记Windows服务器密码怎么办
  14. GateWay新一代网关
  15. 为何数据分析师更容易获得高薪工作?
  16. 父亲发现高三女儿早恋 机智做法让网友惊呆
  17. 现货黄金历史价格涨了几倍?
  18. 给你一个水杯如何进行测试?
  19. 设定是否使用IOB中的寄存器
  20. 【MySQL】MySQL数据库结构与操作

热门文章

  1. 发SCI,审稿人意见有一条是“English should be improved”,应该怎样回复?
  2. Distractor-aware Siamese Networks for Visual Object Tracking 论文学习
  3. 面经 | 腾讯/阿里/京东/头条/旷视等20+企业计算机视觉算法岗面经吐血整理
  4. sso单点登录与Jsonp
  5. mybatis mysql ssh_SSH Mybatis 框架
  6. 计算机用户接入广域网的技术,第五章广域网接入技术全解.ppt
  7. 关于Java实现“1000个鸡蛋/苹果分装到10个篮子/箱子里,可表述1000以内任何正整数”的程序
  8. 计算机选择题在线,计算机考试选择题
  9. Microsoft Visio 2010 - 编辑属性值
  10. 块级、内联、内联块级