目的: 利用OpenCv 实现对颜色的过滤,实现魔法袍的效果
UE4 + OpenCV + 魔法袍
一,本文目的:
实现通过摄像头捕捉画面, 体验者身披特定颜色长跑,可以实现类似魔法长袍的效果。
二,开发环境
UE4 4.15 (必须此版本,其他版本的openCV 集成有问题)
VS2015 (OpenCV 的环境变量 按照百度配置)
三,开发步骤
思路:
关键步骤解析:
1, 初始保存图片
初始化 begin pla y 中 读取50帧的画面 存入一个mat 变量中。下面的代码是在纯vs 中的代码。 如果要迁移到UE4 中, 记住将 baakground 变量定义在。H 文件中。
Mat background;
for (int i = 0; i < 60; i++)
{
cap >> background;
}
flip(background, background, 1);
2,读取图片 ,镜像
Mat frame;
// Capture frame-by-frame
cap >> frame;
if (frame.empty())
break;
// imshow("FG Segmentation", frame);
Mat hsv;
flip(frame, frame, 1); //图像绕Y 轴翻转, 摄像头获取的画面是镜像 我们翻转过来
3,转换为hsv 格式的图像
cvtColor(frame, hsv, COLOR_BGR2HSV); // RGB —— HSV
4,创建掩膜
Mat mask1, mask2;
inRange(hsv, Scalar(0, 120, 45), Scalar(8, 255, 255), mask1); // p判断hsv 中 的每一个像素 是否在 两个颜色范围之内, 如果是 则dst 对应的像素就是255, 否则变为0
inRange(hsv, Scalar(156, 120, 45), Scalar(180, 255, 255), mask2);
mask1 = mask1 + mask2;
注意这两个掩膜的范围 只是针对于红色的情况, 网站上写的是避免 人的皮肤的影像,实际上没有什么用。
此处插播广告:
HSV是一种在人们生活中甚至更常用的颜色系统,H——Hue即色相,就是我们平时所说的红、绿,如果你分的更细的话可能还会有洋红、草绿等等;在HSV模型中,用度数来描述色相,其中红色对应0度,绿色对应120度,蓝色对应240度。
S——Saturation即饱和度,色彩的深浅度(0-100%) ,对于一种颜色比如红色,我们可以用浅红——大红——深红——红得发紫等等语言来描述它(请原谅一个纯理科生的匮乏的颜色系统),对应在画水彩的时候即一种颜料加上不同分量的水形成不同的饱和度。
V——Value即色调,纯度,色彩的亮度(0-100%) ,这个在调整屏幕亮度的时候比较常见。当V=0时,颜色最暗,最暗被描述为黑色,因此此时H(无论什么颜色最暗都为黑色)和S(无论什么深浅的颜色最暗都为黑色)均无意义。
通过以上对照表 我们可以看到红色对应的范围。
3,掩膜处理
Mat kernel = Mat::ones(3, 3, CV_32F);
Mat kernel1= getStructuringElement(MORPH_ELLIPSE, Size(3, 3), Point(-1, -1)); //自己修改的,后添加的,第一个参数代表的是划算的形状;第二个是相邻的像素点
morphologyEx(mask1, mask1, cv::MORPH_OPEN, kernel1); //开运算是对图像先腐蚀再膨胀,可以排除小团的物体,
morphologyEx(mask1, mask1, cv::MORPH_DILATE, kernel1);
// 此时的mask1 ROI 区域为白色255 ,其他区域为黑色0
插播广告:
在进行腐蚀和膨胀的讲解之前,首先需要注意,腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
4,创建另外一个掩膜
bitwise_not(mask1, mask2);
//mask2 ROI 红色区域 为黑色0, 其他区域为白255色; 、、、、
mask1 ROI 红色区域 为白色255, 其他区域为黑色0
5,输出最后的frame
Mat res1, res2, final_output;
bitwise_and(frame, frame, res1, mask2);
//当前镜头获取的图像,红色的区域变黑, 其他的区域颜色不变,最后输出到res1中 ,红色区域变黑0
imshow("FG3 ", mask2);
建刚加油,看好你!**************************************************************
bitwise_and(background, background, res2, mask1); // 初始化的背景图 ,红色区域255 与操作后,该区域颜色不变; 其他区域颜色全部变为黑色0
addWeighted(res1, 1, res2, 1, 0, final_output); //第一张图融合比例1 ,第二张图融合吧比例2, 偏差为0 , 最后输出final——output,两个画面的融合可以理解为像素的相加。 黑色的区域像素为0 ,所以相加之后,黑色不影响
2019-2-28 by小飞