1.研究背景与意义
随着人口老龄化程度的不断加深,老年人的健康问题越来越受到关注。其中,老年人跌倒是一种常见但危险的事件,可能导致严重的身体损伤甚至死亡。因此,开发一种能够及时检测和预警老年人跌倒的系统具有重要的现实意义。
在过去的几十年里,计算机视觉技术取得了巨大的进步,尤其是在图像和视频处理方面。OpenCV作为一个开源的计算机视觉库,提供了丰富的图像处理和分析工具,被广泛应用于各个领域。基于OpenCV的人员跌倒检测系统能够利用计算机视觉技术实时监测和分析视频流,从而及时发现跌倒事件并进行预警。
该系统的研究意义主要体现在以下几个方面:
-
提高老年人的安全性:老年人跌倒是导致伤害和死亡的主要原因之一。通过开发基于OpenCV的人员跌倒检测系统,可以及时发现老年人跌倒事件并及时采取救援措施,提高老年人的安全性。
-
减轻护理负担:老年人跌倒后,需要及时的救援和护理。基于OpenCV的人员跌倒检测系统可以自动监测老年人的行为,一旦发现跌倒事件,可以立即向护理人员发送警报,减轻护理负担。
-
促进智能化养老:随着人工智能技术的发展,智能化养老已经成为一个热门的研究方向。基于OpenCV的人员跌倒检测系统可以作为智能化养老的一部分,为老年人提供更加智能、便捷的生活服务。
-
推动计算机视觉技术的应用:计算机视觉技术在人员跌倒检测系统中的应用,可以推动计算机视觉技术在其他领域的应用。通过研究基于OpenCV的人员跌倒检测系统,可以进一步提高计算机视觉技术的准确性和稳定性,为其他领域的应用提供技术支持。
总之,基于OpenCV的人员跌倒检测系统具有重要的现实意义和研究价值。通过该系统的研究和应用,可以提高老年人的安全性,减轻护理负担,促进智能化养老,并推动计算机视觉技术的应用和发展。
2.图片演示
3.视频演示
基于OpenCV的人员跌倒检测系统(源码&部署教程)_哔哩哔哩_bilibili
4.图像预处理
4.1 中值滤波
中值滤波法为非线性平滑方法,它主要是把图像中像素点的灰度值替换为这个像素相邻区域内其他像素点灰度值的中间值。对于有限的实数集,中值既是集合排序后中间的数值的值。在一定条件下,线性滤波都拥有低通滤波的特性,在降噪的时候可能会模糊图像边缘细节,中值滤波能够解决线性滤波在处理图像边缘时存在的问题,并且因为其冲激响应为零,使得它能够抑制脉冲干扰和图像扫描噪声,对消除椒盐噪声效果不错,但是如果图像拥有众多条纹,效果一般不理想。
中值滤波的步骤为:
1、通过滑动模板窗口,使其中心点和图像里的某个像素点保持重合;2、获取像素点灰度值;
3、把读取到的灰度值从小到大排序;
4、从排列好的数值中取出这些值的中值,接着把中值赋值给模板的中心像素点。如果这些排列好的序列总数是奇数,中值就为这些数值的中间那个像素的灰度值,如果是偶数,就是中间两个像素点的灰度值平均值。在实际处理中一般使用奇数模板,这样可以保证中值具有唯一性。
下面利用序列来理解中值滤波的原理32],假定xx2x3…xn为一组数列,按照大小顺序排列为
i1 ≤Xi2 ≤Xi3 ≤…≤Xin
在OpenCV函数库中,cv2.medianBlur(src,ksize)可以对图像进行中值滤波处理,其中src为图像矩阵,Ksize为内核大小。对图3.1进行中值滤波处理,处理结果如下图3.3所示,从左至右内核大小分别为3、5、7,内核数值越大,得到的结果往往越模糊,而且在图中能够看到使用中值滤波处理后的图像在线条处丢失了较多的细节,图像中的字体依旧变得非常模糊。
4.2 阈值处理
本文后续的工作对于目标的检测,将会用到阈值处理提取目标人体,经过阈值处理后,一般只保留图像的关键信息,会使图像的目标更加明确,图像的像素拥有灰度相似性与灰度不连续性两种特性,图像同一区域内是像素拥有灰度相似性,不同区域的一般拥有灰度不连续性l34]。通过设置不同的阈值,可以把图像分离为不同的区域。
阈值处理它是通过预先设置好的阈值来划分图像像素,大于阈值的划分为一个区域,小于阈值的划分为另一个区域。它适用于目标与背景存在较大的灰度对比度,且目标与背景灰度单一的图像。但是这种方法比较依赖于灰度直方图,对于背景复杂的图像效果并不理想。根据对图像采用一个或多个阈值,可以分成全局阈值法和局部阈值法。根据阈值算法的自有特性又可以分为Р参数法、Otsu阈值法、迭代阈值法、双阈值法等。
(1)Р参数法
Р参数法根据目标区域在整个图像上占的比例设定阈值,然后进行二值化。假如已知了目标占到整幅图像的多少,这个时候便能够使用Р参数法,Р为比例值。Р参数法的步骤如下:
①计算出图像的直方图分布P(t),t=0,1,2…255。
②计算阈值T,m×n为图像大小。
(2)Otsu阈值法
Otus阈值法又名最大类间方差法,由Otsu在1978年提出,基本思想是根据图像的灰度特征把图像分成前景和背景两种,他们的类间方差最大时的阈值就是最优阈值。类间方差越大,前景与背景就越不一样,所以最大化类间方差法拥有很好的效果[36l。(3)迭代阈值法
迭代阈值法利用像素的相似性,先选择一个合适的开始阈值,接着使用某种方法不停的更新直到收敛,即直到找到相似的像素点。迭代阈值法简单且容易实现,拥有较好的执行速度。
(4)双阈值法
针对单阈值法的局限性,即图像的灰度直方图的双峰通常都会重叠,使用单阈值法会有较大误差。双阈值法是利用两个阈值T与T,来区分背景与目标,T,<T2,灰度值比T小的判定为背景,灰度值比T,大的判定为目标,两者之间的另外再做判断。
在获取运动目标的过程中,进过差分法会得到如图3.5的一张灰度图,利用阈值处理可以使目标特征更加的明确,从而可以进行后续的工作。Otsu法能够自动选择合适的阈值对图像进行分割,所以利用Otsu法进行处理不易产生错分的情况,使得该方法更加高效,是使用较多的方法之一。进行Otsu阈值处理可以得到如图的效果图。
5.核心代码讲解
5.1 bs.py
class Bs:
def __init__(self):
self.settings = settings.Settings()
self.method = self.settings.bsMethod
if self.method == 0:
self.fgbg = cv2.BackgroundSubtractorMOG2(self.settings.MOG2history, self.settings.MOG2thresh, self.settings.MOG2shadow)
self.foregroundMask = None
if self.method == 1:
self.backgroundFrame = None
self.frameCount = 1
def updateBackground(self, frame): # Updating the background
if self.method == 0:
self.foregroundMask = self.fgbg.apply(frame, self.foregroundMask, self.settings.MOG2learningRate)
if self.method == 1:
alpha = (1.0/self.frameCount)
if self.backgroundFrame is None:
self.backgroundFrame = frame
self.backgroundFrame = cv2.addWeighted(frame, alpha, self.backgroundFrame, 1.0-alpha, 0)
self.frameCount += 1
def compareBackground(self, frame):
if self.method == 0:
return self.foregroundMask
if self.method == 1:
self.frameDelta = cv2.absdiff(self.backgroundFrame, frame)
self.foregroundMask = cv2.threshold(self.frameDelta, self.settings.thresholdLimit, 255, cv2.THRESH_BINARY)[1] # Creating a foregroundMask
return self.foregroundMask
def deleteBackground(self):
if self.method == 0:
self.foregroundMask = None
if self.method == 1:
self.backgroundFrame = None
def resetBackgroundIfNeeded(self, frame):
if self.method == 0:
if self.foregroundMask is None:
self.foregroundMask = self.fgbg.apply(frame)
if self.method == 1:
if self.backgroundFrame is None:
self.updateBackground(frame)
self.frameCount = 1
该程序文件名为bs.py,主要实现了一个名为Bs的类。该类用于进行背景减除操作,根据不同的方法选择不同的背景减除算法。
程序中使用了OpenCV库进行图像处理操作。在初始化方法中,根据设置文件中的bsMethod参数选择使用的背景减除方法。如果方法为0,则使用MOG2算法,如果方法为1,则使用动态方法。
在updateBackground方法中,根据选择的方法更新背景。如果方法为0,则使用MOG2算法的apply方法更新前景掩码。如果方法为1,则根据帧计数和权重参数更新背景帧。
在compareBackground方法中,根据选择的方法比较背景。如果方法为0,则返回前景掩码。如果方法为1,则计算帧差并根据阈值生成前景掩码。
在deleteBackground方法中,根据选择的方法删除背景。如果方法为0,则将前景掩码置为None。如果方法为1,则将背景帧置为None。
在resetBackgroundIfNeeded方法中,根据选择的方法重置背景。如果方法为0且前景掩码为None,则使用MOG2算法的apply方法初始化前景掩码。如果方法为1且背景帧为None,则更新背景帧并重置帧计数。
5.2 fall_detection.py
class MotionDetection:
def __init__(self):
self.cap = None
self.fgbg = cv2.createBackgroundSubtractorKNN()
self.consecutive_frames = 0
def select_file(self):
file_path = filedialog.askopenfilename()
return file_path
def use_webcam(self):
self.cap = cv2.VideoCapture(0)
def process_frame(self, frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
fgmask = self.fgbg.apply(gray)
contours, _ = cv2.findContours(fgmask, cv2.RETR_TREE, cv2.CHAIN_APPROX_TC89_KCOS)
if contours:
areas = []
heights = []
widths = []
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
ar = cv2.contourArea(contour)
areas.append(ar)
heights.append(h)
widths.append(w)
max_area = max(areas or [0])
max_area_index = areas.index(max_area)
cnt = contours[max_area_index]
x, y, w, h = cv2.boundingRect(cnt)
cv2.drawContours(fgmask, [c