【OpenCV】第二十章: 图像及视频去背景

这篇具有很好参考价值的文章主要介绍了【OpenCV】第二十章: 图像及视频去背景。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第二十一章: 图像及视频去背景

我们做目标识别、目标检测的时候经常需要去背景,比如车辆检测,就是摄像头拍摄一段车辆行驶视频,统计一下视频里面的车流量,此时我们首先要识别出图片中的车辆才能计数有多少辆车,而要识别车辆就需要先把车辆从图像中分割出来再做识别,而把车辆分割出来就是将前景物体从背景中分离出来,就是我们需要把视频的背景全部去掉,只剩下车辆,然后再进行其他操作。
所以去背景就是前后景分割和提取,去背景的方法和手段有很多,我们第十七章也详细讲了两种去背景的算法:分水岭算法和GrabCut算法。本章讲meanshift算法几种视频去背景算法

一、MeanShift算法

meanshift算法本是机器学习中聚类算法中的一个算法,就是一种无监督分类算法,就是把图像的所有像素点看成一个个没有标签的样本数据,然后用探索这些样本数据的内部规律,把所有样本自动分成若干个类别,实现自动聚类。如果我们对机器学习算法中的聚类算法比较熟悉,那就很容易理解meanshift算法。但这个算法的亮点是用在图像处理中,这个算法搭配canny算法可以得到效果更加好的边缘检测效果;搭配分水岭算法可以得到更好的图像分割效果;搭配轮廓检测函数cv2.findContours()可以得到更好的轮廓效果;搭配直方图可以得到更好的匹配效果,可以用于视频中的运动跟踪了。

meanshift算法运用到图像上就是:以图像上任一点为圆心p,半径为sp,色彩幅值为sr,进行不断地迭代,实现像素点地自动聚类。实现效果如下:

createbackgroundsubtractormog,算法,opencv,学习

 从上图我们可以看到图像上的颜色都变成一片一片的了,那是因为算法将色彩分布相近的颜色聚为一类,并且都用该类的中心点像素值代替了。
所以meanshift可以很好的平滑掉图像上彩色细节,侵蚀掉面积较小的颜色区域,色彩分布相近的颜色都变成一片片了,此时要做分割就可以很好的分割了,要提取轮廓就可以很好的提取了。所以这个算法搭配其他算法可以更好的实现图像分割、前后景提取、视频跟踪等功能。

meanshift算法的原理其实非常简单,其中的数学推导和代码实现也不是很复杂,网上有大量的资料可供我们参考,但是,把这个机器学习算法用到图像处理中,其中涉及到的细节还是非常多的:
1、改进后的meanshift算法又加入了核函数,核密度估计要了解;
2、机器学习中的meanshift算法是不断画圆-找质心-迭代,从而实现自动聚类,但是对于图像数据来说,就不是画圆迭代而是画球迭代,因为除了设置像素点之间的物理空间坐标半径外,还需要设置色彩幅值的半径,就是一个空间球体的不断迭代;
3、为了实现尺度不变性,opencv中该算法还结合了图像金字塔,其参数中就有一个专门定义所需金字塔层数的变量,所以我们还需要对图像金字塔有所了解;
4、用于计算的像素点的色彩空间,我们一般不用RGB而是转化为luv色彩空间,因为我们在计算色彩距离的时候一般用欧式距离,而计算出来的结果不一定符合人眼的色彩距离,比如两个色彩颜色我们人类觉得很近似,如果用RGB计算这两个色彩之间的欧式距离,结果很大,不符合人眼的规律,如果用luv计算欧式距离,人眼看着颜色相近,计算结果就越小,人眼看着颜色相差越大,计算结果就越大,符合人类视觉规律。一句话,Luv色彩空间是和人类视觉统一的,所以计算的时候要转化为Luv。
。。。。牵扯到的细节非常多,所以本章只讲opencv中的meanshift算法api,以后写机器学习算法了,再详细写这个算法的原理、数学推导以及代码实现。

  • API:cv2.pyrMeanShiftFiltering(src, sp, sr[, dst[, maxLevel[, termcrit]]])
    scr:输入的图像,8位3通道彩图。但是这里并不要求必须是RGB格式,BGR,HSV等都可以,算法在底层都统一转化为Luv进行计算;
    sp:为像素点物理坐标空间半径的大小。sp设置得越高,模糊程度就越大,sp设置得越小,图像模糊程度就越小。
    sr:为像素点色彩空间的半径大小,也就是色彩幅值的范围,就是规定颜色相近到多少才算作同类颜色。sr设置的越高,能模糊的差异就越大,sr设置的越低,颜色相近度就要求得越高。
    dst:输出图像,跟输入src有同样的大小和数据格式;
    maxLevel:定义金字塔的最大层数;默认值是1,就是不用下采样数据。
    termcrit:定义的漂移迭代终止条件,可以设置为迭代次数满足终止,迭代目标与中心点偏差满足终止,或者两者的结合;

  • pyrMeanShiftFiltering()函数的执行过程
    1、构建迭代空间。
    以输入图像上任一点P0为圆心,建立以sp为物理空间半径,sr为色彩空间半径的球形空间,物理空间上坐标为x和y,色彩空间上坐标为RGB或Luv(最好)或HSV,构成一个空间球体。其中x和y表示图像的长和宽,色彩空间R、G、B在0至255之间。
    2、求迭代空间的向量并移动迭代空间球体重新计算向量,直至收敛。
    在上一步构建的球形空间中,求出所有点相对于中心点的色彩向量之和,移动迭代空间的中心点到该向量的终点,并再次计算该球形空间中所有点的向量之和,如此迭代,直到在最后一个空间球体中所求得向量和的终点就是该空间球体的中心点Pn,迭代结束。
    3、更新输出图像dst上对应的初始原点P0的色彩值为本轮迭代的终点Pn的色彩值,完成一个点的色彩均值漂移。
    4、对输入图像src上其他点,依次执行上述三个步骤,直至遍历完所有点后,整个均值偏移色彩滤波完成。

