前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用人工智能检测色情图片

利用人工智能检测色情图片

作者头像
云水木石
发布2019-07-02 14:55:35
2.7K2
发布2019-07-02 14:55:35
举报

色情内容在中国一直处于严格的监管,即使这样,互联网上还是很容易就能访问到色情内容。还记得曾经的“绿坝-花季护航”软件么?由于其识别效果差、软件不稳定,最后不了了之,浪费了大量的人力和金钱。

随着计算机视觉和深度学习的发展,算法已经成熟,利用人工智能,我们能够更加精确的识别色情内容。现在有很多云服务商提供鉴黄服务,通过集成鉴黄API到产品中,就可以给产品增加色情过滤功能。这种模式对于大多数互联网产品非常有效,可以极大的降低运营风险(对于博客、图床、直播等服务提供商而言,过滤色情、暴力等内容是重中之重)。但对于一部分产品而言,这种模式存在一些不足:

  1. 鉴别图片、视频内容等必须通过网络服务进行,响应速度难以保证;
  2. 通常鉴黄服务按次或者按照流量计费,对于个人开发者而言,有成本负担;

open_nsfw

现在有个好消息,雅虎开源了其深度学习色情图片检测模型open_nsfw,项目地址: http://github.com/yahoo/open_nsfw,这里的NSFW代表Not Suitable for Work。项目提供了基于caffe的深度神经网络模型和一个python脚本,可以供测试:

代码语言:javascript
复制
python ./classify_nsfw.py \
--model_def nsfw_model/deploy.prototxt \
--pretrained_model nsfw_model/resnet_50_1by2_nsfw.caffemodel \
test_image.jpg

定义NSFW内容是非常主观的,在某个国家或地区会引起反感的内容可能在另一个地方完全没问题。所以,open_nsfw模型只关注一种类型的NSFW内容:色情图片。但需要注意的是,该模型不能解决草图、漫画、文本等内容的识别。

色情图片的判别也是非常主观的,所以该模型并不会直接给出某个图片是否色情的结果,而是给出一个概率(0-1之间的分数)。一般而言,得分小于0.2表示图像很可能是安全的,评分大于0.8则基本可判定图片属于色情图片。如果得分介于这两个值之间,则需要程序员根据需求来设定一个阀值。如果需要比较严格的过滤,设一个比较低的阀值,反之设一个比较高的阀值。

集成open_nsfw到C++程序

open_nsfw提供了一个python脚本,google了一圈,也没有找到有人将open_nsfw集成到C++代码中。好在classify_nsfw.py这个脚本比较简单,而caffe提供了C++的例子cpp_classification,结合这两部分的代码,我编写了一个C++的鉴黄程序,源码参考:https://gitee.com/mogoweb/dpexamples。

当然看似简单的代码翻译工作,遇到的坑也不少,下面就总结一下C++代码中需要注意的地方。

图片预处理

在classify_nsfw.py中,编写了一个resize_image函数来处理图片缩放,没有采用caffe内置的图片缩放程序。代码注释中解释是因为训练时使用了这个缩放算法,所以为了达到最好的效果,测试中也需要采用该缩放算法。随后又对图片进行了一次裁剪,因为调用resize_image缩放为256x256大小,而模型接受的size为224x224。

代码语言:javascript
复制
img_data_rs = resize_image(pimg, sz=(256, 256))
image = caffe.io.load_image(StringIO(img_data_rs))H, W, _ = image.shape
_, _, h, w = caffe_net.blobs['data'].data.shape
h_off = max((H - h) / 2, 0)
w_off = max((W - w) / 2, 0)
crop = image[h_off:h_off + h, w_off:w_off + w, :]

在C++代码中,我使用了caffe中提供的opencv方法处理这个步骤:

