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

基本思想如下:
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(白色)。

颜色仅由色调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)表示背景。结果如下图所示:


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


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/
[OpenCV实战]3 透明斗篷的更多相关文章
- OpenCV实战:人脸关键点检测(FaceMark)
Summary:利用OpenCV中的LBF算法进行人脸关键点检测(Facial Landmark Detection) Author: Amusi Date: 2018-03-20 ...
- [OpenCV实战]50 用OpenCV制作低成本立体相机
本文主要讲述利用OpenCV制作低成本立体相机以及如何使用OpenCV创建3D视频,准确来说是模仿双目立体相机,我们通常说立体相机一般是指双目立体相机,就是带两个摄像头的那种(目就是指眼睛,双目就是两 ...
- [OpenCV实战]49 对极几何与立体视觉初探
本文主要介绍对极几何(Epipolar Geometry)与立体视觉(Stereo Vision)的相关知识.对极几何简单点来说,其目的就是描述是两幅视图之间的内部对应关系,用来对立体视觉进行建模,实 ...
- [OpenCV实战]48 基于OpenCV实现图像质量评价
本文主要介绍基于OpenCV contrib中的quality模块实现图像质量评价.图像质量评估Image Quality Analysis简称IQA,主要通过数学度量方法来评价图像质量的好坏. 本文 ...
- 使用opencv为没有透明通道的图像加入透明通道
在图像处理中,我们经常需要处理带透明通道的图片,比如为图片或视频添加水印,为图片或视频添加字幕.贴图等.然而,我们的素材图片未必总是带有透明通道.比如,素材的背景本该透明的地方,却是黑色和白色.有时, ...
- opencv实战——图像矫正算法深入探讨
摘要 在机器视觉中,对于图像的处理有时候因为放置的原因导致ROI区域倾斜,这个时候我们会想办法把它纠正为正确的角度视角来,方便下一步的布局分析与文字识别,这个时候通过透视变换就可以取得比较好的裁剪效果 ...
- 用python进行OpenCV实战之用OpenCV3实现图片载入、显示和储存(argparse详细解释)
将下面文档存为load_display_save.py #-*- coding:utf-8 -*- ap = argparse.ArgumentParser() ap.add_argument(&qu ...
- [OpenCV实战]45 基于OpenCV实现图像哈希算法
目前有许多算法来衡量两幅图像的相似性,本文主要介绍在工程领域最常用的图像相似性算法评价算法:图像哈希算法(img hash).图像哈希算法通过获取图像的哈希值并比较两幅图像的哈希值的汉明距离来衡量两幅 ...
- [OpenCV实战]8 深度学习目标检测网络YOLOv3的训练
目录 1 数据集 1.1 下载openImages雪人数据[约1.5小时] 1.2 训练集测试集拆分 2 Darknet 2.1 下载并构建Darknet 2.2 修改代码以定期保存模型文件 2.3 ...
随机推荐
- JUC(5)BlockingQueue四组API
1.读写锁ReadWriteLock package com.readlock; import java.util.HashMap; import java.util.Map; /** * ReadW ...
- rabbitmq原理和应用
0.1.索引 https://blog.waterflow.link/articles/1663772504649 RabbitMQ 是一个轻量级且易于部署的消息队列.它支持开箱即用的多种消息传递协议 ...
- 九、Django3的ASGI
九.Django3的ASGI 9.1.Web应用程序和web服务器 Web应用程序(Web)是一种能完成web业务逻辑,能让用户基于web浏览器访问的应用程序,它可以是一个实现http请求和响应功能的 ...
- 一键部署haproxy脚本
HAPROXY_VERSION=2.6.6 HAPROXY_FILE=haproxy-${HAPROXY_VERSION}.tar.gz #HAPROXY_FILE=haproxy-2.2.12.ta ...
- Element Ui 安装以及配置
npm 安装 推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用. npm i element-ui -S 引入 Element 你可以引入整个 Element,或是根据需要 ...
- Golang 加密方法
如果想直接使用我下列的库 可以直接go get 我的github go get -u github.com/hybpjx/InverseAlgorithm md5 加密--不可逆 MD5信息摘要算法是 ...
- TensorFlow?PyTorch?Paddle?AI工具库生态之争:ONNX将一统天下
作者:韩信子@ShowMeAI 深度学习实战系列:https://www.showmeai.tech/tutorials/42 本文地址:https://www.showmeai.tech/artic ...
- 当前数据库表空间达到32G,需要扩容
表空间名:cwy_init 操作:给cwy_init增加数据文件,分配5G的空间,达到瓶颈自动增长1G,如下: alter tablespace cwy_init add datafile '/u01 ...
- springcloud组件梳理之hystrix
在微服务架构体系中,各服务中间的相互调用是常态,没有哪个服务能保证自身百分百不会出问题,然后再加上网络的波动以及环境等问题,服务间调用的稳定性无法保证,这时候就需要一个有容错能力的组件来介入,当调用出 ...
- 【题解】CF1659E AND-MEX Walk
题目传送门 位运算 设题目中序列 \(w_1,w_1 \& w_2,w_1 \& w_2 \& w_3,\dots,w_1 \& w_2 \& \dots \& ...