传统目标跟踪——MeanShift算法

article/2025/11/6 14:30:45

目录

一、均值漂移(MeanShift)

二、流程

三、代码

3.1 meanshift+固定框的代码

3.2 优化:meanshift+鼠标选择

3.3 meanshift+自己实现函数

四、补充知识

4.1 直方图

4.2 归一化

4.3 直方图反投影


一、均值漂移(MeanShift)

        该算法寻找离散样本的最大密度,并且重新计算下一帧的最大密度,这个算法的特点就是可以给出目标移动的方向。

         meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中。 

        最开始的窗口是蓝色圆环的区域,命名为C1。蓝色圆环的圆心用一个蓝色的矩形标注,命名为C1_o。
        而窗口中所有点的点集构成的质心在蓝色圆形点C1_r处,显然圆环的形心和质心并不重合。所以,移动蓝色的窗口,使得形心与之前得到的质心重合。在新移动后的圆环的区域当中再次寻找圆环当中所包围点集的质心,然后再次移动,通常情况下,形心和质心是不重合的。不断执行上面的移动过程,直到形心和质心大致重合结束。这样,最后圆形的窗口会落到像素分布最大的地方,也就是图中的绿色圈,命名为C2。
        meanshift算法除了应用在视频追踪当中,在聚类,平滑等等各种涉及到数据以及非监督学习的场合当中均有重要应用,是一个应用广泛的算法。

        如果不知道预先要跟踪的目标,就可以采用这种巧妙地办法,加设定条件,使能动态的开始跟踪(和停止跟踪)视频的某些区域,(如可以采用预先训练好的SVM进行目标的检测,然后开始使用均值漂移MeanShift跟踪检测到的目标)

        所以一般是分两个步骤:1.标记感兴趣区域 2.跟踪该区域

二、流程

         图像是一个矩阵信息,如何在一个视频当中使用meanshift算法来追踪一个运动的物体呢?大致流程如下:

meanshift流程
1.首先在图像上选定一个目标区域
2.计算选定区域的直方图分布,一般是HSV色彩空间的直方图
3.对下一帧图像 b 同样计算直方图分布
4.计算图像 b 当中与选定区域直方图分布最为相似的区域,使用meanshift算法将选定区域沿着最为相似的部分进行移动,直到找到最相似的区域,便完成了在图像b中的目标追踪。
5.重复3到4的过程,就完成整个视频目标追踪。
通常情况下我们使用直方图反向投影得到的图像和第一帧目标对象的起始位置,当目标对象的移动会反映到直方图反向投影图中,meanshift算法就把我们的窗口移动到反向投影图像中灰度密度最大的区域了。

                直方图反向投影

实现Meanshift的主要流程是︰

  1. 读取视频文件:cv.videoCapture()
  2. 感兴趣区域设置:获取第一帧图像,并设置目标区域,即感兴趣区域
  3. 计算直方图:计算感兴趣区域的HSV直方图,并进行归一化
  4. 目标追踪︰设置窗口搜索停止条件,直方图反向投影,进行目标追踪,并在目标位置绘制矩形框

三、代码

opencv API

cv2.meanShift(probImage, window, criteria)

参数:

  • probImage:ROI区域,即目标直方图的反向投影
  • window:初始搜索窗口,就是定义ROI的rect
  • criteria:确定窗口搜索停止的准则,主要有迭代次数达到设置的最大值,窗口中心的漂移值大于某个设定的限值等

(Python)从零开始,简单快速学机器仿人视觉Opencv---运用五:物体运动跟踪 - 古月居

3.1 meanshift+固定框的代码

