效果图:
介绍
这是一个比较简易粗糙的抠图demo ,基于HSV进行抠图.
适合用于背景颜色大片相似的情况下.
但因为是demo,所以比较粗糙。
写的过程中翻看了很多博客,所以很多内容都是从大牛博客中学习的
如有相似代码,那基本上都是学习大牛的 哈哈哈
写这个demo的目的主要是为了获取合适的HSV的值,当作工具来使用的
HSV介绍
理论:
- HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。
- HSV即色相(Hue)、饱和度(Saturation)、明度(Value),又称HSB(B即Brightness)。
- 色相是色彩的基本属性,就是平常说的颜色的名称,如红色、黄色等。
- 饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
- 明度(V),取0-max(计算机中HSV取值范围和存储的长度有关)。
- HSV颜色空间可以用一个圆锥空间模型来描述。
- 圆锥的顶点处,V=0,H和S无定义,代表黑色。圆锥的顶面中心处V=max,S=0,H无定义,代表白色。如上图。
转换:
- RGB -> HSV
设max等于r、g和b中的最大者,min为最小者。对应的HSV空间中的(h,s,v)值为:
h在0到360°之间,s在0到100%之间,v在0到max之间。
- HSV -> RGB
- opencv 里面给我们提供了一种比较便捷的转换方式:
RGB -> HSV cvtColor ( RGB, HSV, COLOR_BGR2HSV );
HSV -> BGR cvtColor ( HSV, BGR, COLOR_HSV2BGR );
具体内容
- 读取配置文件中目的图片和背景图片的地址
- 读取图片后判断是否成功
Frame = imread(Add); Back = imread(BAdd); if (Frame.empty() || Back.empty()) { cout << "Frame/Back read Failed !" << endl; system("pause"); return -1; }
- 创建滑条 窗口等准备工作
namedWindow(WIN); createTrackbar("Huemin", WIN, &h, hsvMax); createTrackbar("Huemax", WIN, &h2, hsvMax); createTrackbar("Saturationmin", WIN, &s, hsvMax); createTrackbar("Valuemin", WIN, &v, hsvMax);
- 目标图片转成HSV格式
cvtColor(Frame, Hsv, COLOR_BGR2HSV);
- 处理图片
//颜色范围,将结果存在mask中 inRange(Hsv, Scalar(h, s, v), Scalar(h2, 255, 255), Mask); //对视频的每一帧的图像与背景进行混合处理 ,返回结果给result Mat result = BlendFrame(Frame, Mask); string print = format(" Huemin = %d\n Huemax = %d\n Saturationmin = %d\n Valuemin =%d\n\n\n", h, h2, s, v); cout << print.c_str() << endl; imshow("mask", Mask); imshow(WIN, result);
- 每一帧进行图像混合
//创建一张结果图 cv::Mat result = cv::Mat(frame.size(), frame.type()); //图像的高 宽 与通道数 int height = result.rows; int width = result.cols; int channels = result.channels(); //mask的像素值 int m = 0; //融合的比例 double wt = 0; //输出的像素 int r = 0, g = 0, b = 0; int r1 = 0, g1 = 0, b1 = 0; int r2 = 0, g2 = 0, b2 = 0;
- 通过图像的宽高进行循环混合
//读取mask的像素值 m = *pmask++;
- 判断是否前景背景
//如果是背景的话 if (m == 255) { //进行三个通道的赋值 *presult++ = *pbg++; *presult++ = *pbg++; *presult++ = *pbg++; //将frame的图像的像素的通道也移动单个保持一致 pframe += 3; } //如果是前景的话 else if (m == 0) { //进行三个通道的赋值 *presult++ = *pframe++; *presult++ = *pframe++; *presult++ = *pframe++; //将frame的图像的像素的通道也移动单个保持一致 pbg += 3; }
- 其余的情况下
//背景图每个像素的三个通道 b1 = *pbg++; g1 = *pbg++; r1 = *pbg++; //每一帧每一个像素的三个通道 b2 = *pframe++; g2 = *pframe++; r2 = *pframe++; // 权重 wt = m / 255.0; // 混合 b = b1*wt + b2*(1.0 - wt); g = g1*wt + g2*(1.0 - wt); r = r1*wt + r2*(1.0 - wt); *presult++ = b; *presult++ = g; *presult++ = r;
- 可以再写一个输出,调整到满意的图像后把该图像的HSV导出,就能实现一个获取目标图像HSV的工具的功能啦
运行结果图 分别是原图 背景图 Mask 结果图:
备注:
- 背景大小要与目标图片一致。
- 处理图片时写成循环方便调整。
- 处理HSV图像的时候,可以做一些边缘模糊,这样融合后不会太突兀,但是因为时个demo 所以这个版本里就没写。
demo地址:https://download.csdn.net/download/weixin_41794771/11632053
以上为学习笔记。