今天去交社保,要白底的电子版照片,我目前手头就是一个蓝底的,又不想手动抠图,于是想做一个自动换背景的程序。

先上效果:

具体分三步,第一步是大体的背景转换,把蓝色变为白色:

void colortransfer(cv::Mat image) //蓝背景转白背景,有边缘残留
{int Diff;int num_row = image.rows;int num_col = image.cols;for (int r = 0; r < num_row; r++){cv::Vec3b *data = image.ptr<cv::Vec3b>(r);for (int c = 0; c < num_col; c++){Diff = data[c][0] - (data[c][1] + data[c][2]) / 2; //蓝色检测if (Diff > 60 && data[c][0]>150)//蓝色分量比GR分量的平均值高60且蓝色分量大于150
            {data[c][0] = 255; data[c][1] = 255;data[c][2] = 255;}}}
}

但是这步出来之后效果不太好,可以看出来有很明显的蓝色边缘,很多蓝底照片因为照的时候和背景过近,导致边缘颜色变化

接下来就是对这些深色的蓝边进行一个处理,这里采用了检测蓝边->中值滤波器的方法:

void Optimization(cv::Mat image)   //去边缘残留
{int num_row = image.rows;int num_col = image.cols;for (int i = 1; i < num_row-1; i++){cv::Vec3b *last_r = image.ptr<cv::Vec3b>(i-1);cv::Vec3b *data = image.ptr<cv::Vec3b>(i);cv::Vec3b *next_r = image.ptr<cv::Vec3b>(i+1);for (int j = 1; j < num_col-1; j++){    if (data[j][0]>90 && data[j][0] - data[j][1]>9 && data[j][0] - data[j][2]>9){int stat;cv::Vec3b Temp;cv::Vec3b array[9] = { last_r[j - 1], last_r[j], last_r[j + 1], data[j - 1], data[j], data[j + 1], next_r[j - 1], next_r[j], next_r[j + 1] };do{stat = 0;for (int m = 0; m < 8; m++){if (array[m][0] + array[m][1] + array[m][2]> array[m + 1][0] + array[m + 1][1] + array[m + 1][2]){Temp=array[m + 1];array[m + 1] = array[m];array[m] = Temp;stat = 1;}}} while (stat == 1);data[j][0] = array[7][0];  data[j][1] = array[7][1];data[j][2] = array[7][2];}}}
}

中间用了冒泡算法进行排序,结果如下:

边缘基本去除了,但是头发这边显得非常不真实,没有边缘的毛躁感。这里我们检测到头发边缘后,对边缘区域进行一个低通滤波和颜色的加白处理,让边缘有层次感:

