日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python实现图片拼接长图_用Python实现长截图拼接

發布時間:2023/12/10 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python实现图片拼接长图_用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()可以得到像素信息

from PIL import Image #引入PIL

from datetime import datetime #后續用于測試運行時間

class sewImage(object): #拼接圖片的類

def __init__(self,imagePath=[]):

self.imgPath = imagePath #imgPath是儲存圖片路徑的數組

self.imgdatas = [] #imgdatas是儲存每張圖片的像素信息的數組

self.width = -1 #截圖寬度

self.height = -1 #截圖高度

self.curr = 0 #當前圖片的位置

#打開圖片

def openImages(self):

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

raise ValueError("圖片數量小于2張")

for path in self.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.width or h != self.height):

raise ValueError("圖片尺寸不一致")

self.imgdatas.append(imgdata) #將獲取的像素信息加入imgdatas數組

尋找相同的頭部

在iOS中的導航欄通常是磨砂半透明的,所以實際上無論微信還是其他app的導航欄,兩張截圖的顏色通常是有差別的,如圖所示,因此我們再比較是否兩個像素是否相同的時候,應該允許一定的誤差范圍,我試驗后發現RGB分別相差在25以內可以認為是“相同的”。(這個可根據需求自行調整)同時,截圖時狀態欄的圖標可能也會發生細微變化,比如信號強度不同,因此我們也得設置一定的誤差允許范圍,在此我設置了一行中超過90%的像素是“相同的”,即認為該行相同。

導航欄的顏色可能不同,狀態欄可能有細微差別

代碼如下

#尋找相同的頭部

def findHead(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]

for h in range(head):

for w in range(width):#比對一行

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

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

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

equalPixel +=1

if(equalPixel

head = h

break

equalPixel=0

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

return head

拼接圖片

拼接部分是按這樣的順序,兩張兩張拼接:

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

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

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

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

先調用上面的函數尋找圖1和圖2的相同的頭部,將圖2的頭部的那一行與圖1從底至頂依次比較每一行,為了提高準確率,我再同時比較圖2頭部的后15行,與圖1的對應位置的行。

#拼接兩張圖

def getNewImgData(self):

newHeight = self.height

newImgData = list(self.imgdatas[0])

width = self.width

height = self.height

for i in range(len(self.imgdatas)-1):

equalPixel=0

tail = newHeight

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

head = self.findHead()

offsetLine = 15 #同時檢查offsetLine行是否一致

for h in range(newHeight-offsetLine)[::-1]:

for w in range(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==r2 and g1==g2 and b1==b2 and r3==r4 and g3==g4 and b3==b4):

equalPixel+=1

if(h < newHeight-height): #沒有找到相同行

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函數組織起來前面的函數,拼圖并保存

def sew(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))

優化

顯然,逐個像素比較還是比較慢的,可以看到拼接上面的三張圖,需要1.8秒

因此我們需要尋找更好的方法來優化一下

識別拼接尾部的優化

在拼接尾部的時候我們遍歷了每個像素,實際上我們只是需要判斷兩行是否完全一致,因此我們可以切片出每行的內容,直接判斷即可,這樣則可以去掉一個for循環,效率會提高不少。

我們可以將原來的修改成下面這樣

#拼接兩張圖

def __getNewImgData(self):

newHeight = self.__height

newImgData = list(self.__imgdatas[0])

width = self.__width

height = self.__height

for i in range(len(self.__imgdatas)-1):

tail = newHeight

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

head = self.__findHead()

offsetLine = 15 #同時檢查offsetLine行是否一致

#####改動部分#####

for h in range(newHeight-offsetLine)[::-1]:

line1 = imgdata2[width*head:width*(head+1)]

line2 = newImgData[width*h:width*(h+1)]

line3 = imgdata2[width*(head+offsetLine):width*(head+offsetLine+1)]

line4 = newImgData[width*(h+offsetLine):width*(h+offsetLine+1)]

if(h < newHeight-height): #沒有找到相同行

break

if(line1==line2 and line3 == line4):

tail = h

break

####改動部分結束####

newImgData = newImgData[:width*tail]

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

newHeight = tail + (height - head)

return (newImgData,newHeight)

改動后拼接3張圖快了有半秒

效果

變成這個

new.png

總結

以上是生活随笔為你收集整理的python实现图片拼接长图_用Python实现长截图拼接的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。