opencv3更換圖片背景

#include <opencv2/opencv.hpp>
#include <iostream>ios

using namespace std;
using namespace cv;spa

void ChangeImgBG();
Mat HandleImgData(Mat &img);
/*
圖片背景替換
知識點:分水嶺分割、高斯模糊
處理步驟:數據組裝-KMeans分割-背景消除-生成遮罩-模糊-輸出
*/
void ChangeImgBG()
{
  char* win1 = "window1";
  char* win2 = "window2";
  char* win3 = "window3";
  char* win4 = "window4";
  char* win5 = "window5";
  char* win6 = "window6";
  namedWindow(win1,CV_WINDOW_AUTOSIZE);//建立窗口 win1
  namedWindow(win2,CV_WINDOW_AUTOSIZE);//建立窗口 win2
  namedWindow(win3,CV_WINDOW_AUTOSIZE);//建立窗口 win3
  namedWindow(win4, CV_WINDOW_AUTOSIZE);//建立窗口 win4
  namedWindow(win5, CV_WINDOW_AUTOSIZE);//建立窗口 win5
  namedWindow(win6, CV_WINDOW_AUTOSIZE);//建立窗口 win6orm

  Mat img1, img2;
  //加載圖片
  img1 = imread("D:\\參考手冊\\opencv素材\\xl.jpg");
  if (img1.empty())
  {
    cout << "image not found..." << endl;
    exit(0);//若是圖片不存在,退出程序
  }
  img2 = img1.clone();
  //顯示原始圖片
  imshow(win1,img1);
  //組裝數據
  Mat points = HandleImgData(img1);blog

  //Kmeans處理
  int numCluster = 4;
  Mat labels;
  Mat centers;
  TermCriteria termCriteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT,10,0.1);圖片

  kmeans(points, numCluster,labels, termCriteria,3,KMEANS_PP_CENTERS,centers);
  //遮罩
  Mat mask = Mat::zeros(img1.size(),CV_8UC1);
  int index = img1.rows*2 + 2;
  int cindex = labels.at<int>(index,0);//背景設置爲0
  int height = img1.rows;
  int width = img1.cols;ci

  for (int row = 0;row<height;row++)
  {
    for (int col =0;col<width;col++)
    {
      index = row*width + col;
      int label = labels.at<int>(index,0);
      if (label ==cindex)
      {
        img2.at<Vec3b>(row, col)[0] = 0;
        img2.at<Vec3b>(row, col)[1] = 0;
        img2.at<Vec3b>(row, col)[2] = 0;
        mask.at<uchar>(row, col) = 0;
      }
      else
      {
        mask.at<uchar>(row, col) = 255;
      }
    }
  }

  //腐蝕
  Mat k = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));
  erode(mask,mask,k);
  imshow(win4,mask);

  //高斯模糊
  GaussianBlur(mask,mask,Size(3,3),0,0);
  imshow(win5,mask);get

  //通道混合
  RNG rng(12345);
  Vec3b color;
  color[0] = rng.uniform(0,255);
  color[1] = rng.uniform(0, 255);
  color[2] = rng.uniform(0, 255);
  Mat result(img1.size(),img1.type());it

  double d1 = 0.0;
  int r = 0, g = 0, b = 0;
  int r1 = 0, g1 = 0, b1 = 0;
  int r2 = 0, g2 = 0, b2 = 0;io


  for (int row = 0; row < height;row++)
  {
    for (int col=0;col<width;col++)
    {
      int m = mask.at<uchar>(row,col);
      if (m==255)
      {
        result.at<Vec3b>(row, col) = img1.at<Vec3b>(row,col);//前景
      }
      else if (m == 0)
      {
        result.at<Vec3b>(row, col) = color;//背景
      }
      else
      {
        d1 = m / 255.0;
        b1 = img1.at<Vec3b>(row, col)[0];
        g1 = img1.at<Vec3b>(row, col)[1];
        r1 = img1.at<Vec3b>(row, col)[2];opencv

        b2 = color[0];
        g2 = color[1];
        r2 = color[2];

        b = b1*d1 + b2*(1.0-d1);
        g = g1*d1 + g2*(1.0-d1);
        r = r1*d1 + r2*(1.0-d1);

        result.at<Vec3b>(row,col)[0] = b;
        result.at<Vec3b>(row, col)[1] = g;
        result.at<Vec3b>(row, col)[2] = r;
      }
    }
  }

  //輸出
  imshow(win2,mask);
  imshow(win3,img2);
  imshow(win6,result);
  //保存處理後的圖片
  imwrite("result-2.jpg",result);
}

//組裝樣本數據
Mat HandleImgData(Mat &img)
{
  int width = img.cols;
  int height = img.rows;
  int count1 = width*height;
  int channels1 = img.channels();

  Mat points(count1, channels1,CV_32F,Scalar(10));
  int index = 0;
  for (int row = 0; row < height;row++)
  {
    for (int col = 0; col < width;col++)
    {
      index = row*width + col;
      Vec3b bgr = img.at<Vec3b>(row,col);
      points.at<float>(index, 0) = static_cast<int>(bgr[0]);
      points.at<float>(index, 1) = static_cast<int>(bgr[1]);
      points.at<float>(index, 2) = static_cast<int>(bgr[2]);
    }
  }
  return points;
}

int main()
{
  ChangeImgBG();

  waitKey(0);
  return 0;
}

 

運行效果:

 

相關文章
相關標籤/搜索