import cv2 as cv# 创建读取视频的对象
cap = cv.VideoCapture("E:\Python-Code/videodataset/enn.mp4")# 获取第一帧位置,并指定目标位置
ret, frame = cap.read()
c, r, h, w = 530, 160, 300, 320
track_window = (c, r, h, w)
# 指定感兴趣区域
roi = frame[r:r + h, c:c + w]# 计算直方图
# 转换色彩空间
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
# 计算直方图
roi_hist = cv.calcHist([hsv_roi], [0], None, [180], [0, 180])
# 归一化
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)# 目标追踪
# 设置窗口搜索终止条件:最大迭代次数,窗口中心漂移最小值
term_crit = (cv.TermCriteria_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)while True:ret, frame = cap.read()if ret:# 计算直方图的反向投影hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)# 进行meanshift追踪ret, track_window = cv.meanShift(dst, track_window, term_crit)# 将追踪的位置绘制在视频上,并进行显示x, y, w, h = track_windowimg = cv.rectangle(frame, (x, y), (x + w, y + h), 255, 2)cv.imshow("frame", img)if cv.waitKey(20) & 0xFF == ord('q'):breakelse:break# 资源释放
cap.release()
cv.destroyAllWindows()

 缺点:这种就是一开始设定了具体框的大小和位置,不能根据实际情况自己进行更改。

        初始框的位置很重要。以Meanshift为例,它的工作原理是根据概率密度来寻找最大的密度区域,但如果我们一开始将跟踪框放置在了一个直方图反向投影图中全黑的区域(密度为0),这会导致其无法正确向物体方向进行移动,从而导致卡死在那里。

        我们已追踪视频的初始帧(第一帧)为例,我们假设想要跟踪其中的一个物体,我们就得将跟踪框放置到跟踪物体周边的区域才能让程序正常运行,但我们其实很难知道一张图片中跟踪物体的具体位置。   举个简单的例子,比如我现在有一张图片,我们要跟踪图片右下角的一个物体,但是我不知道这个物体的坐标范围,所以我只能一次一次的去尝试(在代码中修改初始框的位置后,看看程序的运行情况)来保证代码能够正常运行,但这样代码的普适性很差,因为每当要更改跟踪对象的时候,都需要反复的修改,才能应对当前的情况,这样实在是有点麻烦。  

3.2 优化:meanshift+鼠标选择

        这里介绍一个函数,起名为:cv2.selectROI,使用这个函数,我们就能够实现手动画取我们的跟踪框,其函数语法如下所示: 

track_window=cv2.selectROI('frameName', frame)

参数:

  • framename:显示窗口的画布名
  • frame:具体的帧
import cv2
import numpy as np# 读取视频
cap=cv2.VideoCapture('E:\Python-Code/videodataset/enn.mp4')
# 获取第一帧位置,参数ret 为True 或者False,代表有没有读取到图片 第二个参数frame表示截取到一帧的图片
ret,frame=cap.read()
#我这里画面太大了所以缩小点——但是缩小后我的就会报错
# frame=cv2.resize(frame,None,None,fx=1/2,fy=1/2,interpolation=cv2.INTER_CUBIC)#跟踪框
track_window=cv2.selectROI('img', frame)#获得绿色的直方图
# 转换色彩空间
hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
mask=cv2.inRange(hsv,np.array((35,43,46)),np.array((77,255,255)))
# 计算直方图
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)# 目标追踪
# 设置窗口搜索终止条件:最大迭代次数,窗口中心漂移最小值
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:# 计算直方图的反向投影hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)dst=cv2.calcBackProject([hsv],[0],hist,[0,180],1)# 进行meanshift追踪ret,track_window=cv2.meanShift(dst,track_window,term_crit)# 将追踪的位置绘制在视频上,并进行显示x,y,w,h = track_windowimg = 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'):breakelse:break# 资源释放
cap.release()
cv2.destroyAllWindows()

          运行上面的代码,会跳出一个窗口,窗口上显示的就是我们载入的视频的第一帧,我们用鼠标拖动,画出我们要跟踪的物体的位置

        但是这里需要注意的是,这个函数每次调用只能画一个矩形(C++版本中的OpenCV可以一次画好多个),如果想画好多个矩形的话,可以使用while循环:

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键退出,按下其他键继续画下一个框")if cv2.waitKey(0) & 0xFF==ord('q'):break
print('选取的边框为{}'.format(bboxes))

但是完整的代码并没有跑通

3.3 meanshift+自己实现函数

这个效果最好,但是不懂为什么会这样?为什么调用库函数反而效果不好呢?

