Python:使用opennsfw2对图片/视频进行鉴黄识别

简介使用雅虎开源的 TensorFlow 2 Open-NSFW 模型,NSFW:not safe for work,工作场所不宜

实践1.环境准备,Python 3.7 及以上,安装 opennsfw2 库。图片素材请参考 小结中地址进行下载。

代码语言:javascript代码运行次数:0运行复制pip install opennsfw22.代码实践图片识别 代码如下:

代码语言:javascript代码运行次数:0运行复制import opennsfw2 as n2

# 将自动下载预训练模型 open_nsfw_weights.h5 到 C:\Users\Administrator\.opennsfw2\weights

# pip install opennsfw2

# 单张预测

image_path = '1.jpg'

nsfw_probability = n2.predict_image(image_path)

print(nsfw_probability)

# 0.16282974183559418

# 批量预测

image_paths = ['1.jpg', '2.jpg']

nsfw_probabilities = n2.predict_images(image_paths)

print(nsfw_probabilities)

# [0.16282965242862701, 0.8638442158699036]视频识别 代码如下:

代码语言:javascript代码运行次数:0运行复制import opennsfw2 as n2

video_path = '1.mp4'

elapsed_seconds, nsfw_probabilities = n2.predict_video_frames(video_path)

for second, probability in zip(elapsed_seconds, nsfw_probabilities):

print(f'{second:.2f}s: {probability * 100:.0f} %')

# 0.03s: 1%

# ...

# 10.01s: 87.00%

# ...

# 10.64s: 69.00%高级用法1. 加载的方式代码语言:javascript代码运行次数:0运行复制import numpy as np

from PIL import Image

from opennsfw2._model import make_open_nsfw_model

from opennsfw2._image import preprocess_image, Preprocessing

image_path = '1.jpg'

image = preprocess_image(Image.open(image_path), Preprocessing.YAHOO)

model = make_open_nsfw_model()

nsfw_probability = float(model.predict(np.expand_dims(image, 0), batch_size=1)[0][1])

print(nsfw_probability)

# 0.162829741835594182.车速检测代码语言:javascript代码运行次数:0运行复制import time

import numpy as np

import tkinter as tk

from pathlib import Path

from tkinter import filedialog

from tkinter import messagebox

from PIL import ImageTk, Image

from opennsfw2._model import make_open_nsfw_model

from opennsfw2._image import preprocess_image, Preprocessing

begin = time.time()

model = make_open_nsfw_model() # 加载模型

elapsed = time.time() - begin # 加载模型耗时

initialdir = Path.cwd() # 初始化目录,可切换为图片Path.home() / 'Pictures'

img = None # 当前打开的图片

def scale(size, width=None, height=None):

"""获取按比例缩放后的宽高"""

if not width and not height:

width, height = size

if not width or not height:

_width, _height = size

height = width * _height / _width if width else height

width = height * _width / _height if height else width

return int(width), int(height)

def img_resize(event=None):

"""显示图片"""

global img

if img:

_img = img.resize(scale(img.size, height=win.winfo_height()))

_img = ImageTk.PhotoImage(_img)

label.config(image=_img)

label.image = _img

def on_closing():

"""关闭事件"""

if messagebox.askokcancel('关闭', '是否退出程序?'):

win.destroy()

def open_file(event=None):

"""打开图片"""

global initialdir

global img

file_path = filedialog.askopenfilename(title='选择图片', initialdir=initialdir,

filetypes=[('image files', ('.png', '.jpg', '.jpeg', '.gif'))])

if file_path:

statusbar.config(text='正在加载...')

statusbar.update_idletasks()

begin = time.time()

path = Path(file_path)

initialdir = path.parent

img = Image.open(file_path)

img_resize()

_img = preprocess_image(Image.open(file_path), Preprocessing.YAHOO)

probability = float(model.predict(np.expand_dims(_img, 0), batch_size=1)[0][1])

print(probability)

end = time.time()

statusbar.config(text=f'{path.name} 耗时: {end - begin:.2f}s 概率: {probability * 100:.2f} %')

win = tk.Tk()

win.title('黄图检测') # 标题

menu = tk.Menu(win)

menu.add_command(label='打开', command=open_file)

win.config(menu=menu)

win.bind('', img_resize)

win.geometry('600x300+300+300')

win.minsize(200, 200)

win.protocol('WM_DELETE_WINDOW', on_closing)

statusbar = tk.Label(win, text=f'加载模型耗时: {elapsed:.2f}s', bd=1, relief=tk.SUNKEN, anchor=tk.W, name='statusbar')

statusbar.pack(side=tk.BOTTOM, fill=tk.X)

