前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python:使用opennsfw2对图片/视频进行鉴黄识别

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

作者头像
Freedom123
发布2024-03-29 14:20:33
1960
发布2024-03-29 14:20:33
举报
文章被收录于专栏:DevOpsDevOps

简介

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

实践

1.环境准备,

Python 3.7 及以上,安装 opennsfw2 库。图片素材请参考 小结中地址进行下载。

代码语言:javascript
复制
pip install opennsfw2
2.代码实践

图片识别 代码如下:

代码语言:javascript
复制
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
复制
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
复制
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.16282974183559418
2.车速检测
代码语言:javascript
复制
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('<Configure>', 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('<Double-Button-1>', open_file)
label.pack(fill=tk.BOTH, expand=True)
win.mainloop()
3. 视频车速检测(无声)
代码语言:javascript
复制
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('<Double-Button-1>', open_file)
label.pack(fill=tk.BOTH, expand=True)
win.mainloop()
4. 视频车速检测(有声)
代码语言:javascript
复制
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
复制
效率分析:
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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-12-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 实践
    • 1.环境准备,
      • 2.代码实践
      • 高级用法
        • 1. 加载的方式
          • 2.车速检测
            • 3. 视频车速检测(无声)
              • 4. 视频车速检测(有声)
              • 小结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档