代码语言:javascript
复制
cv::Mat img = ReadImageToCVMat(file, 256, 256);
...
// crop image
cv::Size size = sample.size();
int H = size.height;
int W = size.width;
int h = input_geometry_.height;
int w = input_geometry_.width;int h_off = std::max((H - h) / 2, 0);
int w_off = std::max((W - w) / 2, 0);
sample(cv::Rect(w_off, h_off, w, h)).copyTo(sample_resized);
数据预处理

在classify_nsfw.py中,我们可以看到这样一段代码:

代码语言:javascript
复制
caffe_transformer = caffe.io.Transformer({'data': nsfw_net.blobs['data'].data.shape})
# move image channels to outermost
caffe_transformer.set_transpose('data', (2, 0, 1))
# subtract the dataset-mean value in each channel
caffe_transformer.set_mean('data', np.array([104, 117, 123]))
# rescale from [0, 1] to [0, 255]
caffe_transformer.set_raw_scale('data', 255)
# swap channels from RGB to BGR
caffe_transformer.set_channel_swap('data', (2, 1, 0))

这段代码其实是对数据做某种变换,将读入的数据转换为caffe模型能够接受的格式。

代码语言:javascript
复制
caffe_transformer.set_transpose('data', (2, 0, 1))

该语句困扰了我好长时间,不知道在C++程序中该如何处理。后查网络资料,才了解到因为caffe.io读取的图像为HWC(H:高,W:宽,C:颜色)矩阵,而caffe模型需要(CHW)格式,所以需要对矩阵做一个变换,将颜色值维度提前到最前面。(2, 0, 1)的含义就是将原来数据的第2, 0, 1列按照新的顺序重新排列。

代码语言:javascript
复制
caffe_transformer.set_raw_scale('data', 255)

这个处理是因为使用caffe.io读取的颜色值归一化为0~1之间的数,而caffe模型接受的是一个字节的整数,范围0~255,所以需要进行一个放大。

在C++代码中,由于采用了opencv进行图像处理,不需要上面两步的变换处理。

代码语言:javascript
复制
caffe_transformer.set_mean('data', np.array([104, 117, 123]))

在很多示例中,均值通常从均值文件中加载,这里直接给了一个固定值。所谓均值,可以理解为数据的算术平均值。通常输入数据减去均值,是为了减少奇异值(异常的值,比平均值大很多或小很多的值)的影响。这里是一个三元组,分别代表RGB通道上的均值。

对应的C++代码如下:

代码语言:javascript
复制
cv::Mat sample_normalized;
cv::subtract(sample_float, mean_, sample_normalized);

接下来的代码是RGB转BGR,这个比较容易理解。

代码语言:javascript
复制
caffe_transformer.set_channel_swap('data', (2, 1, 0))

查看了一些caffe的C++例子,均没有这个步骤,可能cv::Mat中已经能够正确判断出RGB和BGR,所以代码中没有增加这一步骤。

对比测试

这个程序是否能够如愿工作呢?让我们找一些图片测试一下。考虑到内容审查,这里进行测试的图片均不是严格意义上的色情图片,只是裸露程度不同。下面使用C++程序和open_nsfw python脚本测试的结果进行对比。

C++ : 0.6122

python: 0.875480949879

C++ : 0.2536

python: 0.0773676931858

C++ : 0.6319

python: 0.782215833664

C++ : 0.0914

python: 0.0774072110653

C++ : 0.0073

python: 3.04092318402e-05

从结果可以看出,使用C++程序进行测试,结果基本符合预期,但是和python版本还是有一些差距,猜测问题可能在于对图片进行缩放采用的算法不同,如果要获得好的结果,训练和测试阶段对数据的预处理需要一致。另外一个可能是没有RGB到BGR的转换,这个还需要再验证。

如果你有兴趣,可以找一些尺度更大的图片测试,看看是不是能够正确的识别出来。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云水木石 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • open_nsfw
  • 集成open_nsfw到C++程序
    • 图片预处理
      • 数据预处理
        • 对比测试
        相关产品与服务
        云直播
        云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档