void hairilization(cv::Mat image) //毛躁化
{int num_row = image.rows / 3;int num_col = image.cols;for (int i = 2; i < num_row - 2; i=i+5){cv::Vec3b *last_sec_r = image.ptr<cv::Vec3b>(i - 2);cv::Vec3b *last_r = image.ptr<cv::Vec3b>(i - 1);cv::Vec3b *data = image.ptr<cv::Vec3b>(i);cv::Vec3b *next_r = image.ptr<cv::Vec3b>(i + 1);cv::Vec3b *next_sec_r = image.ptr<cv::Vec3b>(i + 2);for (int j = 2; j < num_col; j = j + 5){int count = 0;// check how many 255point in this area(boundary)cv::Vec3b array[5][5] = { last_sec_r[j - 2], last_sec_r[j - 1], last_sec_r[j], last_sec_r[j + 1], last_sec_r[j + 2], \last_r[j - 2], last_r[j - 1], last_r[j], last_r[j + 1], last_r[j + 2],\data[j - 2], data[j - 1], data[j], data[j + 1], data[j + 2],\next_r[j - 2], next_r[j - 1], next_r[j], next_r[j + 1], next_r[j + 2], \next_sec_r[j - 2], next_sec_r[j - 1], next_sec_r[j], next_sec_r[j + 1], next_sec_r[j + 2]};for (int r = 0; r < 5; r++){for (int c = 0; c < 5; c++){if (array[r][c][1] >= 251)count++;}}if (count >= 7 &&count<=18) //说明是头发边缘,开始处理
            {last_r[j - 1] = 1 / 9 * (array[0][0] + array[0][1] + array[0][2] + array[1][0] + array[1][1] + array[1][2] + array[2][0] + array[2][1] + array[2][2]) + cv::Vec3b(100, 100, 100);last_r[j] = 1 / 9 * (array[0][1] + array[0][2] + array[0][3] + array[1][1] + array[1][2] + array[1][3] + array[2][1] + array[2][2] + array[2][3]) + cv::Vec3b(80, 80, 80);last_r[j + 1] = 1 / 9 * (array[0][2] + array[0][3] + array[0][4] + array[1][2] + array[1][3] + array[1][4] + array[2][2] + array[2][3] + array[2][4]) + cv::Vec3b(100, 100, 100);data[j - 1] = (1 / 9 * array[1][0] + 1 / 9 * array[1][1] + 1 / 9 * array[1][2] + 1 / 9 * array[2][0] + 1 / 9 * array[2][1] + 1 / 9 * array[2][2] + 1 / 9 * array[3][0] + 1 / 9 * array[3][1] + 1 / 9 * array[3][2]) + cv::Vec3b(80, 80, 80);data[j] = (1 / 9 * array[1][1] + 1 / 9 * array[1][2] + 1 / 9 * array[1][3] + 1 / 9 * array[2][1] + 1 / 9 * array[2][2] + 1 / 9 * array[2][3] + 1 / 9 * array[3][1] + 1 / 9 * array[3][2] + 1 / 9 * array[3][3]) + cv::Vec3b(80, 80, 80);data[j + 1] =  (1 / 9 * array[1][2] + 1 / 9 * array[1][3] + 1 / 9 * array[1][4] + 1 / 9 * array[2][2] + 1 / 9 * array[2][3] + 1 / 9 * array[2][4] + 1 / 9 * array[3][2] + 1 / 9 * array[3][3] + 1 / 9 * array[3][4]) + cv::Vec3b(80, 80, 80);data[j - 1] =  (1 / 9 * array[2][0] + 1 / 9 * array[2][1] + 1 / 9 * array[2][2] + 1 / 9 * array[3][0] + 1 / 9 * array[3][1] + 1 / 9 * array[3][2] + 1 / 9 * array[4][0] + 1 / 9 * array[4][1] + 1 / 9 * array[4][2]) + cv::Vec3b(100, 100, 100);data[j] =  (1 / 9 * array[2][1] + 1 / 9 * array[2][2] + 1 / 9 * array[2][3] + 1 / 9 * array[3][1] + 1 / 9 * array[3][2] + 1 / 9 * array[3][3] + 1 / 9 * array[4][1] + 1 / 9 * array[4][2] + 1 / 9 * array[4][3]) + cv::Vec3b(80, 80, 80);data[j + 1] =  (1 / 9 * array[2][2] + 1 / 9 * array[2][3] + 1 / 9 * array[2][4] + 1 / 9 * array[3][2] + 1 / 9 * array[3][3] + 1 / 9 * array[3][4] + 1 / 9 * array[4][2] + 1 / 9 * array[4][3] + 1 / 9 * array[4][4]) + cv::Vec3b(100, 100, 100);}}}
}

View Code

这部分代码比较长,的所以隐藏了。

结果如下:

相比于:

可以看到头发的边缘上有很大提升,因为均值滤波把边缘的头发变浅,形成了一个层次感,模拟了在白幕照相的效果。

转载于:https://www.cnblogs.com/wangxinyu0628/p/5922602.html

