OpenCV3.2图像分割 实例10:绿幕视频背景替换

发布时间 2023-08-18 09:05:23作者: 一杯清酒邀明月
  1 #include <opencv2/opencv.hpp>
  2 #include <iostream>
  3  
  4 using namespace cv;
  5 using namespace std;
  6  
  7 Mat replace_and_blend(Mat &frame, Mat &mask);
  8 Mat background_01;//背景1
  9 Mat background_02;//背景2
 10 int main(int argc, char** argv) {
 11     // start here...    
 12     background_01 = imread("bg_01.jpg");
 13     background_02 = imread("bg_02.jpg");
 14     VideoCapture capture;//视频抓取
 15     capture.open("01.mp4");
 16     if (!capture.isOpened()) {
 17         printf("could not find the video file...\n");
 18         return -1;
 19     }
 20     const char* title = "input video";
 21     const char* resultWin = "result video";
 22     namedWindow(title, CV_WINDOW_AUTOSIZE);
 23     namedWindow(resultWin, CV_WINDOW_AUTOSIZE);
 24     Mat frame, hsv, mask;
 25     int count = 0;
 26     //测试视频读取
 27     //while (capture.read(frame)) {//判断读取视频单帧是否成功,读取单帧图像复制给frame对象
 28     //    imshow(title, frame);
 29     //    char c =waitKey(50);
 30     //    if (c == 27) {
 31     //        break;
 32     //    }
 33  
 34     //}
 35     ///
 36     mask测试
 37     //while (capture.read(frame)) {
 38     //    cvtColor(frame, hsv, COLOR_BGR2HSV);//转换为HSV
 39     //    //原背景选择HSV--绿色
 40     //    inRange(hsv, Scalar(35, 43, 46), Scalar(60, 255, 255), mask);//mask数据调整60
 41     //    imshow("mask",mask);//显示mask
 42     //    count++;
 43     //    imshow(title, frame);//显示输入video
 44     //    char c = waitKey(1);
 45     //    if (c == 27) {
 46     //        break;
 47     //    }
 48     //}
 49     /
 50     while (capture.read(frame)) {//判断读取视频单帧是否成功,读取单帧图像复制给frame对象
 51         cvtColor(frame, hsv, COLOR_BGR2HSV);//转换为HSV
 52         inRange(hsv, Scalar(35, 43, 46), Scalar(60, 255, 255), mask);
 53         // 形态学操作,3*3进行腐蚀,然后高斯进行3*3的模糊,边界不变
 54         Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
 55         morphologyEx(mask, mask, MORPH_CLOSE, k);
 56         erode(mask, mask, k);
 57         GaussianBlur(mask, mask, Size(3, 3), 0, 0);
 58         //背景替换和混合
 59         Mat result = replace_and_blend(frame, mask);
 60         char c = waitKey(1);
 61         if (c == 27) {
 62             break;
 63         }
 64         imshow(resultWin, result);//显示处理结果video
 65         imshow(title, frame);//显示输入video
 66     }
 67  
 68     waitKey(0);
 69     return 0;
 70 }
 71 //背景替换和混合
 72 Mat replace_and_blend(Mat &frame, Mat &mask) {
 73     Mat result = Mat::zeros(frame.size(), frame.type());
 74     int h = frame.rows;
 75     int w = frame.cols;
 76     int dims = frame.channels();
 77  
 78     // replace and blend
 79     int m = 0;
 80     double wt = 0;
 81  
 82     int r = 0, g = 0, b = 0;
 83     int r1 = 0, g1 = 0, b1 = 0;
 84     int r2 = 0, g2 = 0, b2 = 0;
 85  
 86     for (int row = 0; row < h; row++) {
 87         uchar* current = frame.ptr<uchar>(row);//当前
 88         uchar* bgrow = background_01.ptr<uchar>(row);//背景2
 89         uchar* maskrow = mask.ptr<uchar>(row);//面罩 行
 90         uchar* targetrow = result.ptr<uchar>(row);//目标 行
 91         for (int col = 0; col < w; col++) {
 92             m = *maskrow++;
 93             if (m == 255) { // 赋值为背景
 94                 *targetrow++ = *bgrow++;
 95                 *targetrow++ = *bgrow++;
 96                 *targetrow++ = *bgrow++;
 97                 current += 3;
 98  
 99             } else if(m==0) {// 赋值为前景
100                 *targetrow++ = *current++;
101                 *targetrow++ = *current++;
102                 *targetrow++ = *current++;
103                 bgrow += 3;
104             } else {
105                 b1 = *bgrow++;
106                 g1 = *bgrow++;
107                 r1 = *bgrow++;
108  
109                 b2 = *current++;
110                 g2 = *current++;
111                 r2 = *current++;
112  
113                 // 权重
114                 wt = m / 255.0;
115                 
116                 // 混合
117                 b = b1*wt + b2*(1.0 - wt);
118                 g = g1*wt + g2*(1.0 - wt);
119                 r = r1*wt + r2*(1.0 - wt);
120  
121                 *targetrow++ = b;
122                 *targetrow++ = g;
123                 *targetrow++ = r;
124             }
125         }
126     }
127  
128     return result;
129 }