Opencv實(shí)現(xiàn)綠幕視頻背景替換功能
更新時(shí)間:2019年05月21日 11:53:39 作者:東城青年
這篇文章主要為大家詳細(xì)介紹了Opencv實(shí)現(xiàn)綠幕視頻背景替換功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
基于hsv顏色空間的實(shí)時(shí)背景替換:


#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會(huì)根據(jù)Size自動(dòng)算的
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);//結(jié)果
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;
}
*/



以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言 volatile與const同時(shí)使用應(yīng)注意的問題
“volatile”的含義是“請(qǐng)不要做沒譜的優(yōu)化,這個(gè)值可能變掉的”,而并非“你可以修改這個(gè)值”。因此,它們本來就不是矛盾的2013-09-09
深入詳解C編寫Windows服務(wù)程序的五個(gè)步驟
本篇文章介紹了,使用C編寫Windows服務(wù)程序的五個(gè)步驟的詳細(xì)概述。需要的朋友參考下2013-05-05
C語言中用于修改文件的存取時(shí)間的函數(shù)使用
這篇文章主要介紹了C語言中用于修改文件的存取時(shí)間的函數(shù)使用,分別為utime()函數(shù)和utimes()函數(shù)的使用,需要的朋友可以參考下2015-09-09
詳解基于C++實(shí)現(xiàn)約瑟夫環(huán)問題的三種解法
約瑟夫環(huán)問題是算法中相當(dāng)經(jīng)典的一個(gè)問題,其問題理解是相當(dāng)容易的,并且問題描述有非常多的版本,并且約瑟夫環(huán)問題還有很多變形,通過這篇約瑟夫問題的講解,一定可以帶你理解透徹2021-06-06
C++實(shí)現(xiàn)將數(shù)組中的值反轉(zhuǎn)
這里給大家分享的事一則C++實(shí)現(xiàn)將數(shù)組中的值反轉(zhuǎn)的代碼,取材自《C++程序設(shè)計(jì)》(梁勇著第三版367頁),有需要的小伙伴可以參考下2016-05-05
C語言數(shù)據(jù)類型枚舉enum全面詳解示例教程
生活中有很多地方會(huì)用到枚舉,比如一周有7天,可以一一枚舉;性別有男、女...等等都可以可以一一枚舉,今天來和筆者一起學(xué)習(xí)一下c語言枚舉吧2021-10-10