import math
import numpy as np
import cv2def get_tr(img):# 定义需要返回的参数mouse_params = {'x': None, 'width': None, 'height': None,'y': None, 'temp': None}cv2.namedWindow('image')# 鼠标框选操作函数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, point1img2 = img.copy()if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击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)# 返回框选矩形左上角点的坐标、矩形宽度、高度以及矩形包含的图像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 imgcap = cv2.VideoCapture("E:\Python-Code/videodataset/enn.mp4")# 获取视频第一帧ret, frame = cap.read()img = frame# 框选目标并返回相应信息:rect为四个信息,temp为框选出来的图像rect, temp = get_tr(img)print(temp)(a, b, c) = temp.shapey = [a / 2, b / 2]# 计算目标图像的权值矩阵m_wei = np.zeros((a, b))for i in range(a):for j in range(b):z = (i - y[0]) ** 2 + (j - y[1]) ** 2m_wei[i, j] = 1 - z / (y[0] ** 2 + y[1] ** 2)# 计算目标权值直方图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_bhist1[int(q_temp1)] = hist1[int(q_temp1)] + m_wei[i, j]hist1 = hist1 * C# 接着读取视频并进行目标跟踪while (1):ret, frame = cap.read()if ret == True:Img = framenum = 0Y = [1, 1]# mean shift迭代while (np.sqrt(Y[0] ** 2 + Y[1] ** 2) > 0.5) & (num < 20):num = num + 1# 计算候选区域直方图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_bhist2[int(q_temp2[i, j])] = hist2[int(q_temp2[i, j])] + m_wei[i, j]hist2 = hist2 * Cw = 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] = 0sum_w = 0sum_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) & 0xffif k == 27:breakelse:breakif __name__ == '__main__':main()

四、补充知识

4.1 直方图

构建图像的直方图需要使用到函数cv2.calcHist,其常用函数语法如下所示:  

hist=cv2.calcHist(images, channels, mask, histSize, ranges) images:输入的图像
channels:选择图像的通道,如果是三通道的话就可以是[0],[1],[2]
mask:掩膜,是一个大小和image一样的np数组,其中把需要处理的部分指定为1,不需要处理的部分指定为0,一般设置为None,如果有mask,会先对输入图像进行掩膜操作
histSize:使用多少个bin(柱子),一般为256,但如果是H值就是181
ranges:像素值的范围,一般为[0,255]表示0~255,对于H通道而言就是[0,180]

  需要注意的是,这里除了mask以外,其余的几个参数都要加上[],如下所示:  

hist=cv2.calcHist([img],[0],mask,[181],[0,180]) 

4.2 归一化

        这个时候我们还需要使用一种归一化的方法来对彩色直方图中的数量值进行规范化。   现有的直方图中的数值为对应像素的数量,其中图中出现数量最多的像素的数量值(最高的柱子对应的y轴数值)我们记为max的话,整个直方图y方向上的取值范围就是[0,max],我们需要把这个范围缩减到[0,255],

        这里我们需要使用到cv2.normalize函数,函数主要语法如下所示:  

cv2.normalize(src,dst, alpha,beta, norm_type)
·src-输入数组。
·dst-与SRC大小相同的输出数组。
·α-范数值在范围归一化的情况下归一化到较低的范围边界。
·β-上限范围在范围归一化的情况下;它不用于范数归一化。
·范式-规范化类型(见下面详细介绍)。

  这里我们需要注意的是范式-规范化类型,这里有以下几种选择。  

NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化。
NORM_INF:归一化数组的(切比雪夫距离)L∞范数(绝对值的最大值)
NORM_L1: 归一化数组的(曼哈顿距离)L1-范数(绝对值的和)
NORM_L2: 归一化数组的(欧几里德距离)L2-范数

  上面的名词看起来很高大上,其实是很简单,我们一一讲解下。(不是很感兴趣的只要看下第一个NORM_MINMAX即可,剩下的三个可以不看)

        首先是NORM_MINMAX,这个是我们最常用的一种归一化方法。举个例子,我们上面提到的最高的柱子对应的y轴坐标为max,如果我们使用这种方法,想要缩放到的指定的范围为[0,255],那么max就会直接被赋值为255,其余的柱子也会随之一样被压缩(类似于相似三角形那样的缩放感觉)。   没错,很简单得就介绍完了一种,不是很想了解其他几个的读者可以直接跳过本小节剩下来的内容了,因为剩下三种不是很常用。  

      这里有介绍剩下的几种