#例21.1 调用pyrMeanShiftFiltering()函数对图像进行色彩平滑,然后提取边缘、轮廓、前景对象
import cv2
import numpy as np

img = cv2.imread(r'C:\Users\25584\Desktop\rabbit.jpeg')    #原图
mean_img = cv2.pyrMeanShiftFiltering(img, 50, 30)          #色彩平滑,后面两个参数可以根据自己的效果进行调整

#---------------------提取边缘和轮廓-------------------------------------------------------------------------------
canny_img = cv2.Canny(mean_img, 120, 200)                                                       #canny提取边缘
contours, hierarchy = cv2.findContours(canny_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)   #提取轮廓
print(len(contours))      #打印轮廓个数
contours_ = []           #用面积过滤掉小的轮廓
for i in contours:
    if cv2.contourArea(i)>=20:
        contours_.append(i)
print(len(contours_))   #打印出轮廓个数,看剩几个轮廓了
huabu = np.zeros(img.shape, dtype=np.uint8)  #把过滤后的轮廓画出来
contours_img = cv2.drawContours(huabu, contours_, -1, (255,255,255), 1)

#-------------------提取前景--------------------------------------------------------------------------------------
gray_img = cv2.cvtColor(mean_img, cv2.COLOR_BGR2GRAY)   #转灰度图像
_, mask = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)  #用阈值转成二值图像,mask.shape是(400, 600)
img_pre = cv2.bitwise_and(img, cv2.merge([mask,mask,mask]))     #按位与运算,也就相当于img和掩码mask进行运算,mask是一个二维的,用merge函数升到3维,再与img与运算

#可视化
fig, axes = plt.subplots(1,6, figsize=(25,16), dpi=100)   #可视化
axes[0].imshow(img[:,:,::-1]), axes[0].xaxis.set_ticks([]), axes[0].yaxis.set_ticks([]), axes[0].set_title('original')                #原图图像
axes[1].imshow(mean_img[:,:,::-1]), axes[1].xaxis.set_ticks([]), axes[1].yaxis.set_ticks([]), axes[1].set_title('meanshift')          #meanshift后的图像
axes[2].imshow(canny_img, cmap='gray'), axes[2].xaxis.set_ticks([]), axes[2].yaxis.set_ticks([]), axes[2].set_title('canny')          #canny边缘检测的图像
axes[3].imshow(contours_img, cmap='gray'), axes[3].xaxis.set_ticks([]), axes[3].yaxis.set_ticks([]), axes[3].set_title('contour')     #经过面积过滤的轮廓
axes[4].imshow(mask, cmap='gray'), axes[4].xaxis.set_ticks([]), axes[4].yaxis.set_ticks([]), axes[4].set_title('mask')                #掩膜图像
axes[5].imshow(img_pre[:,:,::-1]), axes[5].xaxis.set_ticks([]), axes[5].yaxis.set_ticks([]), axes[5].set_title('pre_img')              #前景
plt.show()

