- 分割算法选择
背景融合 – 高斯模糊
遮罩层生成 - 不使用GMM或者K-means:处理非常慢
而基于色彩的处理方法
RGB与HSV色彩空间 - 过程:
加载视频、帧图像、转为HSV、模型Mask、背景融合替换、显示帧图像、下一帧(循环获取帧图像)、终止
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat bg;//背景图 大小要与 视频流 大小一致
Mat Repalce_and_Belnd(Mat& frame, Mat& mask);
int main(int argc, char** argv)
{
VideoCapture capture;
capture.open("../path.mp4");
if (!capture.isOpened())
{
printf("could not find the video file...\n");
return -1;
}
bg = imread("../background.jpg");
if (bg.empty())
{
cout << "could not load image..." << endl;
return -1;
}
Mat frame,hsv,mask;
while (capture.read(frame))
{
cvtColor(frame, hsv, COLOR_BGR2HSV);
//测试矩阵hsv的元素是否在其他两个矩阵的值之间
inRange(hsv,
Scalar(35, 43, 46), //lowberb//提取HSV中Green的值
Scalar(155, 255, 255),//upperb
mask);//mask = lowberb <= hsv <= upperb
//形态学操作
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
morphologyEx(mask,mask, MORPH_CLOSE, kernel);
erode(mask, mask, kernel);
//高斯模糊
GaussianBlur(mask, mask, Size(3, 3), 0, 0);
//混合图像通道
Mat dst = Repalce_and_Belnd(frame, mask);
char c = waitKey(1);
if (c == 27)
{
break;
}
//imshow("mask", mask);
//imshow("src_Video", frame);
imshow("Blend_video", dst);
}
waitKey(0);
return 0;
}
Mat Repalce_and_Belnd(Mat& frame, Mat& mask)
{
Mat dst = Mat::zeros(frame.size(), frame.type());
int width = frame.cols;
int height = frame.rows;
int dims = frame.channels();
//通道混合
for (int row = 0; row < height; row++)
{
uchar* frame_row = frame.ptr<uchar>(row);
uchar* bg_row = bg.ptr<uchar>(row);
uchar* mask_row = mask.ptr<uchar>(row);
uchar* dst_row = dst.ptr<uchar>(row);
for (int col = 0; col < width; col++)
{
int temp = *mask_row++;//当前mask像素索引值
if (temp == 255)//背景 赋予背景图的像素
{
*dst_row++ = *bg_row++;//b
*dst_row++ = *bg_row++;//g
*dst_row++ = *bg_row++;//r
//同时*frame_row跳过一个像素值(bgr),即+3
frame_row += 3;
}
else if (temp == 0)//前景 赋予原视频frame的像素
{
*dst_row++ = *frame_row++;//b
*dst_row++ = *frame_row++;//g
*dst_row++ = *frame_row++;//r
//同时*bg_row跳过一个像素值(bgr),即+3
bg_row += 3;
}
else //边缘处混合
{
double weight = temp / 255;//权重值
//frame的rgb值
int b_frame = *frame_row++;
int g_frame = *frame_row++;
int r_frame = *frame_row++;
//bg的rgb值
int b_bg = *bg_row++;
int g_bg = *bg_row++;
int r_bg = *bg_row++;
int b = b_frame * weight + b_bg * (1 - weight);
int g = g_frame * weight + g_bg * (1 - weight);
int r = r_frame * weight + r_bg * (1 - weight);
*dst_row++ = b;
*dst_row++ = g;
*dst_row++ = r;
}
}
}
return dst;
}
原视频为绿幕背景,更换同尺寸背景图片,输出结果:
来源:CSDN
作者:丶小早
链接:https://blog.csdn.net/weixin_45553439/article/details/104373260