4.3 直方图反投影

        简单来说,它会输出与输入图像(待搜索)同样大小的图像,其中的每一个像素值代表了输入图像上对应点属于目标对象(我们需要跟踪的目标)的概率。用更简单的话来解释,输出图像中像素值越高(越白)的点就越可能代表我们要搜索的目标 (在输入图像所在的位置)。   而对于灰度图而言,其只有一个通道,取值范围为0到255,所以我们之前在归一化的时候将直方图的y轴坐标的取值范围压缩到了0-255的范围内,就是为了这里可以直接赋值。  

直方图反向投影1    直方图反向投影2

        越暗的地方说明属于跟踪部分的可能性越低,越亮的地方属于跟踪部分的可能性越高。   这里使用到的函数为cv2.calcBackProject,函数语法如下所示:  

dst=cv2.calcBackProject(image,channel,hist,range,scale)image:输入图像
channel:用来计算反向投影的通道数,与产生直方图对应的通道应一致
hist:作为输入的直方图
range:直方图的取值范围
scale:输出图像的缩放比,一般为1,保持与输入图像一样的大小
dst:输出图像注意:除了hist和scale外,其他的参数都要加上[]

  例如:  

dst=cv2.calcBackProject([hsv],[0],hist,[0,180],1)


http://chatgpt.dhexx.cn/article/SdEe7rs3.shtml

相关文章

Mean Shift 聚类算法

原文&#xff1a;https://blog.csdn.net/hjimce/article/details/45718593 一、mean shift 算法理论 Mean shift 算法是基于核密度估计的爬山算法&#xff0c;可用于聚类、图像分割、跟踪等&#xff0c;因为最近搞一个项目&#xff0c;涉及到这个算法的图像聚类实现&#xff…

mean shift聚类matlab,机器学习:Mean Shift聚类算法

今天的文章介绍如何利用Mean Shift算法的基本形式对数据进行聚类操作。而有关Mean Shift算法加入核函数计算漂移向量部分的内容将不在本文讲述范围内。实际上除了聚类&#xff0c;Mean Shift算法还能用于计算机视觉等场合&#xff0c;有关该算法的理论知识请参考这篇文章。 Mea…

Python 实现MeanShift算法

原理 大家自行百度吧&#xff0c;我懒得码字了 推荐一下原理原理https://blog.csdn.net/jinshengtao/article/details/30258833 代码 直接上代码了&#xff0c;看不懂&#xff0c;就参照一下原理 # author: wdq # contact: 1920132572qq.com # datetime:2022/3/15 17:40 # …

Sklearn聚类算法之meanshift

以二维来说明可能更容易理解&#xff0c;下图中的很多的红点就是我们的样本特征点&#xff0c;meanshift就是在这些点中的任意一个点为圆心&#xff0c;然后以半径R画一个圆&#xff08;在opencv中是一个矩形&#xff09;&#xff0c;然后落在这个圆中的所有点和圆心都会对应的…

Python实现Mean Shift聚类算法

Mean Shift算法&#xff0c;又称均值聚类算法&#xff0c;聚类中心是通过在给定区域中的样本均值确定的&#xff0c;通过不断更新聚类中心&#xff0c;直到聚类中心不再改变为止&#xff0c;在聚类、图像平滑、分割和视频跟踪等方面有广泛的运用。 Mean Shift向量 对于给定的…

mean shift 跟踪算法

说明一&#xff1a; Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束. 1. Meanshift推导 给定d维空间Rd的n个样本点 ,i1,…,n,在空间中任选一点x&#xff0c;那么Mean Shift向量…

Python实现Mean Shift算法

声明&#xff1a;代码的运行环境为Python3。Python3与Python2在一些细节上会有所不同&#xff0c;希望广大读者注意。本博客以代码为主&#xff0c;代码中会有详细的注释。相关文章将会发布在我的个人博客专栏《Python从入门到深度学习》&#xff0c;欢迎大家关注~ 在K-Means算…

meanshift算法 java_Meanshift,聚类算法

记得刚读研究生的时候&#xff0c;学习的第一个算法就是meanshift算法&#xff0c;所以一直记忆犹新&#xff0c;今天和大家分享一下Meanshift算法&#xff0c;如有错误&#xff0c;请在线交流。 Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其…

保边滤波之Mean shift filter

Mean shift filter 目录 Mean shift filter 一、算法原理 二、练手实现的算法代码如下&#xff1a; 三、实现结果 一、算法原理 在OpenCV中&#xff0c;meanshift filter函数为 pyrMeanShiftFiltering&#xff0c; 它的函数调用格式如下&#xff1a; C: void pyrMeanShif…

