zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

Tensorflow直播视频流鉴黄 完整项目

直播项目 完整 Tensorflow 视频流
2023-09-11 14:14:26 时间

《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(windowWidthwindowHigh3))
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()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118

代码量还是挺小的。我没有说清楚的,请给我留言。