网上有一些 基于 opencv-python 的绿幕抠图算法,大多比较简单,只写明了最简单的原理,比如就是选择指定范围的颜色,然后在这个范围内的就抠掉。

但是简单的这样有一些问题,就是比如:
1)有些区域会抠出洞
2)边缘扣不干净,而且会存在锯齿状结果。

解决方案:
1)使用图像闭运算
2)需要求出一个离散数值作为抠图通道权重,而非 0 / 1。 可以用颜色的距离作为这个权重,这样权重在边缘应该会呈现过渡分布。

但是解决方案1),会带来一个问题,就是如果绿幕正好是个小洞(比如OK的手指),这样会带来问题。

最终变做实验边写代码,就有了下面我整理的代码,其实也是作为参考,可能对于不同的任务还得继续调
代码中主要看 get_mask_v3
思路是找到绿幕分割边界地方(mask_b),这部分应该选择过度更平滑的get_mask,容易去掉绿色,也不容易出现锯齿。具体实现是使用三级mask检测,具体可以看代码。

from _chj.comm.pic import *
from _chj.comm.video import *
os.chdir( os.path.split( os.path.realpath( sys.argv[0] ) )[0] )
# rbg: rgb(0, 216, 0)def main():f1_base()def f1_base():cls_w_rgb = Cls_video()cls_w_a = Cls_video()cls_w_rgb.task_comm( 1, ["tmp/res_rgb", 30, None] )cls_w_a.task_comm( 1, ["tmp/res_a", 30, None] )cls_read = Cls_video_read().init_files(["a.mp4"]) while True:st, imgs = cls_read.read_imgs()if st: breakimg = imgs[0]mask = get_mask_v3(img)#cv.imwrite("tmp/m.jpg", mask)img = get_mask_img(img, mask, 0)exit()cls_w_rgb.task_comm(2, img)cls_w_a.task_comm(2, mask)cls_w_rgb.ffmpeg_aug="-shortest -b:v 2000k"cls_w_a.ffmpeg_aug="-shortest -b:v 200k"cls_w_rgb.task_comm(3) cls_w_a.task_comm(3) print(122)def img_open(img, size=5, it=3):kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (size, size))  # 矩形结构open = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=it)return opendef img_close(img, size=5, it=3):kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (size, size))  # 矩形结构close = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=it)return closedef img_dilate(img, size=5, it=3):k = np.ones((size, size), dtype=np.uint8)return cv2.dilate(img, k, it)def img_erode(img, size=5, it=3):k = np.ones((size, size), dtype=np.uint8)return cv2.erode(img, k, it)# 非绿幕为1
def get_mask(img, mmin, mmax, minGreen):#, minGreen = np.array([0, 255, 0]), maxGreen = np.array([0, 255, 0])#hsv = cv2.cvtColor(opencv, cv2.COLOR_RGB2HSV)#mask = cv2.inRange(img, minGreen, maxGreen)dis = np.sqrt( np.power(img - minGreen, 2).mean(-1) )#dis = np.power(img - minGreen, 2).sum(-1) #.mean(-1)#dis = np.abs(img - minGreen).sum(-1) #.mean(-1)#mmin, mmax = 5, 400 # 后面这个参数越大,绿幕越小,但是实际上内部已经被平滑了dis[ dis<mmin ] = mmindis-=mmindis = dis / mmaxdis[ dis>1 ] = 1ids=dis*255#print(dis[50:60, 50:60])mask = (dis*255).astype(np.uint8)#showimg(mask)#mask = img_open( mask, 5, 2 )##mask = img_close( mask, 3, 3 )#showimg(mask)return maskdef get_mask_img(img, mask, isshow=0):mr = mask / 255.0img = mr[...,np.newaxis] * img + (1-mr)[...,np.newaxis]#img[ mask.astype(np.bool_) ] = 0img = img.astype(np.uint8)if isshow:showimg(img)return img# 调试 v1 时想到的
def get_mask_v2_1(img):color = np.array([0, 255, 0] )mask = get_mask( img, 5, 400, color ) # 需要调的mask = img_open( mask, 5, 2 )mask4 = get_mask( img, 5, 20, color ) # 真正要的参数mask4 = img_open( mask4, 3, 2 ) # 去掉一些噪声mask1 = img_erode(mask4, 5, 5)mask2 = img_dilate(mask4, 5, 5)mask3 = mask1 != mask2 # 找到边界的地方,这些地方用更加缓和的maskfor e in [mask4, mask, mask1, mask2, mask3.astype(np.uint8)*255]:get_mask_img(img, e, 1)#mask5 = img_close( mask, 5, 2 )mask4[mask3] = mask[mask3]#mask4[mask1==255] = mask5[ mask1==255 ]#mask4 = img_close( mask4, 3, 2 ) # 防止中间有洞get_mask_img(img, mask4, 1)#exit()return mask4# 1)要考虑过渡
# 2)要想使得能检测出更多的绿色范围,那么 get_mask 的第三个参数非常重要
# 3)考虑到第三个参数太大虽然检测的绿色多,但是容易引起错误,
#       因此需要确定一个边界,对于边界上的用第三个值大些的, 而边界通过 膨胀与腐蚀确定,但是应该时通过第三个值小的确定,
#  但是值太小,有些绿色检测不出来,所里这里是个矛盾点。
# 可能更合理的是采用三个 mask,即第三个值分级def get_mask_v2(img):color = np.array([0, 255, 0] )mask = get_mask( img, 3, 150, color ) # 需要调的mask = img_open( mask, 5, 2 )mask4 = get_mask( img, 3, 30, color ) # 真正要的参数mask4[mask4!=255] = 0mask4 = img_open( mask4, 3, 2 ) # 去掉一些噪声mask1 = img_erode(mask4, 7, 5)mask2 = img_dilate(mask4, 7, 5)mask3 = mask1 != mask2 # 找到边界的地方,这些地方用更加缓和的maskfor e in [mask4, mask, mask1, mask2, mask3.astype(np.uint8)*255]:get_mask_img(img, e, 1)mask5 = img_close( mask, 5, 2 ) # 这个可选mask4[mask3] = mask[mask3]mask4[mask1==255] = mask5[ mask1==255 ]#mask4 = img_close( mask4, 3, 2 ) # 防止中间有洞get_mask_img(img, mask4, 1)#exit()return mask4def get_mask_v3(img):color = np.array([0, 255, 0] )mask1 = get_mask( img, 3, 150, color ) # 用于检测更多的边缘绿色mask2 = get_mask( img, 3, 50, color ) # 用于确定边界mask3 = get_mask( img, 3, 20, color ) # 把纯绿色的去掉mask1 = img_open( mask1, 5, 2 )mask2 = img_open( mask2, 5, 2 )mask3 = img_open( mask3, 5, 2 )#mask2[mask2!=255] = 0 # 可选maskb1 = img_erode(mask2, 7, 5)maskb2 = img_dilate(mask2, 7, 5)maskb = maskb1 != maskb2#for e in [mask4, mask, mask1, mask2, mask3.astype(np.uint8)*255]:#    get_mask_img(img, e, 1)mask5 = img_close( mask1, 5, 2 ) # 这个可选mask3[maskb] = mask1[maskb]mask3[maskb1==255] = mask5[ maskb1==255 ]#mask4 = img_close( mask4, 3, 2 ) # 防止中间有洞get_mask_img(img, mask3, 1)#exit()return mask3if __name__=="__main__": main()

