Я новичок в OpenCV и C++, но теперь я должен найти решение этой проблемы: У меня есть изображение человека с синим фоном, теперь мне приходится вычитать фон из изображения, затем замените его другим изображением. Теперь я думаю, что есть 2 пути решения этой проблемы, но я не знаю, что лучше:Вычитаем синий фон с изображения OpenCV C++
Решение 1:
- Преобразовать изображение B & W
- Используйте его как маску для вычитания фона.
Решение 2:
- Использование coutour найти фон,
- , а затем вычесть его.
Я уже реализовал решение 1, но результат не такой, как я ожидаю. Знаете ли вы, что есть другое лучшее решение, или кто-то уже реализует его как исходный код? Поблагодарите вашу помощь.
я обновить свой исходный код здесь, пожалуйста, дайте мне некоторые комментарии
//Get the image with person
cv::Mat imgRBG = imread("test.jpg");
//Convert this image to grayscale
cv::Mat imgGray = imread("test.jpg",CV_LOAD_IMAGE_GRAYSCALE);
//Get the background from image
cv::Mat background = imread("paris.jpg");
cv::Mat imgB, imgW;
//Image with black background but inside have some area black
threshold(imgGray, imgB, 200, 255, CV_THRESH_BINARY_INV);
cv::Mat imgTemp;
cv::Mat maskB, maskW;
cv::Mat imgDisplayB, imgDisplayW;
cv::Mat imgDisplay1, imgDisplay2, imgResult;
//Copy image with black background, overide the original image
//Now imgTemp has black background wrap the human image, and inside the person, if there're some white area, they will be replace by black area
imgRBG.copyTo(imgTemp, imgB);
//Now replace the black background with white color
cv::floodFill(imgTemp, cv::Point(imgTemp.cols -10 ,10), cv::Scalar(255.0, 255.0, 255.0));
cv::floodFill(imgTemp, cv::Point(10,10), cv::Scalar(255.0, 255.0, 255.0));
cv::floodFill(imgTemp, cv::Point(10,imgTemp.rows -10), cv::Scalar(255.0, 255.0, 255.0));
cv::floodFill(imgTemp, cv::Point(imgTemp.cols -10,imgTemp.rows -10), cv::Scalar(255.0, 255.0, 255.0));
//Convert to grayscale
cvtColor(imgTemp,imgGray,CV_RGB2GRAY);
//Convert to B&W image, now background is black, other is white
threshold(imgGray, maskB, 200, 255, CV_THRESH_BINARY_INV);
//Convert to B&W image, now background is white, other is black
threshold(imgGray, maskW, 200, 255, CV_THRESH_BINARY);
//Replace background of image by the black mask
imgRBG.copyTo(imgDisplayB, maskB);
//Clone the background image
cv::Mat overlay = background.clone();
//Create ROI
cv::Mat overlayROI = overlay(cv::Rect(0,0,imgDisplayB.cols,imgDisplayB.rows));
//Replace the area which will be human image by white color
overlayROI.copyTo(imgResult, maskW);
//Add the person image
cv::addWeighted(imgResult,1,imgDisplayB,1,0.0,imgResult);
imshow("Image Result", imgResult);
waitKey();
return 0;
сегментации Try. Используйте cv :: grabCut с маской переднего плана, очень близкой к границам (например, установите 4 угловых пикселя изображения в качестве передних). – William
Дорогой Уильям. Можете ли вы подробнее описать? Как я могу использовать grabCut в этой ситуации? Спасибо – user2411800
Прочтите [это] (http://www.packtpub.com/article/opencv-segmenting-images) и попробуйте [this] (http://stackoverflow.com/questions/14111716/how-to-set-a -mask-изображение-в-grabcut-в-OpenCV). – William