基于hsv顏色空間的實時背景替換:


#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;
}
*/



以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。