实现单一背景抠图
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
//find the biggest contour
std::vector<cv::Point> FindBigestContour(cv::Mat src) {
int imax = 0;
int imaxcontour = -1;
std::vector<std::vector<cv::Point> >contours;
cv::findContours(src, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
if (contours.size() == 0) {
std::cout << "找不到轮廓!" << std::endl;
exit(0);
}
for (int i = 0; i < contours.size(); i++) {
int itmp = cv::contourArea(contours[i]);
if (imaxcontour < itmp) {
imax = i;
imaxcontour = itmp;
}
}
return contours[imax];
}
//remove Light difference by using top hat
cv::Mat moveLightDiff(cv::Mat src, int radius) {
cv::Mat dst;
cv::Mat srcclone = src.clone();
cv::Mat mask = cv::Mat::zeros(radius * 2, radius * 2, CV_8U);
cv::circle(mask, cv::Point(radius, radius), radius, cv::Scalar(255), -1);
//top hat
cv::erode(srcclone, srcclone, mask);
cv::dilate(srcclone, srcclone, mask);
dst = src - srcclone;
return dst;
}
int main(void)
{
cv::Mat src = cv::imread("test.png");
cv::Mat src_hsv;
cv::Mat bin;
cv::Mat src_h;
cv::cvtColor(src, src_hsv, cv::COLOR_BGR2HSV);
std::vector<cv::Mat> rgb_planes;
cv::split(src_hsv, rgb_planes);
src_h = rgb_planes[0]; // h channel is useful
src_h = moveLightDiff(src_h, 40);
cv::threshold(src_h, bin, 100, 255, cv::THRESH_OTSU);
//find and draw the biggest contour
std::vector<cv::Point> bigestcontrour = FindBigestContour(bin);
std::vector<std::vector<cv::Point> > controus;
controus.push_back(bigestcontrour);
cv::drawContours(src, controus, 0, cv::Scalar(0, 0, 255), 3);
cv::imwrite("result.png", src);
cv::imshow("显示轮廓", src);
cv::waitKey();
return 0;
}