[小脚本] 基于opencv 的绿幕抠图相关推荐

  1. 基于OpenCV的绿幕抠像与图像融合

    一.背景知识         Keying,即抠像,从一幅图像中提取所要的前景,让它与背景分离起来.Key通常只包含一个通道,是一幅黑白图像,通常黑色的区域(0)代表完全透明,而白色区域(1)代表完全 ...

  2. 基于opencv的绿幕背景视频抠图算法流程

  3. OpenCV去除绿幕 抠图

    绿布原图 抠图后的图片 源码 #include <opencv2/opencv.hpp> #include <iostream> #include <vector> ...

  4. 基于MODnet无绿幕抠图

    0.前言 MODNet由香港城市大学和商汤科技于2020年11月首次提出,用于实时抠图任务 MODNet特性: 轻量级(light-weight ) 实时性高(real-time) 预测时不需要额外的 ...

  5. 基于opencv的绿背景抠图

    首先感谢 @chenxun2009 的指引,使得我这么快地得到进展,现在还差最后的参数调试问题. http://blog.csdn.net/chenxun_2010/article/details/3 ...

  6. 编程去除背景绿幕抠图,基于.NET+OpenCVSharp

    摘要:本文介绍了一种使用OpenCVSharp对摄像头中的绿幕视频进行实时"抠人像.替换背景"的方式,对于项目中的算法进行了分析.本文中给出了简化OpenCVSharp中Mat.M ...

  7. opencv 绿幕抠图 python版 c++版

    python版绿幕抠图 import cv2image = cv2.imread("images/green_screen.jpg") cv2.imshow("input ...

  8. 通过OpenCV对视频进行绿幕抠图

    通过OpenCV对视频进行绿幕抠图 效果 代码 1.打开视频素材 2.保存视频路径及格式设置 3.读取一帧视频 4.寻找绿幕背景 5.融合 6.代码执行效果 效果 今天跟大家分享的是最近比较受大家喜欢 ...

  9. 直播绿幕抠图的例子(绿幕抠图直播实例参考)

    阿酷TONY  / 2022-11-21 / 长沙 什么是绿幕抠图: 设定绿幕或绿布,做直播软件抠图,这时绿幕绿布就可以被实时的抠掉,绿色就变成透明了,只剩下绿幕外的人物,此时添加上直播的背景画质,就 ...

最新文章

  1. AAAI 2020 | 通过解纠缠模型探测语义和语法的大脑表征机制
  2. Java实现冒泡排序及其优化
  3. THINKPAD T420(4180J4C)还是THINKPAD T420(4180PLC)好?
  4. petshop4.0 详解之三(PetShop数据访问层之消息处理) [转]
  5. python编译:setup.py添加.h头文件或者库的搜索路径
  6. input标签中使输入文本向右偏移像素解决方案(亲测有效)
  7. win 10安装MySQL
  8. 【Linux】SecureCRT中按退格键出现^H
  9. 差分硬盘的merge(合并差异)实验分析
  10. exifinterface.setattribute设置不上去_电脑自动开机怎么设置
  11. PHP基于gettexts实现多语言i18n利用PoEdit
  12. 塞班系统服务器,在Symbian系统邮件应用程序中使用IMAP服务
  13. OpenAI 最强对话模型 ChatGPT 注册使用笔记
  14. 青春时代——是路过还是错过
  15. property of non-object,yii错误
  16. 电脑ip地址错误,网络无法连接怎么一键解决?
  17. 数据告诉你杜蕾斯是怎么风靡全球的?
  18. 数据仓库与数据挖掘-挖掘高价值B站up主案例
  19. 学术速运|利用分子动力学来模拟洗脱溶液中的环肽构象
  20. MATLAB与STK互联47:卫星在轨寿命分析(lifetime)

热门文章

  1. 密码学与网络安全第七版部分课后习题答案
  2. Apache 配置访问日志
  3. html初识教学反思,英语课后反思,英语教学反思20篇简短!
  4. 达梦数据库odbc的安装教程
  5. html5中的空格怎么写,空格的代码(【html5空格代码怎么写】)
  6. 免费的云端软件测试平台-快意测试云平台介绍
  7. Python金融应用编程(数据分析、定价与量化投资)
  8. MCU与电动滑台控制陶瓷加热灯移动模拟人体热释效应
  9. Excel批量数据拼接转换为 insert 插入语句
  10. 总结一下利用Jedis连接redis连接不上的解决办法