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

using namespace std;
using namespace cv;

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);//创建窗口 win6

  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);

  //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;

  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);

  //通道混合
  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());

  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;

  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];

        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;
}

运行效果:

opencv3更换图片背景的更多相关文章

  1. C# 给PDF添加图片背景

    C# 给PDF添加图片背景 今天要实现的是给PDF文件添加图片背景这个功能.PDF是近年来最流行的文件之一,无论是办公还是日常生活中都经常会用到,很多时候,PDF文件的背景色都是白色,看多了难免觉得累 ...

  2. Angular4 自制华容道拼图(可以升级难度、关卡、更换图片)

    前端工程师新手一枚,之前一直做些小设计,以及静态页面的编写工作.刚刚接触 Angular 没有多久,四个月前对于 js 也只是会写 alert 之流,现在进步算是很大,下面是自制的华容道拼图(可以升级 ...

  3. win10更换登陆背景和关闭锁屏

    更换登陆背景图 用国外一个hacker写的工具,可在github上下载,或者下载我上传到百度网盘的备份.win10默认的登陆背景太难看了. 去掉锁屏图片 登陆界面其实本身就是一种锁屏,为什么还要单独搞 ...

  4. Atitit 动态按钮图片背景颜色与文字组合解决方案

    Atitit 动态按钮图片背景颜色与文字组合解决方案 转换背景颜色,setFont("cywe_img", fontScale, 50, 5) 设置文字大小与坐标 文字分拆,使用字 ...

  5. jquery 图片背景透明度(支持IE5/IE6/IE7)

    设置背景图片,以突出透明度的效果及jquery png背景透明插件实例教程 <head> <title>toggle()</title> <style typ ...

  6. 用shader使图片背景透明

    转自:http://blog.csdn.net/dawn_moon/article/details/8631783 好吧,终于抽时间写这篇文章了. 手头上有很多人物行走图,技能特效图等,但这些图都有个 ...

  7. iOS 图片背景模糊效果

    iOS 图片背景模糊效果 1.使用CoreImage中的模糊滤镜 原始效果图如下: CoreImage的实现: - (void)viewDidLoad { [super viewDidLoad]; / ...

  8. 【转】cocos2d-x游戏开发(十四)用shader使图片背景透明

    转自:http://blog.csdn.net/dawn_moon/article/details/8631783 好吧,终于抽时间写这篇文章了. 手头上有很多人物行走图,技能特效图等,但这些图都有个 ...

  9. 关于文字颜色/图片背景---selector状态列表

    文字颜色 android:textColor="@style/style_name" ----------------------------------widget 图片背景 a ...

随机推荐

  1. 【WPF】DataGrid的Row样式设置

    引言      在与DataGrid相关的项目中,会有一个比较常见的需求.那就是在根据数据设置行的样式,例如行的背景色或者字体色.我们用到的方法有几个,下面一个个说来. 准备工作     介绍方法之前 ...

  2. selenium-webdirver api-定位方式

    1,8种单数定位方式 # 通过ID定位目标元素 driver.find_element_by_id('i1') # 通过className定位目标元素 driver.find_element_by_c ...

  3. Spring_总结_04_高级配置(二)_条件注解@Conditional

    一.前言 本文承接上一节:Spring_总结_04_高级配置(一)之Profile 在上一节,我们了解到 Profile 为不同环境下使用不同的配置提供了支持,那么Profile到底是如何实现的呢?其 ...

  4. C#中的索引器的简单理解和用法

    索引器是一种特殊的类成员,它能够让对象以类似数组的方式来存取,使程序看起来更为直观,更容易编写. 1.索引器的定义 C#中的类成员可以是任意类型,包括数组和集合.当一个类包含了数组和集合成员时,索引器 ...

  5. github提交代码时遇到”Everything up-to-date“问题的解决方式

    需要创建一个新分支,将最新代码加入新分支, 再将新分支合并到主分支,然后提交主分支代码到github网站. ---------------------------------------------- ...

  6. 幸运数字(数位dp)

    个人心得:数位dp处理起来是真的麻烦,本来动态规划就够头疼的了,菜的一批. 来看这个题目吧,题目在下面. 把题目变成可以求得就是求前n个数中1-n*9的情况的总和,所以用dp[i][j],表示前i个数 ...

  7. Kerberos的hive链接问题

    javax.security.auth.login.LoginException: Checksum failed 之前碰到过类似的问题,都是因为服务器端的keytab问题:多半是因为重新生成了key ...

  8. SWT与Linux安装包

    关于SWT SWT首先要在Eclipse中添加SWT的安装包:Windowsbuilder Pro.下载路径:http://www.eclipse.org/windowbuilder/download ...

  9. BZOJ4009:[HNOI2015]接水果(整体二分版)

    浅谈离线分治算法:https://www.cnblogs.com/AKMer/p/10415556.html 题目传送门:https://lydsy.com/JudgeOnline/problem.p ...

  10. tyvj 2054 [Nescafé29]四叶草魔杖——最小生成树+状压dp

    题目:http://www.joyoi.cn/problem/tyvj-2054 枚举点集,如果其和为0,则作为一个独立的块求一下最小生成树.因为它可以不和别的块连边. 然后状压dp即可. 别忘了判断 ...