[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 ...
随机推荐
- SQL抽象语法树及改写场景应用
1 背景 我们平时会写各种各样或简单或复杂的sql语句,提交后就会得到我们想要的结果集.比如sql语句,"select * from t_user where user_id > 10 ...
- ubuntu20.04 利用xrandr命令修改多显示器分辨率
问题描述 笔记本是ThinkPad X1 Extreme Gen3 4K屏,外接了一个27寸的1080P显示器.目标是让两个显示器的"显示效果"分辨率能一致,就如winwods和m ...
- JetBrains Fleet初体验,如何运行一个java项目
序言 各位好啊,我是会编程的蜗牛,JetBrains 日前宣布其打造的下一代 IDE Fleet 正式推出公共预览版,现已开放下载.作为java开发者,对于JetBrains开发的全家桶可以说是印象深 ...
- Go素数筛选分析
Go素数筛选分析 1. 素数筛选介绍 学习Go语言的过程中,遇到素数筛选的问题.这是一个经典的并发编程问题,是某大佬的代码,短短几行代码就实现了素数筛选.但是自己看完原理和代码后一脸懵逼(仅此几行能实 ...
- 齐博x2自建流媒体RTMP直播服务器
这里只讲解大家最容易配置的Windows版,测试环境是2008版服务器及WIN7下载下面的软件,解压在任何目录都可,然后双击"启动.bat"即可http://down.php168 ...
- 1.WEB应用模式
1. Web应用模式 在开发Web应用中,有两种应用模式: 前后端不分离[客户端看到的内容和所有界面效果都是由服务端提供出来的.] 前后端分离[把前端的界面效果(html,css,js分离到另一个服务 ...
- pycharm系列---django
manage debug Python Console基本配置 DJANGO_SETTINGS_MODULE=mini_project.settings import sys import djang ...
- webpack4--按需加载
在做单页面应用的过程中,通常利用webpack打包文件,将依赖的外部问价单独打一个vendor.js.这样就会有个问题,这个文件会随着你引用的包的增多,体积会越来越大.在路由中利用import 引用文 ...
- Byte和byte的区别
Byte和byte的区别 背景 今天学习网络编程中,在建立Udp连接时,使用byte[]数组接收传输的数据,但是byte[]错写为Byte[],导致错误. //接收数据: Byt ...
- 如何通过Java导出带格式的 Excel 数据到 Word 表格
在Word中制作报表时,我们经常需要将Excel中的数据复制粘贴到Word中,这样则可以直接在Word文档中查看数据而无需打开另一个Excel文件.但是如果表格比较长,内容就会存在一定程度的丢失,无法 ...