要求:肤色检测
基于色度或其它彩色属性设计一个简单的肤色检测器。

  1. 用手机自拍一张人脸图像。
  2. 剪切照片或另外用画笔工具拾取那些可能是肤色的像素(人脸部位)。
  3. 对这些肤色像素计算彩色分布,如彩色直方图。(该属性的直方图
  4. 对背景像素计算彩色分布。
  5. 用手机再自拍一张人脸图像,试着用这两个分布函数,在新拍图像中寻找肤色区域

学校cv课程的一个小作业。
思路分析
首先确定所要选取的属性,比如题目中说的色度,或者其他自行挑选的属性,比如原文题目中的xy色度,就书里写的Yxy空间里的x,y色度,我选取了HSV空间里的H属性,即 色相。我个人感觉选取一个或多个属性都可,多个属性的话,无非就是对每个属性分别选取阈值,和单属性大同小异,都是卡范围。然后把不在范围里的像素值置零,就这样。
完整代码在最后

  1. 这里手动裁切一下肤色区域,比如面部和颈部。(图片来自网络,侵删,ITZY.Yeji)。
  2. 这里我们选择色相作为计算分布的属性,无他,简单有效耳。转换并画出色相分布直方图。
    先观察一下三张图片色相值的取值范围:

    大概都在0到180左右。

    感觉还是能过滤掉相当一部分非肤色像素的。
  3. 这里就到了题目要求的第四步,但是我怀疑是我们老师对题目理解有偏差,大部分情况下背景应该是比较色相不均匀的,应该在背景比较单一的情况下用背景分割,这里摆一下原题目:

    提到说,使用非肤色像素计算分布作为备选项。而且其实不看原题目要求的话,我们老师也没有很说清楚怎么去分割。原题目不仅明确要求用色度(chromaticity),也告诉我们可以用简单的均值方差方法,或均值偏移分割算法。不看原题目要求的话,我本人最简单的想法就是把肤色属性范围以外的像素排除掉。这里使用最简单的想法和均值方差blabla方法。
  4. 直接排除色相值所有不在肤色色度区间的所有像素。
    使用采集的两个肤色色相区域分别过滤:

emmmmm效果还是可以的,颈部肤色色相区间覆盖更全面效果更好。(没覆盖腮红好像)
(PS:对不起美女,下次回归一直多多支持你)
5. 使用均值方差blabla:

就是卡一个色相范围,a值越大保留越多,可以根据效果选择最适当的a值。
然后我们大概封装一下去试一下别的图像效果怎么样。还是用hlz的自拍,她好美。
封装的是均值方差那个,多个参数玩。
封装函数:

测试代码:

效果:

只能说一般。
完整 notebook代码:

# %%
# created by Jinx7288 230317
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv# %% 欣赏一下hlz美貌
selfie2 = cv.imread(cv.samples.findFile('./selfies/2.jpg'),cv.IMREAD_COLOR)
selfie2 = selfie2[:,:,::-1]
plt.axis('off')
plt.imshow(selfie2)# %% 读入肤色取样
skin_face = cv.imread(cv.samples.findFile('./skins/2_cropped_face.jpg'),cv.IMREAD_COLOR)[:,:,::-1]
skin_neck = cv.imread(cv.samples.findFile('./skins/2_cropped_neck.jpg'),cv.IMREAD_COLOR)[:,:,::-1]
skin_list = [skin_face,skin_neck]# %% 开始看错了,画了一下rgb直方图,不过可以看出用r去过滤也许也可以
plt.subplots_adjust(wspace=0.2,hspace=0.5)
for i,t in enumerate(['skin_face','skin_neck']):plt.subplot(len(skin_list),2,2*i+1)# plt.axis('off')plt.title(t)plt.imshow(skin_list[i])plt.subplot(len(skin_list),2,2*i+2)plt.title('histogram_'+t)hists = [cv.calcHist([skin_list[i]],[j],None,[256],[0,256]) for j in range(3)]for h,c in zip(hists,('r','g','b')):plt.plot(h,color=c)# %% 转换为hsv空间
skin_face_hsv = cv.cvtColor(skin_face,cv.COLOR_RGB2HSV)
skin_neck_hsv = cv.cvtColor(skin_neck,cv.COLOR_RGB2HSV)
selfie2_hsv = cv.cvtColor(selfie2,cv.COLOR_RGB2HSV)
hsv_list = [skin_face_hsv,skin_neck_hsv,selfie2_hsv]
for hsv in hsv_list:print(hsv[:,:,0].min(),hsv[:,:,0].max())# %% 画一下色相直方图
plt.subplots_adjust(wspace=0.2,hspace=0.5)
for i,t in enumerate(['skin_face','skin_neck','original']):plt.subplot(len(hsv_list),2,2*i+1)# plt.axis('off')plt.title(t)plt.imshow(hsv_list[i][:,:,0])plt.subplot(len(hsv_list),2,2*i+2)plt.title('hue_histogram_'+t)plt.plot(cv.calcHist([hsv_list[i]],[0],None,[180],[0,180]))# %% 在范围内保留,其他舍弃
selfie2_h = np.array(selfie2_hsv[:,:,0],dtype=int)
for i,e in enumerate([skin_face_hsv,skin_neck_hsv]):hue_all_range = (e[:,:,0].min(),e[:,:,0].max())mask = np.zeros(selfie2_h.shape)mask[np.logical_and(selfie2_h>=hue_all_range[0],selfie2_h<hue_all_range[1])]=1plt.subplot(2,2,2*i+1)plt.imshow(mask,cmap='gray')selfie2_hsv_temp = np.copy(selfie2_hsv)for j in range(3):new_channel = mask*np.array(selfie2_hsv[:,:,j],dtype=float)selfie2_hsv_temp[:,:,j]= new_channelplt.subplot(2,2,2*i+2)new_selfie = cv.cvtColor(selfie2_hsv_temp,cv.COLOR_HSV2RGB)plt.imshow(new_selfie)# %% 在均值+-a*标准差范围内保留,其他舍弃
# 均值方差blabla,不过用的是标准差
a = 2
for i,e in enumerate([skin_face_hsv,skin_neck_hsv]):h = np.array(e[:,:,0],dtype=float)mean_h = h.mean()std_h = np.std(h)hue_mean_range = (mean_h-a*std_h,mean_h+a*std_h)# print(hue_mean_range)mask = np.zeros(selfie2_h.shape)mask[np.logical_and(selfie2_h>=hue_mean_range[0],selfie2_h<hue_mean_range[1])]=1plt.subplot(2,2,2*i+1)plt.imshow(mask,cmap='gray')selfie2_hsv_temp = np.copy(selfie2_hsv)for j in range(3):new_channel = mask*np.array(selfie2_hsv[:,:,j],dtype=float)selfie2_hsv_temp[:,:,j]= new_channelplt.subplot(2,2,2*i+2)new_selfie = cv.cvtColor(selfie2_hsv_temp,cv.COLOR_HSV2RGB)plt.imshow(new_selfie)# %%
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cvdef url2hsv(file:str):pic = cv.imread(cv.samples.findFile(file),cv.IMREAD_COLOR)[:,:,::-1]pic_hsv = cv.cvtColor(pic,cv.COLOR_RGB2HSV)return pic_hsv,pic_hsv[:,:,0]def skin_filter(skin_url,target_url,a=1.5):skin_hsv,skin_h = url2hsv(skin_url)target_hsv,target_h = url2hsv(target_url)mean_h = skin_h.mean()std_h = skin_h.std()filter_range = (mean_h-a*std_h,mean_h+a*std_h)mask = np.zeros(target_hsv[:,:,0].shape)mask[np.logical_and(target_h>=filter_range[0],target_h<filter_range[1])]=1for j in range(3):new_channel = mask*np.array(target_hsv[:,:,j],dtype=float)target_hsv[:,:,j]= new_channelnew_selfie = cv.cvtColor(target_hsv,cv.COLOR_HSV2RGB)return mask,new_selfieimport os
selfies = os.listdir('./selfies/')
skin_neck_url = './skins/2_cropped_neck.jpg'plt.subplots_adjust(wspace=0)
for i,ele in enumerate(selfies):filtered = skin_filter(skin_url=skin_neck_url,target_url="./selfies/"+ele,a=3)plt.subplot(len(selfies),3,i*3+1)plt.axis('off')plt.imshow(cv.imread(cv.samples.findFile("./selfies/"+ele),cv.IMREAD_COLOR)[:,:,::-1])plt.subplot(len(selfies),3,i*3+2)plt.axis('off')plt.imshow(filtered[0],cmap='gray')plt.subplot(len(selfies),3,i*3+3)plt.axis('off')plt.imshow(filtered[1])# %%
skin_face_url = './skins/2_cropped_face.jpg'for i,ele in enumerate(selfies):print(ele)filtered = skin_filter(skin_url=skin_face_url,target_url="./selfies/"+ele,a=3)plt.subplot(len(selfies),3,i*3+1)plt.axis('off')plt.imshow(cv.imread(cv.samples.findFile("./selfies/"+ele),cv.IMREAD_COLOR)[:,:,::-1])plt.subplot(len(selfies),3,i*3+2)plt.axis('off')plt.imshow(filtered[0],cmap='gray')plt.subplot(len(selfies),3,i*3+3)plt.axis('off')plt.imshow(filtered[1])

基于色度或其他彩色属性设计一个简单的肤色检测器相关推荐

  1. 天猫php采集列表,QueryList: QueryList是一个基于phpQuery的通用列表采集类,是一个简单、 灵活、强大的采集工具,采集任何复杂的页面 基本上就一句话就能搞定了。...

    #QueryList交流社区: http://querylist.cc/ #QueryList文档: http://doc.querylist.cc/ #QueryList交流QQ群:12326696 ...

  2. 设计一个简单分页存储管理系统_【系统架构】如何设计一个简单灵活的收银系统?看这里!(1)...

    在电商项目中,收银系统是一个不可或缺的功能,因为你不仅要通过它来进行收款.退款,而且也要通过它进行财务的对账.报税等.因此,如何设计一个简单灵活的收银系统,对于开发电商项目来说非常重要. 那如何设计一 ...

  3. 设计一个简单的购物页面(html+css+php)

    水平有限,精力有限,很多东西写得可能不那么详细,有不懂可以留言提问,懂的尽量解答 首先讲一下,购物页面肯定会涉及到数据库部分的,我这篇文章数据库方面不会详细讲,就简单给个思路.购物需要用到cookie ...

  4. C++数据结构||为我院设计一个简单的教师信息管理程序。对我院教师进行管理,包括插入、删除、查找、排序等功能。教师信息包括姓名、性别、出生年月、工作年月、学历、职务、住址、电话等信息。

    0.先序条件 在文件夹中新建名称"教师信息.txt"的文本文件存储教师信息 visual studio 2017 1.背景 数据结构课程设计的作业 为我院设计一个简单的教师信息管理 ...

  5. 支付退款流程设计_【系统架构】如何设计一个简单灵活的收银系统?看这里!(1)...

    在电商项目中,收银系统是一个不可或缺的功能,因为你不仅要通过它来进行收款.退款,而且也要通过它进行财务的对账.报税等.因此,如何设计一个简单灵活的收银系统,对于开发电商项目来说非常重要. 那如何设计一 ...

  6. c语言12之编程设计一个简单的计算器程序,要求根据用户从键盘输入的表达式:操作数1 运算符op 操作数2 计算表达式的值,指定的运算符为加减乘除。

    题目: 设计一个简单的计算器程序,要求根据用户从键盘输入的表达式: 操作数1 运算符op 操作数2 计算表达式的值,指定的运算符为加减乘除. 源代码: #include<stdio.h> ...

  7. 如何用Java设计一个简单的窗口界面(学习中.1)

    如何用Java设计一个简单的窗口界面 一.前言 二.简单了解 1.Swing简介 2.框架(frame) 3.层次 三.步骤 1.打开eclipse,依次创建项目,包,类. 2.代码 2.1最简单的可 ...

  8. JAVA同时输入用户名和密码_用java模拟设计一个简单的“用户注册”程序。当用户输入用户名和密码时,单击“注...

    用java模拟设计一个简单的"用户注册"程序.当用户输入用户名和密码时,单击"注 2020 - 9 - 26 TAG : 所有功能均已实现,如有不满意的地方我再修改imp ...

  9. python界面设计-手把手教你用Python设计一个简单的命令行界面

    原标题:手把手教你用Python设计一个简单的命令行界面 对 Python 程序来说,完备的命令行界面可以提升团队的工作效率,减少调用时可能碰到的困扰.今天,我们就来教大家如何设计功能完整的 Pyth ...

最新文章

  1. 生命或可在星际间传播
  2. 【sql server】“因为数据库正在使用,所以无法获得对数据库的独占访问权” 解决方案汇总
  3. 提高github下载速度
  4. 【英语学习】【WOTD】darling 释义/词源/示例
  5. 89c51,8255,6个led数码管显示时钟的汇编语言程序,汇编语言要求编写一个时钟程序 用八位数码管实现时分秒的计时功能...
  6. Asp.net MVC Pager分页实现
  7. Spring自动注入的几种方式
  8. python基础之centos7源码安装python3
  9. 除了快,5G 有哪些关键技术?
  10. WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传
  11. 【JavaScript 逆向】webpack 之某妹游戏登录逆向
  12. 飞桨领航团武汉长沙 | AI如何1秒记笔记,检测你的皮肤状态?
  13. Context 是什么意思
  14. 【企业高管】CIO vs CEO:主要区别是什么?
  15. 【历史上的今天】6 月 26 日:EDSAC 计算机之父诞生;B 站成立;Skype 创始人出生
  16. C语言 基于循环结构的程序设计(PTA)
  17. 小米路由器3G建站折腾笔记1 - 引言与路由器选择
  18. vue族谱架构_vue.js中使用d3.js画家谱关系图
  19. 免费GIF动图制作,简简单单一招搞定
  20. 一梦江湖卡在服务器信息100,一梦江湖卡69、89、129到底有什么区别?这一篇讲的很清楚了...

热门文章

  1. 程序猿的执业修养(六)——勤学好问,自我批评
  2. 【Hello Network】 IP协议
  3. N1BOOK——[第五章 CTF之RE章]wp
  4. 爬虫小插曲:关于代理参数-proxies那些事
  5. 2014年3月份第4周51Aspx源码发布详情
  6. 002 分布式核心概念-CAP帽子理论分析及BASE理论分析
  7. 利用Spring AOP 更新memcached 缓存策略的实现(一)
  8. 逻辑回归模型预测股票涨跌
  9. WEBSTORM 2018版本破解的教程
  10. AcWing 1695. 果壳游戏(模拟)