百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

[OpenCV实战]3 透明斗篷

toyiye 2024-06-21 11:55 13 浏览 0 评论

透明斗篷

弄出哈利波特电影里一样效果的透明斗篷。也就是一个视频里,将红布弄成透明。类似下面的效果。

添加图片注释,不超过 140 字(可选)

基本思想如下:

1寻找和存储背景帧。

2用颜色检测算法检测红色布。

3提取红色区域。

4背景帧红布区域替换当前帧红布区域。

1寻找和存储背景帧

算法关键思想是用背景像素替换与布相对应的当前帧像我们需提取和存储背景帧。背景帧检测算法很简单,实际上算不上背景帧建模算法。仅仅设定视频第31帧为背景图像。如果想了解背景帧提取算法可以看看背景建模算法,比如混合高斯背景建模算法。

C++代码如下:


    Mat background;
    //跳过前30帧
    for (int i = 0; i < 30; i++)
    {
        cap >> background;
    }
    //沿Y轴翻转图像
    flip(background, background, 1);

2红色区域检测

事实上基于RGB空间检测红色很困难,因为红色是RGB综合获得的。正确的方法是将图像从RGB颜色空间转到HSV空间。HSV对颜色的定义更接近人的视觉系统。对于颜色检测来说,HSV空间中,

HSV空间各个参数如下:

色调Hue:用角度度量,取值范围为0-度360度。可以认为0度对应于红色,120度对应于绿色,240度对应于蓝色。

饱和度Saturation:饱和度表示颜色的强度和纯度。例如,粉红色不如大红色饱和。

明度Value:表示颜色的明暗程度,取值范围为0.0(黑色)~1.0(白色)。

添加图片注释,不超过 140 字(可选)

img

颜色仅由色调Hue决定。在OpenCV中色调不是0到360度,而被量化为0到180。

其中红色以0-30和150-180表示。

红色区域检测主要原理如下:

基于OpenCV中的inRange函数筛选颜色。其中红色Hue值的范围为0-10和170-180,以避免发现皮肤为红色。因为红布应该是高度饱和的红色。所以S值设定为120到255。明度设置为70到255。根据以上能够获得红色Hue值的范围为0-10和170-180d的两个红色区域。然后对其做并操作提取图像红色区域(红布区域)范围二值图像。所获得二值图像中白色部分(像素值为255)表示红布,黑色部分(像素值为0)表示背景。结果如下图所示:

添加图片注释,不超过 140 字(可选)

添加图片注释,不超过 140 字(可选)

c++代码如下:


        //检测帧
        Mat frame;

        // Capture frame-by-frame
        cap >> frame;

        // If the frame is empty, break immediately
        if (frame.empty())
        {
            break;
        }
        //hsv图像
        Mat hsv;
        flip(frame, frame, 1);
        cvtColor(frame, hsv, COLOR_BGR2HSV);

        //红色区域1,红色区域2
        Mat mask1, mask2;
        //红色区域
        Mat mask_red;
        //背景区域
        Mat mask_background;
        //过滤颜色
        //二值图,其中黑色0表示无红色,白色1表示红色区域。
        inRange(hsv, Scalar(0, 120, 70), Scalar(10, 255, 255), mask1);
        inRange(hsv, Scalar(170, 120, 70), Scalar(180, 255, 255), mask2);
        mask_red = mask1 + mask2;

3提取红色区域

主要是通过红布区域范围二值图像提取红色区域图像(背景为黑色),并将背景图像中红布区域置为黑色。结果分别如下图所示

添加图片注释,不超过 140 字(可选)

添加图片注释,不超过 140 字(可选)

c++代码如下:


        //去除噪声
        Mat kernel = Mat::ones(3, 3, CV_32F);
        morphologyEx(mask_red, mask_red, cv::MORPH_OPEN, kernel);
        morphologyEx(mask_red, mask_red, cv::MORPH_DILATE, kernel);

        //将mask_red中0,1互换,得到背景区域范围。
        bitwise_not(mask_red, mask_background);
        Mat res1, res2, final_output;
        //从当前帧抠出背景区域res1,红布区域被涂成黑色。
        bitwise_and(frame, frame, res1, mask_background);
        //从背景帧提取红布区域覆盖的背景res2
        bitwise_and(background, background, res2, mask_red);

4背景帧红布区域替换当前帧红布区域。

最后通过 addWeighted 函数将上面两张图融合。这样就能弄出透明的效果。只能针对特定视频,所用视频及代码见:

https://download.csdn.net/download/luohenyj/11001759

https://github.com/luohenyueji/OpenCV-Practical-Exercise

如果没有积分(系统自动设定资源分数)看看参考链接。我搬运过来的,大修改没有。pch是预编译文件。视频有红布出现在第250帧后。

5工程代码

