#include<opencv2\opencv.hpp>
using namespace cv;
Mat replace_and_blend(Mat &frame, Mat&mask);
Mat background,frame, hsv, mask,result;
int main(int arc, char** argv) {
background = imread("2.jpg");
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("src", background);
VideoCapture capture;
capture.open("1.mp4");
CvSize size = cvSize(capture.get(CV_CAP_PROP_FRAME_WIDTH), capture.get(CV_CAP_PROP_FRAME_HEIGHT));
VideoWriter writer("qq.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'),12.0, size, true);
while (capture.read(frame)) {
imshow("input", frame);
cvtColor(frame, hsv, CV_BGR2HSV);
inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);//颜色过滤,得到mask绿色部分为1,其它部分都为0
imshow("mask", mask);
Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3));
morphologyEx(mask, mask, MORPH_DILATE, kernel);
GaussianBlur(mask, mask, Size(3, 3), 0, 0);//0,0会根据Size自动算的
result = replace_and_blend(frame, mask);
writer.write(result);
char c = waitKey(1);
if (c == 27) {
break;
}
imshow("input", frame);
imshow("result", result);
}
waitKey(0);
return 0;
}
//通过颜色过滤得到的掩码为单通道图像
Mat replace_and_blend(Mat &frame, Mat &mask)
{
int rows = frame.rows;
int cols = frame.cols;
result = Mat::zeros(frame.size(), frame.type());
for (int i = 0; i < rows; i++)
{
uchar *pf = frame.ptr(i);//人物前景
uchar *pm = mask.ptr(i);//掩码
uchar *pb = background.ptr(i);//背景
uchar *pr = result.ptr(i);//结果
for (int j = 0; j < cols; j++)
{
pm++;
if (*pm == 255)//背景
{
pr[3 * j] = pb[3 * j];
pr[3 * j + 1] = pb[3 * j + 1];
pr[3 * j + 2] = pb[3 * j + 2];
}
else if (*pm == 0)//前景
{
pr[3 * j] = pf[3 * j];
pr[3 * j + 1] = pf[3 * j + 1];
pr[3 * j + 2] = pf[3 * j + 2];
}
else //融合部分
{
int m = *pm;
double w = m / 255.0;
pr[3 * j] = w *pb[3 * j] + (1-w) * pf[3 * j];
pr[3 * j + 1] = w * pb[3 * j + 1] + (1-w) * pf[3 * j + 1];
pr[3 * j + 2] = w * pb[3 * j + 2] + (1-w) * pf[3 * j + 2];
//或者取前景和背景的平均值
/*pr[3 * j] = (pb[3 * j] + pf[3 * j])/2;
pr[3 * j + 1] = (pb[3 * j + 1] + pf[3 * j + 1])/2;
pr[3 * j + 2] = (pb[3 * j + 2] + pf[3 * j + 2])/2;*/
}
}
}
return result;
}
/*
Mat replace_and_blend(Mat &frame, Mat&mask) {
result = Mat::zeros(frame.size(), frame.type());
int h = frame.rows;
int w = frame.cols;
int dims = frame.channels();
int m ;
double wt ;
int b , g, r;
int b1, g1, r1;
int b2 , g2, r2 ;
//指针操作速度最快,直接访问地址
for (int row = 0; row < h; row++) {
uchar* current = frame.ptr<uchar>(row);
uchar* bgrow = background.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 = wt*b1 + (1 - wt)*b2;
g = wt*g1 + (1 - wt)*g2;
r = wt*r1 + (1 - wt)*r2;
*targetrow++ = b;
*targetrow++ = g;
*targetrow++ = r;
}
}
}
return result;
}
*/