网易首页 > 网易号 > 正文 申请入驻

NSFW 图片分类

0
分享至


NSFW指的是不适宜工作场所("Not Safe (or Suitable) For Work;")。在本文中,我介绍如何创建一个检测NSFW图像的图像分类模型。

数据集

由于数据集的性质,我们无法从一些数据集的网站(如Kaggle等)获得所有图像。

但是我们找到了一个专门抓取这种类型图片的github库,所以我们可以直接使用。clone项目后可以运行下面的代码来创建文件夹,并将每个图像下载到其特定的文件夹中。

folders = ['drawings','hentai','neutral','porn','sexy']
urls = ['urls_drawings.txt','urls_hentai.txt','urls_neutral.txt','urls_porn.txt','urls_sexy.txt']
names = ['d','h','n','p','s']
for i,j,k in zip(folders,urls,names):
try:
#Specify the path of the folder that has to be made
folder_path = os.path.join('your directory',i)
os.mkdir(folder_path)
except:
pass
#setup the path of url text file
url_path = os.path.join('Datasets_Urls',j)
my_file = open(url_path, "r")
data = my_file.read()
#create a list with all urls
data_into_list = data.split("\n")
my_file.close()
icount = 0
for ii in data_into_list:
try:
#create a unique image names for each images
image_name = 'image'+str(icount)+str(k)+'.png'
image_path = os.path.join(folder_path,image_name)
#download it using the library
urllib.request.urlretrieve(ii, image_path)
icount+=1
except Exception as e:
pass
#this below code is done to make the count of the image same for all the data
#you can use a big number if you are building a more complex model or if you have a good system
if icount == 2000:
break

这里的folder变量表示类的名称,urls变量用于获取URL文本文件(可以根据文本文件名更改它),name变量用于为每个图像创建唯一的名称。

上面代码将为每个类下载2000张图像,可以编辑最后一个“if”条件来更改下载图像的个数。

数据准备

我们下载的文件夹可能包含其他类型的文件,所以首先必须删除不需要的类型的文件。

image_exts = ['jpeg','.jpg','bmp','png']
path_list = ['drawings','hentai','neutral','porn','sexy']
cwd = os.getcwd()
def remove_other_images(path_list):
for ii in path_list:
data_dir = os.path.join(cwd,'DataSet',ii)
for image in os.listdir(os.path.join(data_dir)):
image_path = os.path.join(data_dir,image_class,image)
try:
img = cv2.imread(image_path)
tip = imghdr.what(image_path)
if tip not in image_exts:
print('Image not in ext list {}'.format(image_path))
os.remove(image_path)
except Exception as e:
print("Issue with image {}".format(image_path))
remove_other_images(path_list)

上面的代码删除了扩展名不是指定格式的图像。

另外图像可能包含许多重复的图像,所以我们必须从每个文件夹中删除重复的图像。

cwd = os.getcwd()
path_list = ['drawings','hentai','neutral','porn','sexy']
def remove_dup_images(path_list):
for ii in path_list:
os.chdir(os.path.join(cwd,'DataSet',ii))
filelist = os.listdir()
duplicates = []
hash_keys = dict()
for index, filename in enumerate(filelist):
if os.path.isfile(filename):
with open(filename,'rb') as f:
filehash = hashlib.md5(f.read()).hexdigest()
if filehash not in hash_keys:
hash_keys[filehash] = index
else:
duplicates.append((index,hash_keys[filehash]))
for index in duplicates:
os.remove(filelist[index[0]])
print('{} duplicates removed from {}'.format(len(duplicates),ii))
remove_dup_images(path_list)

这里我们使用hashlib.md5编码来查找每个类中的重复图像。

Md5为每个图像创建一个唯一的哈希值,如果哈希值重复(重复图像),那么我们将重复图片添加到一个列表中,稍后进行删除。

因为使用TensorFlow框架所以需要判断是否被TensorFlow支持,所以我们这里加一个判断:

import tensorflow as tf
os.chdir('{data-set} directory')
cwd = os.getcwd()
for ii in path_list:
os.chdir(os.path.join(cwd,ii))
filelist = os.listdir()
for image_file in filelist:
with open(image_file, 'rb') as f:
image_data = f.read()
# Check the file format
_, ext = os.path.splitext(image_file)
if ext.lower() not in ['.jpg', '.jpeg', '.png', '.gif', '.bmp']:
print('Unsupported image format:', ext)
os.remove(os.path.join(cwd,ii,image_file))
else:
# Decode the image
try:
image = tf.image.decode_image(image_data)
except:
print(image_file)
print("unspported")
os.remove(os.path.join(cwd,ii,image_file))

以上就是数据准备的所有工作,在清理完数据后,我们可以拆分数据。比如分割创建一个训练、验证和测试文件夹,并手动添加文件夹中的图像,我们将80%用于训练,10%用于验证,10%用于测试。