createbackgroundsubtractormog,算法,opencv,学习

二、视频去背景

视频去背景又叫视频背景扣除,也叫视频前后景分割和提取。
静态图像去背景和视频去背景在算法上还是有区别的。对于视频来说,是以时间轴为顺序,每张图片前后有一个关联关系。如果图片的像素在一段时间内不发生变化,我们就认为这个像素是背景色,如果发生频繁的变化,我们就认为是前景色。这是视频去背景算法的原理,但也会有一些缺点,比如一棵树在风吹的时候,那这颗树就从背景识别成了前景。再比如我们的影子,人动影子就动,所以影子也很容易就被识别为前景色。再比如动着的人如果不动了,那这个人就又从前景变为背景了,就被扣掉了,就是静止的人就检测不出来,动的人才能检测出来。

opencv给我们提供了多种视频去背景方法,我们介绍下面几种方法:

  • 1、MOG去背景API:cv2.bgsegm.createBackgroundSubtractorMOG([history, nminxtures, backgroundRatio, noiseSigma])
    creatBackgroundSubtractorMOG()是以混合高斯模型为基础的前后景分割算法,是一个类,放在opencv下面的一个子包bgsegm里,我们可以通过这个类创建一个mog对象
    history:表示建模时需要多长时间的参考帧,默认是200毫秒。假设视频的播放速度是一秒钟显示25张图片,也就是25帧,那么建模参考的图片就是5张。
    nminxtures:高斯值范围,默认是5,就是把一张图片分成5x5个小块,每个小块都有一个高斯值,然后算出一个参考模型
    backgroundRatio:背景比例,就是背景在整张图片中的占比,默认是0.7,就是默认一张图中70%是背景。
    noiseSigma:噪音的参数,这个参数设置为0就是自动降噪,默认值也是0
    一般情况下,我们使用这个类时,一般都用默认参数即可,默认值下效果就比较不错了。

  • 2、MOG2去背景API:cv2.createBackgroundSubtractorMOG2([history, detectShadows])
    MOG2是对MOG算法的一个改进,因为MOG对光线下产生的阴影无法识别,MOG2可以对阴影有更好的识别,这对我们计算准确度是非常关键的。
    但是MOG2的缺点是前后景分离时会产生很多噪点。MOG2在opencv的标准库中所以直接调用。
    history:默认500毫秒
    detectShadows:是否检测阴影,默认值是True,就是默认把阴影也检测出来

  • 3、GMG去背景API:cv2.bgsegm.createBackgroundSubtractorGMG([initializationFrames])
    GMG是针对MOG2噪点过多而诞生的,GMG采用静态背景图像估计和每个像素的贝叶斯分割,既可以检测出阴影还具有更强的抗噪性。GMG也没有放在标准库中。
    initializationFrames:初始化的帧数,默认是120。MOG和MOG2都是先缓存200毫秒的时间,而GMG是缓存120个帧数,如果你的视频帧率很大,那缓存的时间就非常短,如果视频帧率很小,比如20帧/秒,就要缓存6秒才能开始视频,这是二者的最大区别,也是GMG的最大缺点,就是开始了好长时间没有任何信息显示,但是这个缺点我们可以通过调整参数initializationFrames来避免,但是这个参数又不能调太小,太小了计算的参考帧数太少,效果又不好。

opencv中去背景的相关论文: An improved adaptive background mixture model for real-time tracking with shadow detection文章来源地址https://www.toymoban.com/news/detail-784081.html

#例21.2 调用上面几种方法对视频进行前后景分离,对比这几种方法的优缺点  
import cv2
import numpy as np

cap = cv2.VideoCapture(r'C:\Users\25584\Desktop\vtest.avi')  #加载视频
mog1 = cv2.bgsegm.createBackgroundSubtractorMOG()  #创建mog对象
mog2 = cv2.createBackgroundSubtractorMOG2()
mog3 = cv2.bgsegm.createBackgroundSubtractorGMG(30)   #初始化帧数取30吧

while True:
    ret, frame = cap.read()
    if ret:
        fgmask1 = mog1.apply(frame)  #传入frame就生成一个前景对象的掩码
        fgmask2 = mog2.apply(frame) 
        fgmask3 = mog3.apply(frame) 
        cv2.imshow('img1', fgmask1)  #显示前景对象
        cv2.imshow('img2', fgmask2)
        cv2.imshow('img3', fgmask3) 
    else:
        break
        
    k = cv2.waitKey(10)    #设置退出
    if k == 27:
        break
