OpenCV C++案例实战六《绿幕视频背景替换》
OpenCV C++案例實(shí)戰(zhàn)六《綠幕視頻背景替換》
- 前言
- 一、圖像預(yù)處理
- 二、HSV色彩空間轉(zhuǎn)換
- 1. cvtColor色彩空間轉(zhuǎn)換
- 2. inRange摳圖
- 三、背景替換
- 四、源碼
- 總結(jié)
前言
本文將使用OpenCV C++ 進(jìn)行綠幕視頻背景替換。
一、圖像預(yù)處理
背景
綠幕視頻
首先,我們需要使用resize API將背景圖尺寸修改與視頻尺寸大小。這樣才能進(jìn)行后續(xù)的像素賦值操作。
二、HSV色彩空間轉(zhuǎn)換
1. cvtColor色彩空間轉(zhuǎn)換
cvtColor(frame, HSV, COLOR_BGR2HSV); //將原圖轉(zhuǎn)換成HSV色彩空間2. inRange摳圖
經(jīng)百度查表,我們可以獲取綠色HSV顏色分量范圍
//綠色HSV顏色分量范圍int hmin = 35, smin = 43, vmin = 46; int hmax = 77, smax = 255, vmax = 255;由于我們已經(jīng)將原圖轉(zhuǎn)換為HSV色彩空間,故可以使用inRange API將前景從綠幕中摳出來。inRange將兩閾值內(nèi)的像素置為255(即綠色被置為白色),閾值外的像素置為0(其他顏色被置為黑色)。故由此我們可以將前景摳出來。
//經(jīng)過inRange API處理,輸出一張二值圖像,即將前景從綠幕中扣出來啦inRange(HSV, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), mask);
mask圖像,即從綠幕中摳出來的前景圖。
三、背景替換
我們通過修改圖像像素值達(dá)到替換背景目的。通過遍歷視頻圖像像素值,當(dāng)mask像素值為0時,表示此時圖像像素為前景,將綠幕視頻當(dāng)前像素點(diǎn)賦給目標(biāo)圖像dst;當(dāng)mask像素值為255時,表示此時圖像像素為背景,將背景圖當(dāng)前像素點(diǎn)賦給目標(biāo)圖像dst。
Mat Replace_Background(Mat frame, Mat mask, Mat bg) {Mat dst = Mat::zeros(frame.size(), frame.type());for (int i = 0; i < frame.rows; i++){for (int j = 0; j < frame.cols; j++){int p = mask.at<uchar>(i, j); //傳入的mask是張二值圖,p為當(dāng)前mask像素值if (p == 0){ //代表mask此時為前景,將綠幕視頻中的前景像素賦給dstdst.at<Vec3b>(i, j) = frame.at<Vec3b>(i, j);}else if (p == 255){//代表mask此時為背景,將背景圖像素賦給dstdst.at<Vec3b>(i, j) = bg.at<Vec3b>(i,j);}}}return dst; }
最終效果如圖所示。
四、源碼
#include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv;Mat Replace_Background(Mat frame, Mat mask, Mat bg) {Mat dst = Mat::zeros(frame.size(), frame.type());for (int i = 0; i < frame.rows; i++){for (int j = 0; j < frame.cols; j++){int p = mask.at<uchar>(i, j); //傳入的mask是張二值圖,p為當(dāng)前mask像素值if (p == 0){ //代表mask此時為前景,將綠幕視頻中的前景像素賦給dstdst.at<Vec3b>(i, j) = frame.at<Vec3b>(i, j);}else if (p == 255){//代表mask此時為背景,將背景圖像素賦給dstdst.at<Vec3b>(i, j) = bg.at<Vec3b>(i,j);}}}return dst; }int main() {Mat bg = imread("background.jpg"); //背景圖VideoCapture capture; //讀取待處理的綠幕視頻capture.open("5.flv");if (!capture.isOpened()){cout << "Can not open video!" << endl;system("pause");return -1;}int width = capture.get(CAP_PROP_FRAME_WIDTH);int height = capture.get(CAP_PROP_FRAME_HEIGHT);resize(bg, bg, Size(width, height), 1, 1, INTER_CUBIC); //將背景圖resize成視頻尺寸大小Mat frame, HSV, mask, dst;//綠色HSV顏色分量范圍int hmin = 35, smin = 43, vmin = 46; int hmax = 77, smax = 255, vmax = 255;while (capture.read(frame)){cvtColor(frame, HSV, COLOR_BGR2HSV); //將原圖轉(zhuǎn)換成HSV色彩空間//經(jīng)過inRange API處理,輸出一張二值圖像,即將前景從綠幕中扣出來啦inRange(HSV, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), mask);dst = Replace_Background(frame, mask, bg);imshow("demo", frame);//imwrite("frame.jpg", frame);imshow("mask", mask);//imwrite("mask.jpg", mask);imshow("dst", dst);//imwrite("dst.jpg", dst);char key = waitKey(10);if (key == 27){break;}}destroyAllWindows();capture.release();system("pause");return 0; }總結(jié)
本文使用OpenCV C++進(jìn)行綠幕視頻背景替換,關(guān)鍵步驟有以下幾點(diǎn)。
1、將原圖轉(zhuǎn)換成HSV色彩空間。
2、使用inRange API將前景從綠幕中摳出來,得到一張二值圖。
3、通過像素賦值操作達(dá)到背景替換效果。
總結(jié)
以上是生活随笔為你收集整理的OpenCV C++案例实战六《绿幕视频背景替换》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序史简史:从巴贝奇到爱达在到图灵
- 下一篇: C/C++内存泄漏和野指针的区别