OpenCV——证件照自动抠图相关推荐

  1. PaddleHub创意项目-制作证件照(抠图换底美颜)

    PaddleHub创意项目-制作证件照(抠图换底美颜) 经过三个星期的百度架构师手把手带你零基础实践深度学习,对paddle有了一定了解,现在利用PaddleHub实践一个对图像进行抠图换底加美颜的小 ...

  2. Python实现自动抠图(上篇)

    Python实现自动抠图(上篇) 生活中,我们经常需要使用到一些图片资源,比如做ppt.项目需要等,这就涉及图片的处理.但抠图是一个痛苦的过程,本人是ps入门级玩家,每次使用磁链勾画想要的图像都很费劲 ...

  3. 怎么给图片自动抠图换背景?简单一招轻松操作

    相信平时小伙伴们都接触过抠图换背景吧!比如改变证件照的背景颜色,图片素材的处理,P掉路人照片等等.而且说到背景抠图,很多人应该会想到用PS来解决,但是对于我这样的PS小白来说,PS抠图改变背景的操作是 ...

  4. 在windows中python安装sit-packages路径位置 在Pycharm中导入opencv不能自动代码补全问题

    一.在windows中python安装sit-packages路径位置 C:\Users\shl\AppData\Local\Programs\Python\Python36\Lib\site-pac ...

  5. python自动抠头像图_Python实现AI自动抠图实例解析

    一.简介 抠图是用PS? 用魔棒和快速选择工具? 遇到复杂背景怎么办? 最近发现一个神奇的工具--Remove Image Background 它是基于Python.Ruby和深度学习技术开发,通过 ...

  6. ps抠头发插件_彻底告别抠图的烦恼!PS自动抠图超级插件Topaz ReMask大放送

    我们经常需要对各种图片进行抠图,虽然抠图方法很多,但是我们却要花费很长的时间,这无疑来说效率非常不高. 有没有一款PS插件可以快速对照片进行抠图?并且可以达到自己理想的效果? 当然是有的,今天米朵就送 ...

  7. python抠图_python 网站自动抠图

    python 网站自动抠图 翻东西, 突然找到了以前用python写的自动下载网站图片的一个脚本 很好用, 如果修改的话, 只要将路径改成自己的即可! picdown.py #! /usr/bin/p ...

  8. learn opencv-使用OpenCV的自动红眼删除

    参考:https://github.com/spmallick/learnopencv 使用OpenCV的自动红眼删除(C ++ / Python) 在本教程中,我们将学习如何完全自动地从照片中删除红 ...

  9. python人工自动抠图_Python - AI自动抠图

    一.简介 抠图是用PS? 用魔棒和快速选择工具? 遇到复杂背景怎么办? 最近发现一个神奇的工具--Remove Image Background 它是基于Python.Ruby和深度学习技术开发,通过 ...

  10. python人物抠图算法_Python实现AI自动抠图实例解析

    一.简介 抠图是用PS? 用魔棒和快速选择工具? 遇到复杂背景怎么办? 最近发现一个神奇的工具--Remove Image Background https://www.remove.bg/zh 它是 ...

最新文章

  1. linux利用vi挂载磁盘,如何在linux环境上挂载磁盘
  2. poj-1042 nyoj-30(Gone fishing)
  3. 自定义View 中很关键的问题View获取宽/高是0 的解决办法
  4. 自制Unity小游戏TankHero-2D(3)开始玩起来
  5. POJ 2785 有多少种4个数相加等于0的方案(二分查找 or hash)
  6. Deno 是面向代码的浏览器?
  7. jquery 获取同级元素_如何在jQuery中获取元素的同级
  8. 忘记密码后恢复思科设备密码的方案
  9. 计算机考研复试之数据库
  10. 不相交轮换的乘积怎么求_怎么样将一个轮换分解成不相交的轮换的乘积
  11. 大家来找茬:富连网今天中午抢购二手iPhone时网站无法访问的问题
  12. python默认安装目录在哪_怎么查看python的安装目录
  13. 调试Cello时快速清除已有容器
  14. Linux服务介绍一,关闭你不需要的服务
  15. Currency Translation in Bex Query Variable 1
  16. jQuery on(绑定事件)前别忘了off(移除事件)
  17. apache-jmeter-5.5使用教程
  18. 编写五子棋的完整python代码_PyQt写的五子棋
  19. lisp 中望cad 选项卡_CAD应用技巧:中望CAD中加载LISP程序
  20. 计算机控制系统在机电设备中的应用,接口技术在机电一体化控制系统中的应用...

热门文章

  1. 网页设计html颜色大全,50个使用柔和色彩的网页设计作品欣赏
  2. at android.widget.Toast$TN.handleShow(Toast.java:501)自定义布局异常
  3. mysql 查询开始时间和结束时间是一个月的数据sql
  4. 手把手教你搭建一台永久运行的个人服务器
  5. Zstack协议栈中CC2530协调器掉电重启后重新加入之前网络的方法
  6. 使用MapReduce实现专利文件的分析
  7. 大觉寺-阳台山穿越记
  8. 简述java重载和重写的相同点_方法的重载和重写的异同之处
  9. 谷歌浏览器如何清理缓存
  10. 使用bat脚本创建快捷方式