Opencv c++ change video background for image
Нужно заменить задний фон исходного видео с видеокамеры на статическое изображение или видеоряд. Пытался сделать это через функционал bitwise_ and/or/not. Но после выделения контура функцией inRange outputArray становится типа 0, в то время как исходное было типа 16. Как можно решить эту проблему? Пытался с помощью src.convertTo(), но толку было 0. Вот исходник:
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/video.hpp>
#include <opencv2\videoio.hpp>
#include <iostream>
#include <cctype>
using namespace std;
using namespace cv;
void viewImage(cv::String nOfWin, cv::Mat image) {
namedWindow(nOfWin, (640,480));
imshow(nOfWin, image);
}
int main() {
//находимся в приложении пока пользователь не захочет закончить работу
for (;;) {
char key;
cout << "1-Quit; 2 - Work\n";
cin >> key;
VideoCapture video;
switch (key) {
//выход из программы
case '1':
goto exit_mark;
//начало работы программы
case '2': {
//создали прототип окна для настройки цвета заднего фона
namedWindow("Options");
createTrackbar("Down hue", "Options", 0, 255);
createTrackbar("High hue", "Options", 0, 255);
createTrackbar("Down saturation", "Options", 0, 255);
createTrackbar("High saturation", "Options", 0, 255);
createTrackbar("Down value", "Options", 0, 255);
createTrackbar("High value", "Options", 0, 255);
//начнем работу с видеорядом и его обработку
int deviceID = 0, apiID = CAP_ANY;
video.open(deviceID, apiID);
if (!video.isOpened()) {
cerr << "ERROR! Unable to open camera\n";
return -1;
}
video.set(CAP_PROP_FRAME_WIDTH, 640);
video.set(CAP_PROP_FRAME_HEIGHT, 480);
Mat back;
back = imread("bg1.jpg", IMREAD_COLOR);
for (; ; ) {
//зададим переменные, в которых будут храниться кадры видео
Mat frame, hsv, mask;
//считаем кадр видео в фрейм, зададим ему размер
video.read(frame);
video.read(mask);
viewImage("VIDEO FRAME!", frame);
//изменим систему цвета на HSV, чтобы заработал inRange
cvtColor(frame, hsv, COLOR_BGR2HSV);
//не забываем про значения наших трекбаров!
int d_hue = getTrackbarPos("Down hue", "Options"),
h_hue = getTrackbarPos("High hue", "Options"),
d_sat = getTrackbarPos("Down saturation", "Options"),
h_sat = getTrackbarPos("High saturation", "Options"),
d_val = getTrackbarPos("Down value", "Options"),
h_val = getTrackbarPos("High value", "Options");
//теперь определим пороги для inRange
Scalar lowerb, upperb;
lowerb = Scalar(d_hue, d_sat, d_val);
upperb = Scalar(h_hue, h_sat, h_val);
inRange(hsv, lowerb, upperb, mask);
//threshold(hsv, mask, d_hue, h_hue, hsv.type());
//mask.convertTo(mask, frame.type());
viewImage("Mask", mask);
bitwise_not(mask, mask);
//viewImage("mask", mask);
//начали работу с задним и передним планами изображения
Mat fg_masked, bg_masked;
//благодаря маске, берем с изначального изображения только основной силуэт (человек/
камень и др.)
//mask.convertTo(mask, 8);
cout << endl << "Type: " << hsv.type() << "; Mask: " << mask.type() << endl;
bitwise_and(frame, mask, fg_masked);
viewImage("fg", fg_masked);
/*//инвертируем маску, чтобы она отображала задний фон
bitwise_not(mask, mask);
bitwise_and(back, mask, bg_masked);
viewImage("bg", bg_masked);
//объединяем передний и задний планы
Mat fin_img;
bitwise_or(fg_masked, bg_masked, fin_img);
viewImage("Res image", fin_img);
*/
if (waitKey(5) >= 0) break;
}
}
default:
break;
}
}
//выход из программы
exit_mark:
return 0;
}