cap.release()   #释放资源
cv2.destroyAllWindows()

到了这里,关于【OpenCV】第二十章: 图像及视频去背景的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【opencv】教程代码 —video(3) 视频背景剔除

    bg_sub.cpp 这段代码的功能是 把视频中的背景和前景分离,提取出前景的运动物体 。根据用户选择的不同的模式,可以选择 基于MOG2或者基于KNN的方法 来进行背景减除。在处理每一帧图像的过程中,首先使用背景减除模型对图像帧进行处理,得到一个前景掩码,该掩码中包含了

    2024年04月13日
    浏览(46)
  • 使用OpenCV与深度学习去除图像背景:Python实现指南

    第一部分:简介和OpenCV的背景去除 在现代的图像处理和计算机视觉应用中,背景去除是一个常见的需求。这不仅用于产品摄影和电商平台,还广泛应用于各种图像分析任务。在这篇文章中,我们将使用OpenCV和深度学习技术来实现此功能,并通过Python进行实现。本教程会介绍两

    2024年01月20日
    浏览(43)
  • Python 基于 OpenCV 视觉图像处理实战 之 背景知识

    目录 Python  基于 OpenCV 视觉图像处理实战  之 背景知识 一、简单介绍 二、人工智能(Artificial Intelligence,AI) 三、OpenCV 四、计算机视觉任务的主要类型 五、计算机视觉是通过创建人工模型来模拟本该由人类执行的视觉任务。 Python是一种跨平台的计算机程序设计语言。是一

    2024年04月12日
    浏览(58)
  • 详解OpenCV的视频背景/前景分割(背景建模/前景提取)类cv::BackgroundSubtractorMOG2,并利用它实现对道路监控视频前景/背景的提取

    cv::BackgroundSubtractorMOG2和cv::bgsegm::BackgroundSubtractorMOG一样,都是基于高斯混合模型的背景与前景分割算法。 cv::BackgroundSubtractorMOG2是对cv::bgsegm::BackgroundSubtractorMOG的改进,经过改进,它实现了自适应高斯混合模型参数的更新,增强了复杂场景背景检测的性能。 具体的算法原理可

    2023年04月18日
    浏览(31)
  • C# OpenCVSharp图像入门_给绿幕图片视频加背景

    OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的 图像处理计算机视觉以及模式识别程序。该程序库也可以使用英特尔公司的IPP进

    2024年02月13日
    浏览(44)
  • 第二十章hive

    1) 窗口函数 over(partition by 分组字段 order by 排序字段 rows between 起始行 and 结束行) 窗口计算范围的指定 需要使用rows 进行指定 计算行数 范围的确认: 默认情况下没有指定partition by 的字段,范围是全表,如果指定了partition by,范围是分组内的范围 可以通过rows指定计算行的

    2024年04月28日
    浏览(29)
  • 第二十章 中介者模式

    提示:以下是本篇文章正文内容,下面案例可供参考 闹钟 Alarm 咖啡机 CoffeeMachine TV 窗帘 Curtains

    2024年02月02日
    浏览(33)
  • 第二十章 Unity 渲染管线

    渲染管线是计算机图形中最基础最核心的部分,它是将3D场景显示到2D平面的技术过程。在DirectX课程中,我们就介绍了渲染管线,分为固定渲染管线和可编程渲染管线(Shader)。但是在DirectX 10版本之后统一了渲染架构,就是将顶点着色器和像素着色器被合二为一,成为流处理

    2024年02月07日
    浏览(38)
  • Python Opencv实践 - 车辆统计(1)读取视频,移除背景,做预处理

            示例中的图像的腐蚀、膨胀和闭运算等需要根据具体视频进行实验得到最佳效果。代码仅供参考。

    2024年02月07日
    浏览(40)
  • 基于OpenCV+CUDA实时视频抠绿、背景合成以及抠绿算法小结

    百度百科上描述抠绿“抠绿是指在摄影或摄像时,以绿色为背景进行拍摄,在后期制作时使用特技机的“色键”将绿色背景抠去,改换其他更理想的背景的技术。”绿幕的使用已经非常普遍,大到好莱坞大片,小到自媒体的节目,一些商业娱乐场景,几乎都用使用。但是很多

    2023年04月09日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包