Tensorflow直播视频流鉴黄 完整项目
效果展示
这是一个GIF图片,图片较大,请耐心等待。
黄色字体显示的是sexy类别的,蓝色、绿色代表视频没有问题,红色代表色情,表示视频有问题。
效果展示的完整MP4文件在项目的show目录中。可以下载查看更长时间的视频播放。
项目说明
项目的大部分内容在《Tensorflow图片鉴黄 完整项目》中进行了说明,这里就不重复说明了。视频鉴黄和图片鉴黄最大的区别就是数据源的不同,但原理还是相同的,就是在图片鉴黄的基础上添加一个对视频的抽帧处理,抽出的帧变成图片,然后再对图片鉴黄。简单吧。
项目搭建
由于要对视频流进行鉴黄,需要自行搭建一个视频服务器,《
利用nginx搭建RTMP视频点播、直播、HLS服务器》这篇博文,我对如何搭建直播服务器进行了说明,如何搭建测试服务器,只需要搭建到点播服务器那里就可以了。
项目使用说明
项目里的两个重要文件:
TFServer.py这个是Tensorflow服务,用于对图片打分。打的分数就是GIF文件上显示的百分数的分值。
CVMonitor.py 他的功能就是同时打开9路直播流,对这9路直播流进行抽帧,将帧转化成图片发给TFServer,并获取分值,并显示在视频上面。如图所示:
其实后台可以对成百上千个直播流进行分析,这里显示9个就是为了展示,并没有啥特别的。或者将可疑的跳到前台显示,没问题的依旧留着后台。
代码讲解
这是对程序员最感兴趣的地方了,TFServer.py在图片鉴黄里说过了,这里只讲解CVMonitor
import cv2
import time
import numpy as np
import os
import socket
from threading import Thread
#用于控制线程的停止
threadStop = False
#我的屏幕分辨率,这里是写死的了,没有动态获取。
windowHigh = 1080
windowWidth = 1920
#我用来测试的直播地址,都是localhost开头的,证明我在本地搭建的服务器。
videoList = ['rtmp://localhost/vod/sample1.mp4',
'rtmp://localhost/vod/sample2.mp4',
'rtmp://localhost/vod/sample3.mp4',
'rtmp://localhost/vod/sample4.mp4',
'rtmp://localhost/vod/sample5.mp4',
'rtmp://localhost/vod/sample9.mp4',
'rtmp://localhost/vod/sample6.mp4',
'rtmp://localhost/vod/sample7.mp4',
'rtmp://localhost/vod/sample8.mp4']
def getVideoURL(num):
return videoList[num]
#同时监控显示9路视频流,每个视频流是一个线程。
class MonitorThread(Thread):
def __init__(self, name, args):
super().__init__()
self.name = name
self.args = args
self.cameraCapture = cv2.VideoCapture(getVideoURL(self.args))
print('Thread : ' + str(self.args) + ', ' + self.name + ' start')
def run(self):
while threadStop is not True:
success, frame = self.cameraCapture.read()
fileFullName = 'pic/' + str(self.args) + '.jpg'
cv2.imwrite(fileFullName, frame)
time.sleep(0.1)
#创建sock链接,用于将抽帧的图片发给Tensorflow服务器。
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.connect("/tmp/tfserver.sock")
client.send(bytes(fileFullName, 'utf-8'))
#等待获取打分结果。
resultbyte = client.recv(1024)
resultStr = str(resultbyte, encoding="utf-8")
splitString = resultStr.split('\n')
#获得的打分,我只要第一个。因为第一个分值是最高的。
print('aaaaaaaaaaaaaaaaaaaaaaaaa : ' + splitString[0])
img = cv2.imread(fileFullName)
img_w = (int)(windowWidth/3)
img_h = (int)(windowHigh/3)
print(img_w, img_h)
#对抽出的帧,做缩放,适合同时在一个屏幕中显示这9路视频流。
reSize = cv2.resize(img, (img_w, img_h), interpolation=cv2.INTER_CUBIC)
#这里根据分值的不同,显示不同的颜色
if(splitString[0].startswith('porn')):
cv2.putText(reSize, splitString[0], (30, 60), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 0, 255), 1)
elif(splitString[0].startswith('neutral')):
cv2.putText(reSize, splitString[0], (30, 60), cv2.FONT_HERSHEY_TRIPLEX, 1, (255, 0, 0), 1)
elif(splitString[0].startswith('sexy')):
cv2.putText(reSize, splitString[0], (30, 60), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 255, 255), 1)
else:
cv2.putText(reSize, splitString[0], (30, 60), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 255, 0), 1)
board_x = (int)(self.args/3)
board_y = self.args%3
start_x = board_x*img_h
start_y = board_y*img_w
print(self.args, board_x, board_y, start_x, start_y, img_w, img_h)
#现在显示到屏幕上的不同区域上。
bgrImage[start_x:start_x+img_h, start_y:start_y+img_w] = reSize
print('Tread : ' + str(self.args) + ', ' + self.name + ' stop')
#生成一个比较大的画板,用于绘制这9路视频。
randomByteArray = bytearray(os.urandom(windowWidth*windowHigh*3))
flatNumpyArray = np.array(randomByteArray)
bgrImage = flatNumpyArray.reshape(windowHigh, windowWidth, 3)
#创建9个线性,每个线程去读取一个直播流。
for i in range(9):
t = MonitorThread(name='monitor', args=(i))
t.start()
cv2.namedWindow('image', cv2.WINDOW_FULLSCREEN)
#cv2.setWindowProperty('image', cv2.)
while True:
if cv2.waitKey(1) == 27:
break
#这里就是每隔0.1秒显示一次画板。
time.sleep(0.1)
cv2.imshow('image', bgrImage)
#标注线程结束,线程停止循环读取数据。
threadStop = True
#销毁窗口。
cv2.destroyAllWindows()
代码量还是挺小的。我没有说清楚的,请给我留言。