基于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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。