肤色检测算法 - 基于二次多项式混合模型的肤色检测。

由于CSDN博客和博客园的编辑方面有不一致的地方,导致文中部分图片错位,为不影响浏览效果,建议点击打开链接 

      由于能力有限,算法层面的东西自己去创新的很少,很多都是从现有的论文中学习,然后实践的。

      本文涉及的很多算法,在网络上也有不少同类型的文章,但是肯定的一点就是,很多都是不配代码的,或者所附带的代码都是象征性的,速度慢,不优雅,不具有实用价值,本文努力解决这些问题。

      文中各算法出现的顺序并不代表算法的优越性,仅仅是作者随机排布的而已。

      1、二次多项式混合模型

           二次多项式混合模型首先有SORIANO提出,此后CHIANG对此进行了改进。改进后的模型由两个R-G平面的二次多项式和一个圆方程构成:

在以上三个方程的基础上,肤色区域可以通过一下规则实现:

               

     上述算法的参考论文:Adaptive skin color modeling using the skin locus.pdf  

 A novel method for detecting lips,eyes and faces in real time

以及百度文库相关文章:基于混合肤色模型的快速人脸检测算法 

     上式中,小写r,g,b(未涉及)为对R/G/B(byte类型的数据,0-255)进行归一化后的数据,即:

             

     如上所示,算法中涉及到了不少的浮点运算,以及大量的乘法,如果按照源汁原味的来编写代码,程序的效率可想而知。因此,我们着手于算法的优化。

     首先,我们来看四个判断条件,由于判断条件是不分先后,需要同时满足的地方才是区域,因此应该把简单的判断条件放在最前面判断。

     首先看如果符合了判断条件R4,条件R3中的R>G肯定是已经成立的,则只需要判断G是否大于B,这是优化手段1。  

     然后我们来看R2的优化,为方便表达,我们这里令Sum=R+G+B,将判断条件R2展开:

                     

     上式子最后一步同时乘以156, 理论上说156×0.33=51.48,不应该取52的,不过这个0.33本来就是个经验数据,谁说不能是1/3呢。

     到此,我们看到在式子的最右侧还有个浮点数0.0624,如果不消除该数据,算法速度依旧会有大的影响,常常研究移位的朋友肯定对0.0625这个数字很熟悉,1/16=0.0625,不是吗,懂了吗,还不懂,看代码吧(这里的式子很多都是经验公式,因此,稍微修改一些参数对结果基本无影响)。

     上述这样做的目的,无非是将浮点数的运算全部转换为整数的运算。

最后来看式R1的优化,R1实际上也是两个条件,把他分开来,分别称为R11及R12,对于R11,同样展开:

               

     现在大部分的PC都还是32位的系统,因此,使用32位的整数类数据类型速度是最快的,因此,如果上述放大系数的取夺就必须主要使得计算式两边的值都在int.MinValue和 int.MaxValue之间,比如上式,>号左侧算式的肯能最大取值为10000×255×765,是小于int.MaxValue所能表达的范围的,因此放大系数是合理的。

     对于R12的展开我想应该不需要我在去贴出来了吧。

     算法部分参考代码:

