本项目将使用python3去识别图片是否为图片,会使用到PIL这个图像处理库,并且编写算法来划分图像的皮肤区域
介绍一下PIL:
PIL(Python Image Library)是一种免费的图像处理工具包,这个软件包提供了基本的图像处理功能,如:改变图像大小,旋转图像,图像格式转化,色场空间转换(这个我不太懂),图像增强(就是改善清晰度,突出图像有用信息),直方图处理,插值(利用已知邻近像素点的灰度值来产生未知像素点的灰度值)和滤波等等。虽然这个软件包要实现复杂的图像处理算法并不太适合,但是python的快速开发能力以及面向对象等等诸多特点使得它非常适合用来进行原型开发。
在 PIL 中,任何一副图像都是用一个 Image 对象表示,而这个类由和它同名的模块导出,因此,要加载一副图像,最简单的形式是这样的:
注意:==第一行的 Image 是模块名;第二行的 img 是一个 Image 对象;== Image 类是在 Image 模块中定义的。关于 Image 模块和 Image 类,切记不要混淆了。现在,我们就可以对 img 进行各种操作了,所有对 img 的 操作最终都会反映到到 dip.img 图像上
PIL 2009 年之后就没有更新了,也不支持 Python3 ,于是有了 Alex Clark 领导的公益项目 Pillow 。Pillow 是一个对 PIL 友好的分支,支持 Python3,所以我们这里安装的是 Pillow,这是它的官方文档。
默认已经有python3.0以上和包管理工具pip3。那要执行如下命令升级pip3并安装Pillow 工具包:
根据颜色(肤色)找出图片中皮肤的区域,然后通过一些条件判断是否为图片。
程序的关键步骤如下:
遍历每个像素,检查像素颜色是否为肤色
将相邻的肤色像素归为一个皮肤区域,得到若干个皮肤区域
剔除像素数量极少的皮肤区域
我们定义非图片的判定规则如下(满足任意一个判断为真):
皮肤区域的个数小于3个
皮肤区域的像素与图像所有像素的比值小于15%
最大皮肤区域小于总皮肤面积的45%
皮肤区域数量超过60个
这些规则你可以尝试更改,直到程序效果让自己满意为止。关于像素肤色判定这方面,公式可以在网上找到很多,但是世界上不可能有正确率100%的公式。你可以用自己找到的公式,在程序完成后慢慢调试。
RGB颜色模式
第一种:r > 95 and g > 40 and g < 100 and b > 20 and max([r, g, b]) - min([r, g, b]) > 15 and abs(r - g) > 15 and r > g and r > b
第二种:nr = r / (r + g + b), ng = g / (r + g + b), nb = b / (r +g + b) nr / ng > 1.185 and r * b / (r + g + b) ** 2 > 0.107 and r * g / (r + g + b) ** 2 > 0.112
HSV颜色模式
==h > 0 and h < 35 and s > 0.23 and s < 0.68==
YCbCr颜色模式
==97.5 <= cb <= 142.5 and 134 <= cr <= 176==
一幅图像有零个到多个的皮肤区域,程序按发现顺序给它们编号,第一个发现的区域编号为0,第n个发现的区域编号为n-1
用一种类型来表示像素,我们给这个类型取名为Skin,包含了像素的一些信息:唯一的编号id、是/否肤色skin、皮肤区域号region、横坐标x、纵坐标y
遍历所有像素时,我们为每个像素创建一个与之对应的Skin对象,并设置对象的所有属性,其中region属性即为像素所在的皮肤区域编号,创建对象时初始化为无意义的None。关于每个像素的id值,左上角为原点,像素id值按照像素坐标排布,那么看起来如下图:
其实id的顺序也即遍历的顺序。遍历所有像素时,创建Skin对象后,如果当前像素为肤色,且相邻的像素有肤色的,那么我们把这些肤色像素归到一个皮肤区域。
相邻像素的定义:通常都能想到是当前像素周围的8个像素,然而实际上只需要定义4个就可以了,位置分别在当前像素的左方,左上方,正上方,右上方。因为另外四个像素都在当前像素后面,我们还未给这4个像素创建对应的Skin对象:
直接在python中新建文件,在这个文件进行代码编写:
导入所需要的模块:
我们将设计一个Nude类:
这个类里面我们首先使用 定义一个 Skin 类型:
函数实际上是一个返回 Python 中标准元组类型子类的一个工厂方法。你需要传递一个类型名和你需要的字段给它,然后它就会返回一个类,你可以初始化这个类,为你定义的字段传递值等。详情参见官方文档。
然后定义 Nude 类的初始化方法:
如果参数 是参数 的实例,返回真,否则假;参数 可以是一个包含若干 对象的元组,如果参数 是其中任意一个类型的实例,返回真,否则假。
涉及到效率问题,越大的图片所需要消耗的资源与时间越大,因此有时候可能需要对图片进行缩小。所以需要有图片缩小方法:
size – 包含宽高像素数的元祖 (width, height) resample – 可选的重采样滤波器
返回 对象
然后便是最关键之一的解析方法了:
接着,遍历每个像素,为每个像素创建对应的 对象,其中 这个方法是检测像素颜色是否为肤色:
若当前像素并不是肤色,那么跳过本次循环,继续遍历:
若当前像素是肤色像素,那么就需要处理了,先遍历其相邻像素。
一定要注意相邻像素的索引值,因为像素的 值是从 1 开始编起的,而索引是从 0 编起的。变量 是存有当前像素的 值, 所以当前像素在 中的索引值为 ,以此类推,那么其左方的相邻像素在 中的索引值为 ,左上方为 ,上方为 ,右上方为 :
把id值从0编起:
这个方法接收两个区域号,它将会把两个区域号添加到 中的元素中, 的每一个元素都是一个列表,这些列表中存放了 1 到多个的区域号,区域号代表的区域是连通的,需要合并。
检测的图像里,有些前几行的像素的相邻像素并没有 4 个,所以需要用 “试错”。
然后相邻像素的若是肤色像素,如果两个像素的皮肤区域号都为有效值且不同,因为两个区域中的像素相邻,那么其实这两个区域是连通的,说明需要合并这两个区域。记录下此相邻肤色像素的区域号,之后便可以将当前像素归到这个皮肤区域里了。
遍历完所有相邻像素后,分两种情况处理:
所有相邻像素都不是肤色像素:发现了新的皮肤区域。
存在区域号为有效值的相邻肤色像素:region 的中存储的值有用了,把当前像素归到这个相邻像素所在的区域。
返回一个替换指定字段的值为参数的 实例
遍历完所有像素之后,图片的皮肤区域划分初步完成了,只是在变量 中还有一些连通的皮肤区域号,它们需要合并,合并之后就可以进行图片判定了:
方法 便是用来合并这些连通的皮肤区域的。方法 ,运用之前在程序原理一节定义的非图像判定规则,从而得到判定结果。现在编写我们还没写过的调用过的 类的方法。
首先是 方法,这个方法是检测像素颜色是否为肤色,之前在程序原理一节已经把肤色判定该公式列举了出来,现在是用的时候了:
颜色模式的转换并不是本实验的重点,转换公式可以在网上找到,这里我们直接拿来用就行:
方法主要是对 操作,而self.merge_regions 的元素都是包含一些 int 对象(区域号)的列表,列表中的区域号代表的区域都是待合并的区。 方法接收两个区域号,将之添加到 中。
这两个区域号以怎样的形式添加,要分 3 种情况处理:
传入的两个区域号都存在于 中
传入的两个区域号有一个区域号存在于 中
传入的两个区域号都不存在于 中
具体的处理方法,见代码:
在序列中循环时,索引位置和对应值可以使用 enumerate() 函数同时得到,在上面的代码中,索引位置即为 ,对应值即为。 方法则是将 中的元素中的区域号所代表的区域合并,得到新的皮肤区域列表:
方法只将像素数大于指定数量的皮肤区域保留到 :
self._yse_regions() 是很简单的,它的工作只是进行一系列判断,得出图片是否的结论:
然后可以组织下分析得出的信息:
类如果就这样完成了,最后运行脚本时只能得到一些真或假的结果,我们需要更直观的感受程序的分析效果,我们可以生成一张原图的副本,不过这个副本图片中只有黑白色,白色代表皮肤区域,那么这样我们能直观感受到程序分析的效果了。
前面的代码中我们有获得图像的像素的 RGB 值的操作,设置像素的 RGB 值也就是其逆操作,还是很简单的,不过注意设置像素的 RGB 值时不能在原图上操作:
变量 使用而不是列表是有性能上的考量的,Python 中的是哈希表实现的,查询效率很高。最后支持一下命令行参数就大功告成啦!我们使用 这个模块来实现命令行的支持。argparse 模块使得编写用户友好的命令行接口非常容易。程序只需定义好它要求的参数,然后 argparse 将负责如何从 sys.argv 中解析出这些参数。argparse 模块还会自动生成帮助和使用信息并且当用户赋给程序非法的参数时产生错误信息。
具体使用方法请查看argparse的 官方文档
先来一张很正经的测试图片:
在PyCharm中的终端运行下面的命令执行脚本,注意是python3而不是python:
运行截图:
这表示1.jpg不是一张图片
这个项目就是熟悉了一下PIL的使用,了解了图片检查的原理。主要实现难点是在皮肤区域的检测与整合这一方面。项目还有许多可以改进的地方,比如肤色检测公式,判定条件,还有性能问题,我得去学习一下用多线程或多进程提高性能。
感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python必备开发工具
三、最新Python学习笔记
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、Python视频合集
观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
五、实战案例
纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试宝典
本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕,E-mail:975644476@qq.com
本文链接:http://www.gawce.com/tnews/1943.html