label = tk.Label(win, text='双击打开图片')

label.bind('', open_file)

label.pack(fill=tk.BOTH, expand=True)

win.mainloop()3. 视频车速检测(无声)代码语言:javascript代码运行次数:0运行复制import time

import threading

import tkinter as tk

from pathlib import Path

from tkinter import filedialog

from tkinter import messagebox

from timeit import default_timer as timer

import imageio

import numpy as np

from PIL import ImageTk, Image

from opennsfw2._model import make_open_nsfw_model

from opennsfw2._image import preprocess_image, Preprocessing

# pip install imageio-ffmpeg

begin = time.time()

model = make_open_nsfw_model() # 加载模型

elapsed = time.time() - begin # 加载模型耗时

initialdir = Path.cwd() # 初始化目录,可切换为图片Path.home() / 'Pictures'

reader = None # 视频读取器

accum_time = 0

curr_fps = 0

last_fps = 0

prev_time = timer()

def on_closing():

"""关闭事件"""

if messagebox.askokcancel('关闭', '是否退出程序?'):

win.destroy()

def play():

global reader

global prev_time, accum_time, curr_fps

for image in reader:

image = Image.fromarray(image)

frame_image = ImageTk.PhotoImage(image)

label.config(image=frame_image)

label.image = frame_image

_img = preprocess_image(image, Preprocessing.YAHOO)

probability = float(model.predict(np.expand_dims(_img, 0), batch_size=1)[0][1])

# FPS

curr_time = timer()

exec_time = curr_time - prev_time

prev_time = curr_time

accum_time = accum_time + exec_time

curr_fps = curr_fps + 1

if accum_time > 1:

accum_time = accum_time - 1

last_fps = curr_fps

curr_fps = 0

statusbar.config(text=f'概率: {probability * 100:.2f} % FPS: {last_fps}')

def open_file(event=None):

"""打开视频"""

global initialdir

global reader

file_path = filedialog.askopenfilename(title='选择视频', initialdir=initialdir,

filetypes=[('Select files', ('.mp4', '.mkv', '.avi', '.wmv'))])

if file_path:

statusbar.config(text='正在加载...')

statusbar.update_idletasks()

path = Path(file_path)

initialdir = path.parent

reader = imageio.get_reader(path)

thread = threading.Thread(target=play, daemon=True)

thread.start()

win = tk.Tk()

win.title('黄图检测') # 标题

menu = tk.Menu(win)

menu.add_command(label='打开', command=open_file)

win.config(menu=menu)

win.geometry('1280x720+300+300')

win.minsize(200, 200)

win.protocol('WM_DELETE_WINDOW', on_closing)

statusbar = tk.Label(win, text=f'加载模型耗时: {elapsed:.2f}s', bd=1, relief=tk.SUNKEN, anchor=tk.W, name='statusbar')

statusbar.pack(side=tk.BOTTOM, fill=tk.X)

label = tk.Label(win, text='双击打开视频')

label.bind('', open_file)

label.pack(fill=tk.BOTH, expand=True)

win.mainloop()4. 视频车速检测(有声)代码语言:javascript代码运行次数:0运行复制import io

import pyglet

import numpy as np

from PIL import Image

from opennsfw2._model import make_open_nsfw_model

from opennsfw2._image import preprocess_image, Preprocessing

# pip install pyglet

model = make_open_nsfw_model()

filename = '1.mp4'

source = pyglet.media.load(filename)

video_format = source.video_format

width, height = video_format.width, video_format.height

title = 'Video Player'

window = pyglet.window.Window(width, height, title)

player = pyglet.media.Player()

player.queue(source)

player.play()

@window.event

def on_draw():

window.clear()

if player.source and player.source.video_format:

player.get_texture().blit(0, 0, width=width, height=height)

image_data = player.get_texture().get_image_data()

pitch = -(image_data.width * len('RGB'))

data = image_data.get_data('RGB', pitch)

_img = preprocess_image(Image.frombytes('RGB', (width, height), data, 'raw'), Preprocessing.YAHOO)

probability = float(model.predict(np.expand_dims(_img, 0), batch_size=1)[0][1])

print(probability)

pyglet.app.run()运行结果:

代码语言:javascript代码运行次数:0运行复制效率分析:

get_data() 0.941 s

frombytes() 0.001 s

preprocess_image() 0.006 s

predict() 0.052 s小结参考: https://blog.csdn.net/lly1122334/article/details/121247781

https://github.com/bhky/opennsfw2

资源: https://img-blog.csdnimg.cn/20210702231858370.jpg

http://www.lenna.org/full/len_full.jpg