python软件长什么样图片_听说各大网站的色情图片识别都是用的这个程序?Python识别色情图...

2.2 程序原理

本程序根据颜色(肤色)找出图片中皮肤的区域,然后通过一些条件判断是否为色情图片。

程序的关键步骤如下:

HSV 颜色模式

h > 0 and h < 35 and s > 0.23 and s < 0.68

97.5 <= cb <= 142.5 and 134 <= cr <= 176

一幅图像有零个到多个的皮肤区域,程序按发现顺序给它们编号,第一个发现的区域编号为 0,第 n 个发现的区域编号为 n-1

我们用一种类型来表示像素,我们给这个类型取名为 Skin ,包含了像素的一些信息:唯一的 编号( id ),是/否肤色( skin ),皮肤区域号( region ),横坐标( x ),纵坐标( y)

接下来实现细节部分

2.3 实现脚本

在 /home/shiyanlou/ 目录下新建 nude.py 文件,我们将在这个文件中进行代码的编写:

导入所需要的模块

import sys import os import _io from collections import namedtuple from PIL import Image

我们将设计一个 Nude 类:

class Nude(object):

这个类里面我们首先使用 collections.namedtuple 定义一个 Skin 类型

Skin = namedtuple("Skin", "id skin region x y")

def __init__(self, path_or_image): # 若 path_or_image 为 Image.Image 类型的实例,直接赋值 if isinstance(path_or_image, Image.Image): self.image = path_or_image # 若 path_or_image 为 str 类型的实例,打开图片 elif isinstance(path_or_image, str): self.image = Image.open(path_or_image) # 获得图片所有颜色通道 bands = self.image.getbands # 判断是否为单通道图片(也即灰度图),是则将灰度图转换为 RGB 图 if len(bands) == 1: # 新建相同大小的 RGB 图像 new_img = Image.new("RGB", self.image.size) # 拷贝灰度图 self.image 到 RGB图 new_img.paste (PIL 自动进行颜色通道转换) new_img.paste(self.image) f = self.image.filename # 替换 self.image self.image = new_img self.image.filename = f # 存储对应图像所有像素的全部 Skin 对象 self.skin_map = # 检测到的皮肤区域,元素的索引即为皮肤区域号,元素都是包含一些 Skin 对象的列表 self.detected_regions = # 元素都是包含一些 int 对象(区域号)的列表 # 这些元素中的区域号代表的区域都是待合并的区域 self.merge_regions = # 整合后的皮肤区域,元素的索引即为皮肤区域号,元素都是包含一些 Skin 对象的列表 self.skin_regions = # 最近合并的两个皮肤区域的区域号,初始化为 -1 self.last_from, self.last_to = -1, -1 # 色情图像判断结果 self.result = None # 处理得到的信息 self.message = None # 图像宽高 self.width, self.height = self.image.size # 图像总像素 self.total_pixels = self.width * self.height

本实验代码中使用到的模块中的函数均可以在其模块的文档中找到,一定要培养查阅文档的习惯isinstane(object, classinfo)

如果参数 object 是参数 classinfo 的实例,返回真,否则假;参数 classinfo 可以是一个包含若干 type 对象的元祖,如果参数 object 是其中任意一个类型的实例,返回真,否则假

涉及到效率问题,越大的图片所需要消耗的资源与时间越大,因此有时候可能需要对图片进行缩小

所以需要有图片缩小方法

若当前像素并不是肤色,那么跳过本次循环,继续遍历

# 若当前像素不为肤色像素,跳过此次循环 if not isSkin: continue

若当前像素是肤色像素,那么就需要处理了,先遍历其相邻像素

检测的图像里,有些前几行的像素的相邻像素并没有 4 个,所以需要用 try “试错”

然后相邻像素的若是肤色像素,如果两个像素的皮肤区域号都为有效值且不同,因为两个区域中的像素相邻,那么其实这两个区域是连通的,说明需要合并这两个区域。记录下此相邻肤色像素的区域号,之后便可以将当前像素归到这个皮肤区域里了。

遍历完所有相邻像素后,分两种情况处理

方法 self._merge 便是用来合并这些连通的皮肤区域的

方法 self._analyse_regions ,运用之前在程序原理一节定义的非色情图像判定规则,从而得到判定结果

现在编写我们还没写过的调用过的 Nude 类的方法

首先是 self._classify_skin 方法,这个方法是检测像素颜色是否为肤色,之前在程序原理一节已经把肤色判定该公式列举了出来,现在是用的时候了

颜色模式的转换并不是本实验的重点,转换公式可以在网上找到,这里我们直接拿来用就行

def _to_normalized(self, r, g, b): if r == 0: r = 0.0001 if g == 0: g = 0.0001 if b == 0: b = 0.0001 _sum = float(r + g + b) return [r / _sum, g / _sum, b / _sum] def _to_ycbcr(self, r, g, b): # 公式来源: # http://stackoverflow.com/questions/19459831/rgb-to-ycbcr-conversion-problems y = .299*r + .587*g + .114*b cb = 128 - 0.168736*r - 0.331364*g + 0.5*b cr = 128 + 0.5*r - 0.418688*g - 0.081312*b return y, cb, cr def _to_hsv(self, r, g, b): h = 0 _sum = float(r + g + b) _max = float(max([r, g, b])) _min = float(min([r, g, b])) diff = float(_max - _min) if _sum == 0: _sum = 0.0001 if _max == r: if diff == 0: h = sys.maxsize else: h = (g - b) / diff elif _max == g: h = 2 + ((g - r) / diff) else: h = 4 + ((r - g) / diff) h *= 60

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值