mean shift

参考&#xff1a; http://blog.csdn.net/google19890102/article/details/51030884 http://www.cvvision.cn/5778.html https://wenku.baidu.com/view/5862334827d3240c8447ef40.html http://blog.csdn.net/qq_23968185/article/details/51804574 https://www.cnblogs.com…

机器学习算法原理与实践(二)、meanshift算法图解以及在图像聚类、目标跟踪中的应用

【原创】Liu_LongPo 转载请注明出处 【CSDN】http://blog.csdn.net/llp1992 最近在关注跟踪这一块的算法&#xff0c;对于meanshift的了解也是来自论文和博客&#xff0c;本博客将对meanshift算法进行总结&#xff0c;包括meanshift算法原理以及公式推导&#xff0c;图解&…

基于MeanShift的目标跟踪算法及实现

这次将介绍基于MeanShift的目标跟踪算法&#xff0c;首先谈谈简介&#xff0c;然后给出算法实现流程&#xff0c;最后实现了一个单目标跟踪的MeanShift算法【matlab/c两个版本】 csdn贴公式比较烦&#xff0c;原谅我直接截图了… 一、简介 首先扯扯无参密度估计理论&#xff0c…

聚类算法:Mean Shift

目录 简介 mean shift 算法理论 Mean Shift算法原理 算法步骤 算法实现 其他 聚类算法之Mean Shift Mean Shift算法理论 Mean Shift向量 核函数 引入核函数的Mean Shift向量 聚类动画演示 Mean Shift的代码实现 算法的Python实现 scikit-learn MeanShift演示 s…

meanshift算法通俗讲解

这几天学习《学习OpenCV》中的第十章运动跟踪&#xff0c;里面讲到了meanshift算法&#xff0c;根据书上所讲实在难以理解&#xff0c;meanshift在运动跟踪这个过程中到底起到什么作用&#xff0c;于是经过几天不断地看相关资料和别人的博客文章&#xff0c;慢慢思路清晰了&…

机器学习实验 - MeanShift聚类

目录 一、报告摘要1.1 实验要求1.2 实验思路1.3 实验结论 二、实验内容2.1 方法介绍2.2 实验细节2.2.1 实验环境2.2.2 实验过程2.2.3 实验与理论内容的不同点 2.3 实验数据介绍2.4 评价指标介绍2.5 实验结果分析 三、总结及问题说明四、参考文献附录&#xff1a;实验代码 报告内…

聚类 之 MeanShift

文章目录 Meanshift 聚类基本原理Meanshift 聚类流程简述实例演示MeanShift聚类简易应用示例总结拓展阅读 上篇博客介绍了基于距离的K-Means聚类&#xff0c;这次给大家推荐一个基于密度的聚类算法&#xff1a;Meanshift&#xff08;均值漂移&#xff09;。 Meanshift 聚类基本…

Muduo源码剖析

1、总体流程 1. acceptor 进行listen阶段后&#xff0c; 往channel中注册可读事件。 2. acceptor可读处理中生成TcpConnection指针&#xff0c;通过EventloopThreadPool 轮询出其中一个线程的eventloop, 并将此TcpConnection的可读、可写等事件注册到自己Channel&#xff08;ev…

Muduo - Reactor模式

Muduo - Reactor模式 一、Reactor 是什么 wiki的中文定义&#xff1a;Reactor模式是事件驱动的&#xff0c;有一个或多个并发输入源&#xff0c;有一个Service Handler&#xff0c;有多个Request Handler&#xff0c;这个Service Handler会同步的将输入的请求&#xff08;Even…

muduo网络库——ThreadPool

模型 源码分析 1&#xff09;接口 class ThreadPool : noncopyable {public:typedef std::function<void ()> Task;explicit ThreadPool(const string& nameArg string("ThreadPool"));~ThreadPool();void setMaxQueueSize(int maxSize) { maxQueueSize…

muduo网络库——Channel

模型 实现流程&#xff1a; 前面已经介绍了EPoller类&#xff0c;EPoller主要监听的是Channel对象&#xff0c;每一个Channel对象会绑定一个文件描述符&#xff08;fd_&#xff09;&#xff0c;fd_上绑定要监听的事件。当epoll监听到就绪事件时&#xff0c;会将就绪事件添加到…