for (Y = 0; Y < Height; Y++)
{Pointer = Scan0 + Y * Stride;SkinP = SkinScan0 + Y * SkinStride;for (X = 0; X < Width; X++){*SkinP = 0;                                 // 非皮肤区域为黑色Blue = *Pointer; Green = *(Pointer + 1); Red = *(Pointer + 2);if (Red - Green >= 45)                                              //  符合条件R4
        {if (Green > Blue)                                               //   符合条件R3
            {Sum = Red + Green + Blue;T1 = 156 * Red - 52 * Sum;                                 T2 = 156 * Green - 52 * Sum;if (T1 * T1 + T2 * T2 >= (Sum * Sum) >> 4)                    // 符合条件R2,在32位系统要尽量避免用long类型数据,
                   {T1 = 10000 * Green * Sum;Lower = - 7760 * Red * Red + 5601 * Red * Sum + 1766 * Sum * Sum;         // 把这里的公用的乘法提取出来基本没啥优化的效果if (T1 > Lower)                                         // 符合条件R11
                    {Upper = - 13767 * Red * Red + 10743 * Red * Sum + 1452 * Sum * Sum ;if (T1 < Upper)                                     //  符合条件R12
                        {*SkinP = 255;}}}}}Pointer += 3;SkinP++;}

本人特喜欢优化,特别是代码层面的优化,比如上述的 Lower = 5601 * Red * Sum + 1766 * Sum * Sum 这句,偶尔我写成Lower =- Red * Red * 7760+ 5601 * Red * Sum + 1766 * Sum * Sum 这样,然后没事的时候我反汇编了两种写法有什么不同,结果如下:

 Lower =-7760 * Red * Red+ 5601 * Red * Sum + 1766 * Sum * Sum ;         // 把这里的公用的乘法提取出来基本没啥优化的效果
00000118  imul        ebx,ecx,0FFFFE1B0h 
0000011e  imul        ebx,ecx 
00000121  imul        eax,ecx,15E1h 
00000127  imul        eax,esi 
0000012a  add         ebx,eax 
0000012c  imul        eax,esi,6E6h 
00000132  imul        eax,esi 
00000135  add         ebx,eax 

 

 Lower = -Red * Red * 7760 * +5601 * Red * Sum + 1766 * Sum * Sum;         // 把这里的公用的乘法提取出来基本没啥优化的效果
00000118  mov         ebx,ecx 
0000011a  neg         ebx 
0000011c  imul        ebx,ecx 
0000011f  imul        ebx,ebx,1E50h 
00000125  imul        ebx,ebx,15E1h 
0000012b  imul        ebx,ecx 
0000012e  imul        ebx,esi 
00000131  imul        eax,esi,6E6h 
00000137  imul        eax,esi 
0000013a  add         ebx,eax 

     可见多了两条汇编语句的。可能这个优化举在这里不合适,因为有个系数-7760,一般谁都不会像上面写,但是如果系数是-1,那就比一定了,比如如果是-Red+Blue 和Blue-Red那就有着截然不同的意义了。

      这个算法的皮肤检测效果还是很不错的,那原文中的图像来举例如下:

           

        原图                                                           梦版图                                                      合成图

 然后贴一张别人博客上的照片的例子(一群帅哥和美女):

 检测结果:

  由于是有选择性的执行,因此程序执行的速度其实和图像的内容有关,同样一副大小的图像,如果皮肤部分站的比例越大,执行的时间可能就会越长,就上述这幅800*600的图像来说,在我I3的笔记本上仅用了4ms就得到了结果,因此速度是相当的快的。

      测试工程随后附上。

     

*****************************基本上我不提供源代码,但是我会尽量用文字把对应的算法描述清楚或提供参考文档**************************

*******************************因为靠自己的努力和实践写出来的效果才真正是自己的东西,人一定要靠自己****************************

***************************作者: laviewpbt   时间: 2013.8.17   联系QQ:  33184777  转载请保留本行信息*************************

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle解析儒略日,利用to_char获取当前日期准确的周数!

总的来说周数的算法有两种&#xff1a;算法一&#xff1a;iw算法&#xff0c;每周为星期一到星期日算一周&#xff0c;且每年的第一个星期一为第一周&#xff0c;就拿2014年来说&#xff0c;2014-01-01是星期三&#xff0c;但还是算为今年的第一周&#xff0c;可以简单的用sql函…

密码机

树状数组1 #include<bits/stdc.h>2 using namespace std;3 int x,y,c[200005];4 char str[20];5 int inline read(){6 int x0,f1;7 char chgetchar();8 while(ch<0||ch>9)9 chgetchar(); 10 while(ch>0&&ch<9){ 11 …

js有默认参数的函数加参数_函数参数:默认,关键字和任意

js有默认参数的函数加参数PYTHON开发人员的提示 (TIPS FOR PYTHON DEVELOPERS) Think that you are writing a function that accepts multiple parameters, and there is often a common value for some of these parameters. For instance, you would like to be able to cal…

sql management studio 附加mdf文件出错的解决办法

将mdf文件所在文件夹的权限改为everyone.&#xff0c;完全控制即可。

oracle raise_application_error,RAISE_ APPLICATION_ ERROR--之异常处理

平时用来测试的异常处理我们都是通过dbms_output.put_line来输出异常信息&#xff0c;但是在实际的应用中&#xff0c;需要把异常信息返回给调用的客户端。其实 RAISE_APPLICATION_ERROR 是将应用程序专有的错误从服务器端转达到客户端应用程序(其他机器上的SQLPLUS或者其他前台…

金融信息交换协议

随着网络的使用&#xff0c;目前所有大型的金融机构都已经实现了自动化和数字化。当中肯定少不了互联网的加入&#xff0c;那么在这当中&#xff0c;我们主要介绍一下FIX协议。它是由国际FIX协会组织提供的一个开放式协议&#xff0c;目的是推动国际贸易电子化的进程&#xff0…

2018大数据学习路线从入门到精通

最近很多人问小编现在学习大数据这么多&#xff0c;他们都是如何学习的呢。很多初学者在萌生向大数据方向发展的想法之后&#xff0c;不免产生一些疑问&#xff0c;应该怎样入门&#xff1f;应该学习哪些技术&#xff1f;学习路线又是什么&#xff1f;今天小编特意为大家整理了…

相似邻里算法_纽约市-邻里之战

相似邻里算法IBM Data Science Capstone ProjectIBM Data Science Capstone项目 分析和可视化与服装店投资者的要求有关的纽约市结构 (Analyzing and visualizing the structure of New York City in relation to the requirements of a Clothing Store Investor) 介绍 (Introd…

一、面向对象

第一节&#xff1a;面向对象编程1.面向对象三大原则&#xff1a;封装&#xff1a;就是把客观事物封装成抽象的类&#xff0c;并且类可以把自己的数据和方法只让可信的类或者对象操作&#xff0c;对不可信的进行信息隐藏。继承&#xff1a;继承&#xff0c;指可以让某个类型的对…

[poj 1364]King[差分约束详解(续篇)][超级源点][SPFA][Bellman-Ford]

题意 有n个数的序列, 下标为[1.. N ], 限制条件为: 下标从 si 到 sini 的项求和 < 或 > ki. 一共有m个限制条件. 问是否存在满足条件的序列. 思路 转化为差分约束, 就是 即 Si 为第 i 项的前缀和, 特别的 So 为0. 转化不等式(连续子段和变为前缀和之差 > < 变为 &g…

linux质控命令,Linux下microRNA质控-cutadapt安装

如果Linux系统已安装pip或conda&#xff0c;cutadapt的安装相对简便一些&#xff0c;示例如下&#xff1a;1.pip安装pip install --user --upgrade cutadapt添加环境变量echo export PATH$PATH:/your path/cutadapt-1.10/bin >> ~/.bashrc2.conda安装conda install -c b…

采用多播传送FIX行情数据的推荐方案

理由FIX协议由一个会话层协议&#xff0c;一个应用层协议和一套域数据字典组成。后两者不依赖于FIX会话。而且&#xff0c;由于FIX会话作为Point-to-point&#xff08;点-对-点&#xff09;通信&#xff0c;并不适合于发布/订阅模式&#xff08;如为大量接收者提供市场数据&…

AJAX 异步加载技术

AJAX 异步 JavaScript 和 XML。 AJAX 是一种用于创建快速动态网页的技术。 通过在后台与服务器进行少量数据交换&#xff0c;AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下&#xff0c;对网页的某部分进行更新。 传统的网页&#xff08;不使用 AJAX…

linux分辨率和用户有关吗,Linux系统在高分屏非正常分辨率显示

问题描述&#xff1a;win10重装为Ubuntu16.04&#xff0c;在1920x1080的显示屏上&#xff0c;linux系统分辨率只有800x600xrandr # 查看当前显示分辨率#输出&#xff1a;[Screen 0: minimum 800 x 600, current 800 x 600, maximum 800 x 600]可以看出显示屏最小为800x600&…

数据透视表和数据交叉表_数据透视表的数据提取

数据透视表和数据交叉表Consider the data of healthcare drugs as provided in the excel sheet. The concept of pivot tables in python allows you to extract the significance from a large detailed dataset. A pivot table helps in tracking only the required inform…

金融信息交换协议(FIX)v5.0

1. 什么是FIXFinancial Information eXchange(FIX)金融信息交换协议的制定是由多个致力于提升其相互间交易流程效率的金融机构和经纪商于1992年共同发起。这些企业把他们及他们的行业视为一个整体&#xff0c;认为能够从对交易指示&#xff0c;交易指令及交易执行的高效电子数…

观光公交

【问题描述】 风景迷人的小城 Y 市&#xff0c;拥有 n 个美丽的景点。由于慕名而来的游客越来越多&#xff0c;Y 市特意安排了一辆观光公交车&#xff0c;为游客提供更便捷的交通服务。观光公交车在第 0 分钟出现在 1 号景点&#xff0c;随后依次前往 2、3、4……n 号景点。从…

linux行命令测网速,Linux命令行测试网速的方法

最近给服务器调整了互联网带宽的限速策略&#xff0c;调到100M让自己网站也爽一下。一般在windows上我喜欢用speedtest.net来测试&#xff0c;测速结果也被大家认可。在linux上speedtest.net提供了一个命令行工具speedtest-cli&#xff0c;用起来很方便&#xff0c;这里分享一下…

Delphi XE2获取汉字拼音首字母

function CnPYIndex(const CnString: string): string;{ 返回中文的拼音首字母}const ChinaCode: array[0..25, 0..1] of Integer ((1601, 1636), (1637, 1832), (1833, 2077), (2078, 2273), (2274, 2301), (2302, 2432), (2433, 2593), (2594, 2786), (9999, 0000), …

图像处理傅里叶变换图像变化_傅里叶变换和图像床单视图。

图像处理傅里叶变换图像变化What do Fourier Transforms do? What do the Fourier modes represent? Why are Fourier Transforms notoriously popular for data compression? These are the questions this article aims to address using an interesting analogy to repre…