美文网首页
基于色彩阈值实现背景替换

基于色彩阈值实现背景替换

作者: Byte猫 | 来源:发表于2019-05-21 23:15 被阅读0次

    一、静态图片的背景替换

    以证件照替换背景颜色为例子(网上找了个证件照,脸已遮住),其中需要注意的是对蒙版做平滑处理,否则毛刺会比较明显。

    # coding = utf-8
    import numpy as np
    import matplotlib.pyplot as plt
    import cv2 as cv
    
    # 载入图像 
    img = cv.imread('timg.jpg')
    rows, cols, channels = img.shape
    cv.imshow('img',img)
     
    # 转换hsv,得到轮廓蒙版
    hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
    lower_blue = np.array([78,43,46])
    upper_blue = np.array([99,255,255])
    mask = cv.inRange(hsv, lower_blue, upper_blue)
    # 采用中值滤波平滑边缘
    mask = cv.medianBlur(mask, 15)
    cv.imshow('Mask', mask)
     
    # 腐蚀膨胀(形态学处理)
    erode = cv.erode(mask,None,iterations=1)
    dilate = cv.dilate(erode,None,iterations=1)
    cv.imshow('dilate',dilate)
    
    # 遍历替换颜色
    for i in range(rows):
      for j in range(cols):
        if dilate[i,j]==255:
          img[i,j]=(0,0,255) # 此处替换颜色,为BGR通道
    cv.imshow('res', img)
     
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    膨胀和腐蚀称为形态运算。通常在二元图像上执行,类似于轮廓检测。膨胀通过向图像中的对象的边缘添加像素,放大亮白区域。腐蚀正好相反:它会删除对象边缘的像素,并缩小对象的大小。
    (1)膨胀
    要在 OpenCV 中膨胀图像,你可以使用 dilate 函数和三个输入:原始二元图像、确定膨胀大小的内核(均不会导致默认大小)以及进行膨胀的迭代次数(通常为 1)。在下面的示例中,我们用到一个 5x5 内核,它像过滤器一样在图像上移动,如果在 5x5 窗口中,像素周围的任何像素是白色,则使该像素变成白色!
    kernel = np.ones((5,5),np.uint8)
    dilation = cv2.dilate(image, kernel, iterations = 1)
    (2)腐蚀
    要腐蚀图像,我们将采用相同的步骤,但是使用 erode 函数。
    erosion = cv2.erode(image, kernel, iterations = 1)
    (3)开运算
    我们通常结合上述两者一起使用以达到期望的结果。一种此类结合运算称为开运算,即先腐蚀后膨胀。有助于降噪,腐蚀先消除噪点(并缩小对象),然后膨胀会再次放大对象,但是之前的腐蚀已经消除噪点!
    在 OpenCV 中实现这一点,我们对原图采用函数 morphologyEx,执行想要执行的操作并传入内核。
    opening = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)


    (4)闭运算
    闭运算是开运算的逆向组合,先膨胀后腐蚀,有助于填充对象上的小洞或黑色区域。
    closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

    了解更多

    二、视频的背景替换

    基于hsv颜色空间的实时背景替换:


    # coding = utf-8
    import numpy as np
    import cv2 as cv
    import time
    
    def backReplace(img):
        '''
        替换视频帧背景
        '''
        # 转换hsv
        hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
        lower_blue = np.array([0,0,46])
        upper_blue = np.array([180,43,220])
        mask = cv.inRange(hsv, lower_blue, upper_blue)
        # 采用中值滤波平滑边缘
        mask = cv.medianBlur(mask, 15)
        
        # 腐蚀膨胀
        erode = cv.erode(mask,None,iterations=2)
        dilate = cv.dilate(erode,None,iterations=3)
    
        # 遍历替换
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                if dilate[i,j]==255:
                    img[i,j]=(0,0,255) # 此处替换颜色,为BGR通道
        return img
    
    def video_save(num_frames, filepath, out_fps):
        '''
        打开摄像头并保存视频
        INPUT -> 捕获总帧数, 视频保存路径, 输出帧率
        '''
        
        cap = cv.VideoCapture(0)  # VideoCapture(0)表示打开默认的相机
        if cap.isOpened() is False:   # 确认摄像头是否成功打开
            print('Error')
            exit(1)
    
        # 获取捕获的分辨率
        size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)),
                int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
        # 设置要保存视频的编码,分辨率和帧率
        video = cv.VideoWriter(
            filepath,
            cv.VideoWriter_fourcc('M', 'P', '4', '2'),   # 视频编码格式参考:http://www.fourcc.org/codecs.php
            out_fps,   # 输出文件的帧率
            size
        )
    
        for i in range(num_frames):
            ret, frame = cap.read()
            video.write(backReplace(frame))
            # time.sleep(interval)  捕获图像的间隔(秒)
    
        # 释放资源并写入视频文件
        video.release()
        cap.release()
    
    video_save(50, '100000.avi', 24)
    

    附:hsv颜色空间
    H: 0-180 S:0-255 V:0-255

    相关文章

      网友评论

          本文标题:基于色彩阈值实现背景替换

          本文链接:https://www.haomeiwen.com/subject/rlxszqtx.html