赞
踩
关于视频的操作: https://wangsp.blog.csdn.net/article/details/118701315
实现流程:
头文件 machine_learning_all.h
:
#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
class Machine_learning{
public:
void replace_bg_demo(Mat& image);
void replace_bg_video_demo(Mat& image, const char* mp4_path);
};
主函数main.cpp
#include "machine_learning_all.h" int main(int argc, char** argv) { const char* input_path = "D:\\Desktop\\meinv3.png"; const char* mp4_path = "D:\\Desktop\\01.mp4"; Mat src = imread(input_path); if (src.empty()) { cout << "Read image failed!" << endl; return -1; } Machine_learning ml; ml.replace_bg_video_demo(src, mp4_path); ml.replace_bg_demo(src); imshow("src", src); waitKey(0); destroyAllWindows(); return 0; }
效果展示
void Machine_learning::replace_bg_demo(Mat& image) { int width = image.cols; int height = image.rows; int samplecount = width * height; int dims = image.channels(); Mat points = Mat::zeros(samplecount, dims, CV_32F); // image to matrix int index_t = 0; for (int row = 0; row < height; row++) { uchar* src_ptr = image.ptr<uchar>(row); for (int col = 0; col < width; col++) { index_t = row * width + col; points.at<float>(index_t, 0) = *src_ptr++; points.at<float>(index_t, 1) = *src_ptr++; points.at<float>(index_t, 2) = *src_ptr++; } } // 运行KMeans int numCluster = 4; Mat labels; Mat centers; TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1); kmeans(points, numCluster, labels, criteria, 3, KMEANS_PP_CENTERS, centers); // 去背景+遮罩生成 Mat mask_mat = Mat::zeros(image.size(), CV_8UC1); int index = image.rows * 5 + 12; //取此处像素为背景像素 int cindex = labels.at<int>(index, 0); for (int row = 0; row < height; row++) { uchar* mask_ptr = mask_mat.ptr<uchar>(row); for (int col = 0; col < width; col++) { index = row * width + col; int label = labels.at<int>(index, 0); if (label == cindex) { // 背景 *mask_ptr++ = 0; }else { *mask_ptr++ = 255; } } } // 腐蚀 + 高斯模糊 (处理边界区域,使图像混合更自然) Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); erode(mask_mat, mask_mat, kernel); GaussianBlur(mask_mat, mask_mat, Size(3, 3), 0, 0); imshow("mask_mat", mask_mat); RNG rng(1232); Vec3b color(217, 60, 160); Mat result = Mat::zeros(image.size(), image.type()); double weight = 0.0; for (int row = 0; row < height; row++) { uchar* mask_ptr = mask_mat.ptr<uchar>(row); uchar* src_ptr = image.ptr<uchar>(row); uchar* result_ptr = result.ptr<uchar>(row); for (int col = 0; col < width; col++) { if (*mask_ptr == 255) { // 前景 *result_ptr++ = *src_ptr++; *result_ptr++ = *src_ptr++; *result_ptr++ = *src_ptr++; } else if (*mask_ptr == 0) { // 背景 *result_ptr++ = color[0]; *result_ptr++ = color[1]; *result_ptr++ = color[2]; src_ptr += 3; } else { // 加权混合 weight = *mask_ptr / 255.0; *result_ptr++ = *src_ptr++ * weight + color[0] * (1.0 - weight); *result_ptr++ = *src_ptr++ * weight + color[1] * (1.0 - weight); *result_ptr++ = *src_ptr++ * weight + color[2] * (1.0 - weight); } mask_ptr++; } } imshow("result", result); }
实现流程与图像相似,只是部分区域略有不同
Mat replace_and_blend(Mat& frame, Mat& mask_img, Mat& bg_img) { Mat result = Mat::zeros(frame.size(), frame.type()); int h = frame.rows; int w = frame.cols; int dims = frame.channels(); double wt = 0; for (int row = 0; row < h; row++) { uchar* current = frame.ptr<uchar>(row); uchar* bg_ptr = bg_img.ptr<uchar>(row); uchar* mask_ptr = mask_img.ptr<uchar>(row); uchar* result_ptr = result.ptr<uchar>(row); for (int col = 0; col < w; col++) { if (*mask_ptr == 255) { // 背景 *result_ptr++ = *bg_ptr++; *result_ptr++ = *bg_ptr++; *result_ptr++ = *bg_ptr++; current += 3; } else if (*mask_ptr == 0) { // 前景 *result_ptr++ = *current++; *result_ptr++ = *current++; *result_ptr++ = *current++; bg_ptr += 3; } else { wt = *mask_ptr / 255.0; // 权重 *result_ptr++ = *bg_ptr++ * wt + *current++ * (1.0 - wt); *result_ptr++ = *bg_ptr++ * wt + *current++ * (1.0 - wt); *result_ptr++ = *bg_ptr++ * wt + *current++ * (1.0 - wt); } mask_ptr++; } } return result; } void Machine_learning::replace_bg_video_demo(Mat& image, const char* mp4_path) { Mat frame, hsv_img, mask_img; VideoCapture capture(mp4_path); if (!capture.isOpened()) { cout << "could not find the video file..." << endl;; return; } int frame_width = capture.get(CAP_PROP_FRAME_WIDTH); int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT); int height = image.rows; int width = image.cols; if (height < frame_height || width < frame_width) { cout << "背景图像太小了!" << endl; return; } Mat bg_img = image(Rect(0, 0, frame_width, frame_height)); while (capture.read(frame)) { cvtColor(frame, hsv_img, COLOR_BGR2HSV); inRange(hsv_img, Scalar(35, 43, 46), Scalar(155, 255, 255), mask_img); // 形态学操作 Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); morphologyEx(mask_img, mask_img, MORPH_CLOSE, kernel); erode(mask_img, mask_img, kernel); GaussianBlur(mask_img, mask_img, Size(3, 3), 0, 0); Mat result = replace_and_blend(frame, mask_img, bg_img); if (waitKey(30) == 27) { break; } imshow("result", result); imshow("raw_frame", frame); } capture.release(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。