全解析MeanShift傳統(tǒng)目標(biāo)跟蹤算法
一、均值漂移(MeanShift)
該算法尋找離散樣本的最大密度,并且重新計(jì)算下一幀的最大密度,這個(gè)算法的特點(diǎn)就是可以給出目標(biāo)移動(dòng)的方向。

meanshift算法的原理很簡(jiǎn)單。假設(shè)你有一堆點(diǎn)集,還有一個(gè)小的窗口,這個(gè)窗口可能是圓形的,現(xiàn)在你可能要移動(dòng)這個(gè)窗口到點(diǎn)集密度最大的區(qū)域當(dāng)中。
最開(kāi)始的窗口是藍(lán)色圓環(huán)的區(qū)域,命名為C1。藍(lán)色圓環(huán)的圓心用一個(gè)藍(lán)色的矩形標(biāo)注,命名為C1_o。
而窗口中所有點(diǎn)的點(diǎn)集構(gòu)成的質(zhì)心在藍(lán)色圓形點(diǎn)C1_r處,顯然圓環(huán)的形心和質(zhì)心并不重合。所以,移動(dòng)藍(lán)色的窗口,使得形心與之前得到的質(zhì)心重合。在新移動(dòng)后的圓環(huán)的區(qū)域當(dāng)中再次尋找圓環(huán)當(dāng)中所包圍點(diǎn)集的質(zhì)心,然后再次移動(dòng),通常情況下,形心和質(zhì)心是不重合的。不斷執(zhí)行上面的移動(dòng)過(guò)程,直到形心和質(zhì)心大致重合結(jié)束。這樣,最后圓形的窗口會(huì)落到像素分布最大的地方,也就是圖中的綠色圈,命名為C2。
meanshift算法除了應(yīng)用在視頻追蹤當(dāng)中,在聚類,平滑等等各種涉及到數(shù)據(jù)以及非監(jiān)督學(xué)習(xí)的場(chǎng)合當(dāng)中均有重要應(yīng)用,是一個(gè)應(yīng)用廣泛的算法。
如果不知道預(yù)先要跟蹤的目標(biāo),就可以采用這種巧妙地辦法,加設(shè)定條件,使能動(dòng)態(tài)的開(kāi)始跟蹤(和停止跟蹤)視頻的某些區(qū)域,(如可以采用預(yù)先訓(xùn)練好的SVM進(jìn)行目標(biāo)的檢測(cè),然后開(kāi)始使用均值漂移MeanShift跟蹤檢測(cè)到的目標(biāo))
所以一般是分兩個(gè)步驟:1.標(biāo)記感興趣區(qū)域 2.跟蹤該區(qū)域
二、流程
圖像是一個(gè)矩陣信息,如何在一個(gè)視頻當(dāng)中使用meanshift算法來(lái)追蹤一個(gè)運(yùn)動(dòng)的物體呢?大致流程如下:
| meanshift流程 |
| 1.首先在圖像上選定一個(gè)目標(biāo)區(qū)域 |
| 2.計(jì)算選定區(qū)域的直方圖分布,一般是HSV色彩空間的直方圖 |
| 3.對(duì)下一幀圖像 b 同樣計(jì)算直方圖分布 |
| 4.計(jì)算圖像 b 當(dāng)中與選定區(qū)域直方圖分布最為相似的區(qū)域,使用meanshift算法將選定區(qū)域沿著最為相似的部分進(jìn)行移動(dòng),直到找到最相似的區(qū)域,便完成了在圖像b中的目標(biāo)追蹤。 |
| 5.重復(fù)3到4的過(guò)程,就完成整個(gè)視頻目標(biāo)追蹤。 |
| 通常情況下我們使用直方圖反向投影得到的圖像和第一幀目標(biāo)對(duì)象的起始位置,當(dāng)目標(biāo)對(duì)象的移動(dòng)會(huì)反映到直方圖反向投影圖中,meanshift算法就把我們的窗口移動(dòng)到反向投影圖像中灰度密度最大的區(qū)域了。 |
實(shí)現(xiàn)Meanshift的主要流程是︰
- 讀取視頻文件:cv.videoCapture()
- 感興趣區(qū)域設(shè)置:獲取第一幀圖像,并設(shè)置目標(biāo)區(qū)域,即感興趣區(qū)域
- 計(jì)算直方圖:計(jì)算感興趣區(qū)域的HSV直方圖,并進(jìn)行歸一化
- 目標(biāo)追蹤︰設(shè)置窗口搜索停止條件,直方圖反向投影,進(jìn)行目標(biāo)追蹤,并在目標(biāo)位置繪制矩形框
三、代碼
opencv API
cv2.meanShift(probImage, window, criteria)
參數(shù):
- probImage:ROI區(qū)域,即目標(biāo)直方圖的反向投影
- window:初始搜索窗口,就是定義ROI的rect
- criteria:確定窗口搜索停止的準(zhǔn)則,主要有迭代次數(shù)達(dá)到設(shè)置的最大值,窗口中心的漂移值大于某個(gè)設(shè)定的限值等
3.1 meanshift+固定框的代碼
import cv2 as cv
# 創(chuàng)建讀取視頻的對(duì)象
cap = cv.VideoCapture("E:\Python-Code/videodataset/enn.mp4")
# 獲取第一幀位置,并指定目標(biāo)位置
ret, frame = cap.read()
c, r, h, w = 530, 160, 300, 320
track_window = (c, r, h, w)
# 指定感興趣區(qū)域
roi = frame[r:r + h, c:c + w]
# 計(jì)算直方圖
# 轉(zhuǎn)換色彩空間
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
# 計(jì)算直方圖
roi_hist = cv.calcHist([hsv_roi], [0], None, [180], [0, 180])
# 歸一化
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)
# 目標(biāo)追蹤
# 設(shè)置窗口搜索終止條件:最大迭代次數(shù),窗口中心漂移最小值
term_crit = (cv.TermCriteria_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)
while True:
ret, frame = cap.read()
if ret:
# 計(jì)算直方圖的反向投影
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
# 進(jìn)行meanshift追蹤
ret, track_window = cv.meanShift(dst, track_window, term_crit)
# 將追蹤的位置繪制在視頻上,并進(jìn)行顯示
x, y, w, h = track_window
img = cv.rectangle(frame, (x, y), (x + w, y + h), 255, 2)
cv.imshow("frame", img)
if cv.waitKey(20) & 0xFF == ord('q'):
break
else:
break
# 資源釋放
cap.release()
cv.destroyAllWindows()
缺點(diǎn):這種就是一開(kāi)始設(shè)定了具體框的大小和位置,不能根據(jù)實(shí)際情況自己進(jìn)行更改。
初始框的位置很重要。以Meanshift為例,它的工作原理是根據(jù)概率密度來(lái)尋找最大的密度區(qū)域,但如果我們一開(kāi)始將跟蹤框放置在了一個(gè)直方圖反向投影圖中全黑的區(qū)域(密度為0),這會(huì)導(dǎo)致其無(wú)法正確向物體方向進(jìn)行移動(dòng),從而導(dǎo)致卡死在那里。
我們已追蹤視頻的初始幀(第一幀)為例,我們假設(shè)想要跟蹤其中的一個(gè)物體,我們就得將跟蹤框放置到跟蹤物體周邊的區(qū)域才能讓程序正常運(yùn)行,但我們其實(shí)很難知道一張圖片中跟蹤物體的具體位置。 舉個(gè)簡(jiǎn)單的例子,比如我現(xiàn)在有一張圖片,我們要跟蹤圖片右下角的一個(gè)物體,但是我不知道這個(gè)物體的坐標(biāo)范圍,所以我只能一次一次的去嘗試(在代碼中修改初始框的位置后,看看程序的運(yùn)行情況)來(lái)保證代碼能夠正常運(yùn)行,但這樣代碼的普適性很差,因?yàn)槊慨?dāng)要更改跟蹤對(duì)象的時(shí)候,都需要反復(fù)的修改,才能應(yīng)對(duì)當(dāng)前的情況,這樣實(shí)在是有點(diǎn)麻煩。
3.2 優(yōu)化:meanshift+鼠標(biāo)選擇
這里介紹一個(gè)函數(shù),起名為:cv2.selectROI,使用這個(gè)函數(shù),我們就能夠?qū)崿F(xiàn)手動(dòng)畫取我們的跟蹤框,其函數(shù)語(yǔ)法如下所示:
track_window=cv2.selectROI('frameName', frame)參數(shù):
- framename:顯示窗口的畫布名
- frame:具體的幀
import cv2
import numpy as np
# 讀取視頻
cap=cv2.VideoCapture('E:\Python-Code/videodataset/enn.mp4')
# 獲取第一幀位置,參數(shù)ret 為True 或者False,代表有沒(méi)有讀取到圖片 第二個(gè)參數(shù)frame表示截取到一幀的圖片
ret,frame=cap.read()
#我這里畫面太大了所以縮小點(diǎn)——但是縮小后我的就會(huì)報(bào)錯(cuò)
# frame=cv2.resize(frame,None,None,fx=1/2,fy=1/2,interpolation=cv2.INTER_CUBIC)
#跟蹤框
track_window=cv2.selectROI('img', frame)
#獲得綠色的直方圖
# 轉(zhuǎn)換色彩空間
hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
mask=cv2.inRange(hsv,np.array((35,43,46)),np.array((77,255,255)))
# 計(jì)算直方圖
hist=cv2.calcHist([hsv],[0],mask,[181],[0,180])
# hist=cv2.calcHist([hsv],[0],[None],[180],[0,180])
# 歸一化
cv2.normalize(hist,hist,0,255,cv2.NORM_MINMAX)
# 目標(biāo)追蹤
# 設(shè)置窗口搜索終止條件:最大迭代次數(shù),窗口中心漂移最小值
term_crit=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT,10,1)
while True:
ret,frame=cap.read()
# frame = cv2.resize(frame, None, None, fx=1 / 2, fy=1 / 2, interpolation=cv2.INTER_CUBIC)
if ret== True:
# 計(jì)算直方圖的反向投影
hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
dst=cv2.calcBackProject([hsv],[0],hist,[0,180],1)
# 進(jìn)行meanshift追蹤
ret,track_window=cv2.meanShift(dst,track_window,term_crit)
# 將追蹤的位置繪制在視頻上,并進(jìn)行顯示
x,y,w,h = track_window
img = cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
(x,y)=img.shape[:2]
cv2.imshow('img',img)
if cv2.waitKey(1)==ord('q'):
break
else:
break
# 資源釋放
cap.release()
cv2.destroyAllWindows()運(yùn)行上面的代碼,會(huì)跳出一個(gè)窗口,窗口上顯示的就是我們載入的視頻的第一幀,我們用鼠標(biāo)拖動(dòng),畫出我們要跟蹤的物體的位置
但是這里需要注意的是,這個(gè)函數(shù)每次調(diào)用只能畫一個(gè)矩形(C++版本中的OpenCV可以一次畫好多個(gè)),如果想畫好多個(gè)矩形的話,可以使用while循環(huán):
bboxes = []
colors = []
while 1:
bbox = cv2.selectROI('MultiTracker', frame)
bboxes.append(bbox)
colors.append((randint(0, 255), randint(0, 255), randint(0, 255)))
print("按下q鍵退出,按下其他鍵繼續(xù)畫下一個(gè)框")
if cv2.waitKey(0) & 0xFF==ord('q'):
break
print('選取的邊框?yàn)閧}'.format(bboxes))但是完整的代碼并沒(méi)有跑通
3.3 meanshift+自己實(shí)現(xiàn)函數(shù)
這個(gè)效果最好,但是不懂為什么會(huì)這樣?為什么調(diào)用庫(kù)函數(shù)反而效果不好呢?
import math
import numpy as np
import cv2
def get_tr(img):
# 定義需要返回的參數(shù)
mouse_params = {'x': None, 'width': None, 'height': None,
'y': None, 'temp': None}
cv2.namedWindow('image')
# 鼠標(biāo)框選操作函數(shù)
cv2.setMouseCallback('image', on_mouse, mouse_params)
cv2.imshow('image', img)
cv2.waitKey(0)
return [mouse_params['x'], mouse_params['y'], mouse_params['width'],
mouse_params['height']], mouse_params['temp']
def on_mouse(event, x, y, flags, param):
global img, point1
img2 = img.copy()
if event == cv2.EVENT_LBUTTONDOWN: # 左鍵點(diǎn)擊
point1 = (x, y)
cv2.circle(img2, point1, 10, (0, 255, 0), 5)
cv2.imshow('image', img2)
elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): # 按住左鍵拖曳
cv2.rectangle(img2, point1, (x, y), (255, 0, 0), 5)
cv2.imshow('image', img2)
elif event == cv2.EVENT_LBUTTONUP: # 左鍵釋放
point2 = (x, y)
cv2.rectangle(img2, point1, point2, (0, 0, 255), 5)
cv2.imshow('image', img2)
# 返回框選矩形左上角點(diǎn)的坐標(biāo)、矩形寬度、高度以及矩形包含的圖像
param['x'] = min(point1[0], point2[0])
param['y'] = min(point1[1], point2[1])
param['width'] = abs(point1[0] - point2[0])
param['height'] = abs(point1[1] - point2[1])
param['temp'] = img[param['y']:param['y'] + param['height'],
param['x']:param['x'] + param['width']]
def main():
global img
cap = cv2.VideoCapture("E:\Python-Code/videodataset/enn.mp4")
# 獲取視頻第一幀
ret, frame = cap.read()
img = frame
# 框選目標(biāo)并返回相應(yīng)信息:rect為四個(gè)信息,temp為框選出來(lái)的圖像
rect, temp = get_tr(img)
print(temp)
(a, b, c) = temp.shape
y = [a / 2, b / 2]
# 計(jì)算目標(biāo)圖像的權(quán)值矩陣
m_wei = np.zeros((a, b))
for i in range(a):
for j in range(b):
z = (i - y[0]) ** 2 + (j - y[1]) ** 2
m_wei[i, j] = 1 - z / (y[0] ** 2 + y[1] ** 2)
# 計(jì)算目標(biāo)權(quán)值直方圖
C = 1 / sum(sum(m_wei))
hist1 = np.zeros(16 ** 3)
for i in range(a):
for j in range(b):
q_b = math.floor(float(temp[i, j, 0]) / 16)
q_g = math.floor(float(temp[i, j, 1]) / 16)
q_r = math.floor(float(temp[i, j, 2]) / 16)
q_temp1 = q_r * 256 + q_g * 16 + q_b
hist1[int(q_temp1)] = hist1[int(q_temp1)] + m_wei[i, j]
hist1 = hist1 * C
# 接著讀取視頻并進(jìn)行目標(biāo)跟蹤
while (1):
ret, frame = cap.read()
if ret == True:
Img = frame
num = 0
Y = [1, 1]
# mean shift迭代
while (np.sqrt(Y[0] ** 2 + Y[1] ** 2) > 0.5) & (num < 20):
num = num + 1
# 計(jì)算候選區(qū)域直方圖
temp2 = Img[int(rect[1]):int(rect[1] + rect[3]), int(rect[0]):int(rect[0] + rect[2])]
hist2 = np.zeros(16 ** 3)
q_temp2 = np.zeros((a, b))
for i in range(a):
for j in range(b):
q_b = math.floor(float(temp2[i, j, 0]) / 16)
q_g = math.floor(float(temp2[i, j, 1]) / 16)
q_r = math.floor(float(temp2[i, j, 2]) / 16)
q_temp2[i, j] = q_r * 256 + q_g * 16 + q_b
hist2[int(q_temp2[i, j])] = hist2[int(q_temp2[i, j])] + m_wei[i, j]
hist2 = hist2 * C
w = np.zeros(16 ** 3)
for i in range(16 ** 3):
if hist2[i] != 0:
w[i] = math.sqrt(hist1[i] / hist2[i])
else:
w[i] = 0
sum_w = 0
sum_xw = [0, 0]
for i in range(a):
for j in range(b):
sum_w = sum_w + w[int(q_temp2[i, j])]
sum_xw = sum_xw + w[int(q_temp2[i, j])] * np.array([i - y[0], j - y[1]])
Y = sum_xw / sum_w
# 位置更新
rect[0] = rect[0] + Y[1]
rect[1] = rect[1] + Y[0]
v0 = int(rect[0])
v1 = int(rect[1])
v2 = int(rect[2])
v3 = int(rect[3])
pt1 = (v0, v1)
pt2 = (v0 + v2, v1 + v3)
# 畫矩形
IMG = cv2.rectangle(Img, pt1, pt2, (0, 0, 255), 2)
cv2.imshow('IMG', IMG)
k = cv2.waitKey(60) & 0xff
if k == 27:
break
else:
break
if __name__ == '__main__':
main()四、補(bǔ)充知識(shí)
4.1 直方圖
構(gòu)建圖像的直方圖需要使用到函數(shù)cv2.calcHist,其常用函數(shù)語(yǔ)法如下所示:
hist=cv2.calcHist(images, channels, mask, histSize, ranges) images:輸入的圖像 channels:選擇圖像的通道,如果是三通道的話就可以是[0],[1],[2] mask:掩膜,是一個(gè)大小和image一樣的np數(shù)組,其中把需要處理的部分指定為1,不需要處理的部分指定為0,一般設(shè)置為None,如果有mask,會(huì)先對(duì)輸入圖像進(jìn)行掩膜操作 histSize:使用多少個(gè)bin(柱子),一般為256,但如果是H值就是181 ranges:像素值的范圍,一般為[0,255]表示0~255,對(duì)于H通道而言就是[0,180]
需要注意的是,這里除了mask以外,其余的幾個(gè)參數(shù)都要加上[],如下所示:
hist=cv2.calcHist([img],[0],mask,[181],[0,180])
4.2 歸一化
這個(gè)時(shí)候我們還需要使用一種歸一化的方法來(lái)對(duì)彩色直方圖中的數(shù)量值進(jìn)行規(guī)范化。 現(xiàn)有的直方圖中的數(shù)值為對(duì)應(yīng)像素的數(shù)量,其中圖中出現(xiàn)數(shù)量最多的像素的數(shù)量值(最高的柱子對(duì)應(yīng)的y軸數(shù)值)我們記為max的話,整個(gè)直方圖y方向上的取值范圍就是[0,max],我們需要把這個(gè)范圍縮減到[0,255],
這里我們需要使用到cv2.normalize函數(shù),函數(shù)主要語(yǔ)法如下所示:
cv2.normalize(src,dst, alpha,beta, norm_type) ·src-輸入數(shù)組。 ·dst-與SRC大小相同的輸出數(shù)組。 ·α-范數(shù)值在范圍歸一化的情況下歸一化到較低的范圍邊界。 ·β-上限范圍在范圍歸一化的情況下;它不用于范數(shù)歸一化。 ·范式-規(guī)范化類型(見(jiàn)下面詳細(xì)介紹)。
這里我們需要注意的是范式-規(guī)范化類型,這里有以下幾種選擇。
NORM_MINMAX:數(shù)組的數(shù)值被平移或縮放到一個(gè)指定的范圍,線性歸一化。 NORM_INF:歸一化數(shù)組的(切比雪夫距離)L∞范數(shù)(絕對(duì)值的最大值) NORM_L1: 歸一化數(shù)組的(曼哈頓距離)L1-范數(shù)(絕對(duì)值的和) NORM_L2: 歸一化數(shù)組的(歐幾里德距離)L2-范數(shù)
上面的名詞看起來(lái)很高大上,其實(shí)是很簡(jiǎn)單,我們一一講解下。(不是很感興趣的只要看下第一個(gè)NORM_MINMAX即可,剩下的三個(gè)可以不看)
首先是NORM_MINMAX,這個(gè)是我們最常用的一種歸一化方法。舉個(gè)例子,我們上面提到的最高的柱子對(duì)應(yīng)的y軸坐標(biāo)為max,如果我們使用這種方法,想要縮放到的指定的范圍為[0,255],那么max就會(huì)直接被賦值為255,其余的柱子也會(huì)隨之一樣被壓縮(類似于相似三角形那樣的縮放感覺(jué))。 沒(méi)錯(cuò),很簡(jiǎn)單得就介紹完了一種,不是很想了解其他幾個(gè)的讀者可以直接跳過(guò)本小節(jié)剩下來(lái)的內(nèi)容了,因?yàn)槭O氯N不是很常用。
4.3 直方圖反投影
簡(jiǎn)單來(lái)說(shuō),它會(huì)輸出與輸入圖像(待搜索)同樣大小的圖像,其中的每一個(gè)像素值代表了輸入圖像上對(duì)應(yīng)點(diǎn)屬于目標(biāo)對(duì)象(我們需要跟蹤的目標(biāo))的概率。用更簡(jiǎn)單的話來(lái)解釋,輸出圖像中像素值越高(越白)的點(diǎn)就越可能代表我們要搜索的目標(biāo) (在輸入圖像所在的位置)。 而對(duì)于灰度圖而言,其只有一個(gè)通道,取值范圍為0到255,所以我們之前在歸一化的時(shí)候?qū)⒅狈綀D的y軸坐標(biāo)的取值范圍壓縮到了0-255的范圍內(nèi),就是為了這里可以直接賦值。
越暗的地方說(shuō)明屬于跟蹤部分的可能性越低,越亮的地方屬于跟蹤部分的可能性越高。 這里使用到的函數(shù)為cv2.calcBackProject,函數(shù)語(yǔ)法如下所示:
dst=cv2.calcBackProject(image,channel,hist,range,scale) image:輸入圖像 channel:用來(lái)計(jì)算反向投影的通道數(shù),與產(chǎn)生直方圖對(duì)應(yīng)的通道應(yīng)一致 hist:作為輸入的直方圖 range:直方圖的取值范圍 scale:輸出圖像的縮放比,一般為1,保持與輸入圖像一樣的大小 dst:輸出圖像 注意:除了hist和scale外,其他的參數(shù)都要加上[]
例如:
dst=cv2.calcBackProject([hsv],[0],hist,[0,180],1)
到此這篇關(guān)于傳統(tǒng)目標(biāo)跟蹤——MeanShift算法的文章就介紹到這了,更多相關(guān)MeanShift跟蹤算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用 PyTorch-BigGraph 構(gòu)建和部署大規(guī)模圖嵌入的完整步驟
本文深入探討了使用 PyTorch-BigGraph (PBG) 構(gòu)建和部署大規(guī)模圖嵌入的完整流程,涵蓋了從環(huán)境設(shè)置、數(shù)據(jù)準(zhǔn)備、模型配置與訓(xùn)練,到高級(jí)優(yōu)化技術(shù)、評(píng)估指標(biāo)、部署策略以及實(shí)際案例研究等各個(gè)方面,感興趣的朋友跟隨小編一起看看吧2024-11-11
Python?查找算法之二分查找線性查找與哈希查找實(shí)例探究
這篇文章主要為大家介紹了Python查找算法探究之二分查找、線性查找與哈希查找的實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Python實(shí)現(xiàn)識(shí)別圖片和掃描PDF中的文字
在處理掃描的PDF和圖片時(shí),文字信息往往無(wú)法直接編輯、搜索或復(fù)制,這給信息提取和分析帶來(lái)了諸多不便,所以本文將介紹如何使用Python及相關(guān)OCR庫(kù)實(shí)現(xiàn)對(duì)圖片和掃描PDF中文字的識(shí)別,需要的可以了解下2025-02-02
淺談Python2.6和Python3.0中八進(jìn)制數(shù)字表示的區(qū)別
下面小編就為大家?guī)?lái)一篇淺談Python2.6和Python3.0中八進(jìn)制數(shù)字表示的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Python中reduce()函數(shù)的語(yǔ)法參數(shù)與作用詳解
這篇文章主要介紹了Python中reduce()函數(shù)的語(yǔ)法參數(shù)與作用詳解,reduce函數(shù)是通過(guò)函數(shù)對(duì)迭代器對(duì)象中的元素進(jìn)行遍歷操作,Python3.x中reduce函數(shù)已經(jīng)從內(nèi)置函數(shù)中取消了,轉(zhuǎn)而放在functools模塊中,需要的朋友可以參考下2023-08-08
淺析Python中g(shù)etattr和getattribute的調(diào)用
在Python中,getattr和getattribute是兩個(gè)用于屬性訪問(wèn)的重要函數(shù),它們可以在運(yùn)行時(shí)動(dòng)態(tài)地獲取對(duì)象的屬性或自定義屬性訪問(wèn)行為,下面我們就來(lái)學(xué)習(xí)一下它們的具體用法吧2023-11-11
Python實(shí)現(xiàn)判斷給定列表是否有重復(fù)元素的方法
這篇文章主要介紹了Python實(shí)現(xiàn)判斷給定列表是否有重復(fù)元素的方法,列舉了2種列表判斷方法,涉及Python針對(duì)列表的遍歷、統(tǒng)計(jì)、判斷等相關(guān)操作技巧,需要的朋友可以參考下2018-04-04
PyQt5實(shí)現(xiàn)用戶登錄GUI界面及登錄后跳轉(zhuǎn)
PyQt5是強(qiáng)大的GUI工具之一,通過(guò)其可以實(shí)現(xiàn)優(yōu)秀的桌面應(yīng)用程序。本文主要介紹了PyQt5實(shí)現(xiàn)用戶登錄GUI界面及登錄后跳轉(zhuǎn),具有一定的參考價(jià)值,感興趣的可以了解一下2021-11-11
深入了解Python枚舉類型的相關(guān)知識(shí)
這篇文章主要介紹了深入了解Python枚舉類型的相關(guān)知識(shí),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07

