【发布时间】:2013-05-28 04:25:40
【问题描述】:
我是 OpenCV 和 C++ 的初学者,但现在我必须找到解决这个问题的方法: 我有一个蓝色背景的人的图像,现在我必须从图像中减去背景,然后用另一个图像替换它。 现在我认为有两种方法可以解决这个问题,但我不知道哪个更好:
解决方案 1:
- 将图像转换为黑白
- 将其用作遮罩以减去背景。
解决方案 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;
【问题讨论】:
-
尝试分段。将 cv::grabCut 与非常接近边界的前景蒙版一起使用(例如,将图像的 4 个角像素设置为前景像素)。
-
亲爱的威廉。你能描述得更详细些吗?在这种情况下如何使用 grabCut?谢谢
标签: opencv background subtraction