C++OpenCV系统学习(17)——图像分割与抠图(6)——视频背景替换

1.关键知识点

  • 分割算法选择
  • 背景融合-高斯模糊
  • 遮罩层生成

1.1分割算法的选择

  • GMM/Kmeans:对视频的第一帧做trainning,对其他帧只做预言不做trainning。
  • .基于色彩的处理方式
  • RGB与HSV空间

    最终看哪个方法失效更好。对视频的第一帧做trainning,对其他帧只做预言不做trainning。

 1.2知识点补充

1.2.1概括

         HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。

  • 色调H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
  • 饱和度S:取值范围为0.0~1.0;
  • 亮度V:取值范围为0.0(黑色)~1.0(白色)。

        RGB和CMY颜色模型都是面向硬件的,而HSV(Hue Saturation Value)颜色模型是面向用户的。HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。

1.2.2HSV颜色分量范围

一般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本色中对应的HSV分量需要给定一个严格的范围,下面是通过实验计算的模糊范围(准确的范围在网上都没有给出)。

H:  0— 180

S:  0— 255

V:  0— 255

此处把部分红色归为紫色范围:

2.完整程序

#include <opencv2/opencv.hpp>
#include<iostream>

using namespace std;
using namespace cv;

Mat replace_and_blend(Mat& frame, Mat& mask);
Mat background_01;
Mat background_02;

int main()
{
	background_01 = imread("F:\\opencv\\opencv\\sources\\samples\\data\\leuvenA.jpg");
	background_02 = imread("F:\\opencv\\opencv\\sources\\samples\\data\\leuvenB.jpg");
	VideoCapture capture;
	capture.open("F:\\opencv\\opencv\\sources\\samples\\data\\Megamind.avi");
	if (!capture.isOpened())
	{
		printf("could not find the video file...\n");
		return -1;
	}
	namedWindow("input video", WINDOW_AUTOSIZE);
	namedWindow("new video", WND_PROP_AUTOSIZE);
	Mat frame,hsv,mask;
	int count = 0;
	while (capture.read(frame))
	{
		cvtColor(frame, hsv, COLOR_BGR2HSV);
		inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
		//形态学操作
		Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
		morphologyEx(mask, mask, MORPH_CLOSE, k);
		erode(mask, mask, k);
		GaussianBlur(mask, mask, Size(3, 3), 0, 0);

		Mat result = replace_and_blend(frame, mask);

		imshow("mask", mask);
		
		char c = waitKey(1);
		if (c == 27)
		{
			break;
		}
		imshow("output result", result);
		imshow("input video", frame);
	}
	waitKey(0);
	return 0;
}


Mat replace_and_blend(Mat& frame, Mat& mask)
{
	Mat result = Mat::zeros(frame.size(), frame.type());
	int h = frame.rows;
	int w = frame.cols;
	int dims = frame.channels();

	//replace and blend
	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;

	for (int row = 0; row < h; row++)
	{
		uchar* current = frame.ptr<uchar>(row);
		uchar* bgrow = background_01.ptr<uchar>(row);
		uchar* maskrow = mask.ptr<uchar>(row);
		uchar* targetrow = result.ptr<uchar>(row);
		for (int col = 0;col<w;col++)
		{
			m = *maskrow++;
			if (m == 255)//背景
			{
				*targetrow++ = *bgrow++;
				*targetrow++ = *bgrow++;
				*targetrow++ = *bgrow++;
				current += 3;
			}
			else if (m == 0)//前景
			{
				*targetrow++ = *current++;
				*targetrow++ = *current++;
				*targetrow++ = *current++;
				bgrow += 3;
			}
			else
			{
				b1 = *bgrow++;
				g1 = *bgrow++;
				r1 = *bgrow++;

				b2 = *current++;
				g2 = *current++;
				r2 = *current++;

				//混合权重
				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);

				*targetrow++ = b;
				*targetrow++ = g;
				*targetrow++ = r;
			}
		}
	}
	return result;
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI炮灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值