实际上这种方法只有在特定场合实用,来练手还是挺适合的。全部代码如下:

C++版本


#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    //打开视频
    VideoCapture cap("video/detect.mp4");

    // 检查视频是否打开
    if (!cap.isOpened())
    {
        cout << "Error opening video stream or file" << endl;
        return -1;
    }

    Mat background;
    //跳过前30帧
    for (int i = 0; i < 30; i++)
    {
        cap >> background;
    }
    //沿Y轴翻转图像
    flip(background, background, 1);
    //红布第251帧才出现,跳过前250帧
    for (int i = 0; i < 220; i++)
    {
        Mat frame_slip;
        cap >> frame_slip;
        continue;
    }


    //图像读取
    while (1)
    {
        //检测帧
        Mat frame;

        // Capture frame-by-frame
        cap >> frame;

        // If the frame is empty, break immediately
        if (frame.empty())
        {
            break;
        }
        //hsv图像
        Mat hsv;
        flip(frame, frame, 1);
        cvtColor(frame, hsv, COLOR_BGR2HSV);

        //红色区域1,红色区域2
        Mat mask1, mask2;
        //红色区域
        Mat mask_red;
        //背景区域
        Mat mask_background;
        //过滤颜色
        //二值图,其中黑色0表示无红色,白色1表示红色区域。
        inRange(hsv, Scalar(0, 120, 70), Scalar(10, 255, 255), mask1);
        inRange(hsv, Scalar(170, 120, 70), Scalar(180, 255, 255), mask2);
        mask_red = mask1 + mask2;

        //去除噪声
        Mat kernel = Mat::ones(3, 3, CV_32F);
        morphologyEx(mask_red, mask_red, cv::MORPH_OPEN, kernel);
        morphologyEx(mask_red, mask_red, cv::MORPH_DILATE, kernel);

        //将mask_red中0,1互换,得到背景区域范围。
        bitwise_not(mask_red, mask_background);
        Mat res1, res2, final_output;
        //从当前帧抠出背景区域res1,红布区域被涂成黑色。
        bitwise_and(frame, frame, res1, mask_background);
        //从背景帧提取红布区域覆盖的背景res2
        bitwise_and(background, background, res2, mask_red);

        addWeighted(res1, 1, res2, 1, 0, final_output);
        //展示图像
        imshow("Magic !!!", final_output);
        // Press  ESC on keyboard to exit
        char c = (char)waitKey(1);
        if (c == 27)
        {
            break;
        }
    }

    return 0;
}

python代码:


import cv2
import numpy as np
import time


# Creating an VideoCapture object
# This will be used for image acquisition later in the code.
cap = cv2.VideoCapture('video/detect.mp4')

if cap.isOpened:
    print("your video is opened")
# We give some time for the camera to setup
time.sleep(3)
count = 0
background=0

# Capturing and storing the static background frame
for i in range(60):
    ret,background = cap.read()

background = np.flip(background,axis=1)

    
#跳帧
for i in range(200):
    slip_frame = cap.read()
while(cap.isOpened()):

    ret, img = cap.read()
    if not ret:
        break
    count+=1
    img = np.flip(img,axis=1)
    
    # Converting the color space from BGR to HSV
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # Generating mask to detect red color
    lower_red = np.array([0,120,70])
    upper_red = np.array([10,255,255])
    mask1 = cv2.inRange(hsv,lower_red,upper_red)

    lower_red = np.array([170,120,70])
    upper_red = np.array([180,255,255])
    mask2 = cv2.inRange(hsv,lower_red,upper_red)

    mask1 = mask1+mask2

    # Refining the mask corresponding to the detected red color
    mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, np.ones((3,3),np.uint8),iterations=2)
    mask1 = cv2.dilate(mask1,np.ones((3,3),np.uint8),iterations = 1)
    mask2 = cv2.bitwise_not(mask1)

    # Generating the final output
    res1 = cv2.bitwise_and(background,background,mask=mask1)
    res2 = cv2.bitwise_and(img,img,mask=mask2)
    final_output = cv2.addWeighted(res1,1,res2,1,0)

    cv2.imshow('Magic !!!',final_output)
    k = cv2.waitKey(10)
    if k == 27:
        break

参考

https://www.learnopencv.com/invisibility-cloak-using-color-detection-and-segmentation-with-opencv/


引用链接

[1] https://download.csdn.net/download/luohenyj/11001759 : https://download.csdn.net/download/luohenyj/11001759

[2] https://github.com/luohenyueji/OpenCV-Practical-Exercise: https://github.com/luohenyueji/OpenCV-Practical-Exercise

[3] https://www.learnopencv.com/invisibility-cloak-using-color-detection-and-segmentation-with-opencv/ : https://www.learnopencv.com/invisibility-cloak-using-color-detection-and-segmentation-with-opencv/

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码