模型

首先导入tensorflow

import tensorflow as tf
import os
import numpy as np
import matplotlib.pyplot as plt
from sklearn.utils import shuffle
import hashlib
from imageio import imread
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.applications.vgg16 import preprocess_input
from tensorflow.keras.layers import Flatten,Dense,Input
from tensorflow.keras.models import Model,Sequential
from keras import optimizers

对于图像,默认大小设置为224,224。

IMAGE_SIZE = [224,224]

可以使用ImageDataGenerator库,进行数据增强。数据增强也叫数据扩充,是为了增加数据集的大小。ImageDataGenerator根据给定的参数创建新图像,并将其用于训练(注意:当使用ImageDataGenerator时,原始数据将不用于训练)。

train_datagen = ImageDataGenerator(
rescale=1./255,
preprocessing_function=preprocess_input,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')

对于测试集也是这样:

test_datagen = ImageDataGenerator(rescale=1./255)

为了演示,我们直接使用VGG模型

vgg = VGG16(input_shape=IMAGE_SIZE+[3],weights='imagenet',include_top=False

然后冻结前面的层:

for layer in vgg.layers:
layer.trainable = False

最后我们加入自己的分类头:

x = Flatten()(vgg.output)
prediction = Dense(5,activation='softmax')(x)
model = Model(inputs=vgg.input, outputs=prediction)
model.summary()

模型是这样的:

训练

看看我们训练集:

train_set = train_datagen.flow_from_directory('DataSet/train',
target_size=(224,224),
batch_size=32,
class_mode='sparse')

验证集

val_set = train_datagen.flow_from_directory('DataSet/validation',
target_size=(224,224),
batch_size=32,
class_mode='sparse')

使用' sparse_categorical_crossentropy '损失,这样可以将标签编码为整数而不是独热编码。

from tensorflow.keras.metrics import MeanSquaredError
from tensorflow.keras.metrics import CategoricalAccuracy
adam = optimizers.Adam()
model.compile(loss='sparse_categorical_crossentropy',
optimizer=adam,
metrics=['accuracy',MeanSquaredError(name='val_loss'),CategoricalAccuracy(name='val_accuracy')])

然后就可以训练了:

from datetime import datetime
from keras.callbacks import ModelCheckpoint
log_dir = 'vg_log'
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir = log_dir)
start = datetime.now()
history = model.fit_generator(train_set,
validation_data=val_set,
epochs=100,
steps_per_epoch=len(train_set)// batch_size,
validation_steps=len(val_set)//batch_size,
callbacks=[tensorboard_callback],
verbose=1)
duration = datetime.now() - start
print("Time taken for training is ",duration)

模型训练了100次。得到了80%的验证准确率。f1得分为93%

预测

下面的函数将获取一个图像列表并根据该列表进行预测。

import numpy as np
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from scipy.ndimage import gaussian_filter
def print_classes(images,model):
classes = ['Drawing','Hentai','Neutral','Porn','Sexual']
fig, ax = plt.subplots(ncols=len(images), figsize=(20,20))
for idx,img in enumerate(images):
img = mpimg.imread(img)
resize = tf.image.resize(img,(224,224))
result = model.predict(np.expand_dims(resize/255,0))
result = np.argmax(result)
if classes[result] == 'Porn':
img = gaussian_filter(img, sigma=6)
elif classes[result] == 'Sexual':
img = gaussian_filter(img, sigma=6)
elif classes[result] == 'Hentai':
img = gaussian_filter(img, sigma=6)
ax[idx].imshow(img)
ax[idx].title.set_text(classes[result])
li = ['test1.jpeg','test2.jpeg','test3.jpeg','test4.jpeg','test5.jpeg']
print_classes(li,model)

看结果还是可以的。

最后,本文的源代码:

https://avoid.overfit.cn/post/8f681841d02e4a8db7bcf77926e123f1

作者:Nikhil Thalappalli

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
陈松伶瘦出新高度!减重30斤,面部线条棱角分明,53岁状态极好

陈松伶瘦出新高度!减重30斤,面部线条棱角分明,53岁状态极好

听栀子说
2024-06-20 21:44:44
台湾新任陆委会主管邱垂正:我们的祖先来自对岸,但我们只是华人

台湾新任陆委会主管邱垂正:我们的祖先来自对岸,但我们只是华人

小新历史
2024-04-29 17:28:45
济南一女子被读大学的儿子杀死,整整15分钟,她没有任何求救

济南一女子被读大学的儿子杀死,整整15分钟,她没有任何求救

纸鸢奇谭
2024-06-19 08:41:53
泰国未翻盘!日本女排半决赛胜巴西重返亚洲第一,中国还领先7分

泰国未翻盘!日本女排半决赛胜巴西重返亚洲第一,中国还领先7分

排球黄金眼
2024-06-21 03:13:29
广东落马厅官刘正让:边腐边升,后期却升不上去

广东落马厅官刘正让:边腐边升,后期却升不上去

大师兄爱写作
2024-06-20 00:38:06
国家第四次动员,买房你敢不敢跟?

国家第四次动员,买房你敢不敢跟?

米筐投资
2024-06-20 07:10:24
周深获奖风波升级,张杰亲下场发文内涵,官方解释搬石头砸自己脚

周深获奖风波升级,张杰亲下场发文内涵,官方解释搬石头砸自己脚

叶二娱评
2024-06-18 16:53:26
山东省公安厅原厅长孟庆丰逝世,享年91岁

山东省公安厅原厅长孟庆丰逝世,享年91岁

澎湃新闻
2024-06-20 18:34:26
中国女排完败日本,惠若琪指出输球原因,张常宁领衔二队铩羽而归

中国女排完败日本,惠若琪指出输球原因,张常宁领衔二队铩羽而归

海宝爱体育
2024-06-20 19:35:40
10年前神秘失踪的马航MH370发出了信号!失踪 事件之谜有望揭开

10年前神秘失踪的马航MH370发出了信号!失踪 事件之谜有望揭开

王二哥老搞笑
2024-06-20 21:43:15
赴陆参会后,连胜文回台报告,发现不对劲,赖清德突然成立委员会

赴陆参会后,连胜文回台报告,发现不对劲,赖清德突然成立委员会

小影的娱乐
2024-06-20 10:41:16
2024年高龄补贴开始发放,70周岁以上就能领取吗?每月有多少钱?

2024年高龄补贴开始发放,70周岁以上就能领取吗?每月有多少钱?

社保小达人
2024-04-30 09:35:33
上港迎来久违的6大强援助阵,本轮足协杯亮相首发,多条大鱼领衔

上港迎来久违的6大强援助阵,本轮足协杯亮相首发,多条大鱼领衔

罗掌柜体育
2024-06-20 20:22:59
6月19日俄乌:吕特将成北约新秘书长,海王星导弹致俄油库损巨大

6月19日俄乌:吕特将成北约新秘书长,海王星导弹致俄油库损巨大

山河路口
2024-06-19 16:57:15
乌克兰太凶残了!俄军空降师师长汽车被炸瞬间画面曝光

乌克兰太凶残了!俄军空降师师长汽车被炸瞬间画面曝光

亡海中的彼岸花
2024-06-19 10:15:22
知青往事:一件白的确良衬衫,是他一辈子对对父亲的亏欠

知青往事:一件白的确良衬衫,是他一辈子对对父亲的亏欠

草根情感故事茶社
2024-06-20 08:44:32
豪横!童瑶继子王政源购27万单车,穿骑行裤女性特征明显惹争议!

豪横!童瑶继子王政源购27万单车,穿骑行裤女性特征明显惹争议!

小咪侃娱圈
2024-06-19 11:43:42
【李霁野】鲁迅晚年幻灭,对中共说:你们来到,先杀的恐怕是我?

【李霁野】鲁迅晚年幻灭,对中共说:你们来到,先杀的恐怕是我?

年之父
2024-05-04 06:10:03
变态,但能恢复视力的 5 个小技巧

变态,但能恢复视力的 5 个小技巧

今日养生之道
2024-06-18 10:16:48
中央5台直播美洲杯时间表:CCTV直播阿根廷揭幕战吗?CCTV5节目表

中央5台直播美洲杯时间表:CCTV直播阿根廷揭幕战吗?CCTV5节目表

刺头体育
2024-06-21 03:33:02
2024-06-21 10:16:49
deephub
deephub
CV NLP和数据挖掘知识
1373文章数 1416关注度
往期回顾 全部

科技要闻

美媒:苹果正与百度阿里百川等谈AI合作

头条要闻

媒体:中国外交部刚批评美国 五角大楼就送来"神助攻"

头条要闻

媒体:中国外交部刚批评美国 五角大楼就送来"神助攻"

体育要闻

1-0"吊打"意大利 西班牙这就叫冠军相?

娱乐要闻

叶舒华参加柯震东生日聚会,五毒俱全

财经要闻

普华永道,引火烧身

汽车要闻

售价11.79-14.39万元 新一代哈弗H6正式上市

态度原创

本地
家居
房产
时尚
公开课

本地新闻

2024·合肥印象|用崭新视角对话城市发展

家居要闻

自然开放 实现灵动可变空间

房产要闻

海棠湾!一所重量级国际学校真的来了!

黑色的透视单品,就选这6件!

公开课

近视只是视力差?小心并发症

无障碍浏览 进入关怀版