java 違規圖片、視頻自動識別(色情、血腥、暴力)

最近工作上有需要,需要對用戶上傳的圖片和視頻做違規自動識別,網上當然有各種大廠的接口可以調用,但是由於項目的特殊性,不能使用外網,所以只有自己弄了。

查詢資料,網上都是各種python的文章,也測試過一些,由於我對python不是很熟悉,各種環境依賴沒整明白,考慮到後期還要上線到服務器,如果環境這麼複雜,可能對現場實施人員不太友好。

後續找到有spring的包:open-nsfw-spring-boot-starter,提供了違規圖片的識別。

我的方案目前是:

1、圖片違規識別直接使用三方工具。

2、視頻違規識別,首先按幀截圖,保存爲圖片,再是御用圖片的識別方式。

這種方案缺點就是使用過程中對文件IO開銷比較大,但是目前也找不到其他方案了,下面上代碼。

 

1、maven引用工具包

 

<dependency>
       <groupId>com.ruibty.nsfw</groupId>
       <artifactId>open-nsfw-spring-boot-starter</artifactId>
      <version>1.0</version>
</dependency>

2、視頻文件抽幀處理,我這裏用的是ffmpeg,可自行替換。我這裏使用的是直接執行commond命令,因爲ffmpeg不支持多線程,所以這裏做了限制。

/**
     * 視頻文件幀處理
     *
     * @param filePath 幀文件保存地址
     * @return
     */
    public synchronized static String videoFrame(String filePath) {
        boolean exists = Files.exists(Paths.get(filePath));
        Assert.isTrue(exists, "原文件不存在!");
        Path path = Paths.get(filePath);
        // 文件名
        String fileName = path.getFileName().toString();
        int dotIndex = fileName.lastIndexOf('.');
        String fileNameWithoutExtension = dotIndex == -1 ? fileName : fileName.substring(0, dotIndex);
        Path parentPath = path.getParent();
        // 父級文件夾
        String parentDirPath = parentPath == null ? "" : parentPath.toString();
        // 使用文件名創建一個文件夾,準備存幀文件
        String frameFilePath = parentDirPath + "/" + fileNameWithoutExtension + "_" + "video_frame";
        File tsDir = new File(frameFilePath);
        if (!tsDir.exists()) {
            Assert.isTrue(tsDir.mkdirs(), "生成幀文件目錄出錯,生成目錄:" + frameFilePath);
        }
        StringBuilder command = new StringBuilder();
        command.append(LeenledaConfig.getFfmpegPath());
        command.append(" ffmpeg ");
        command.append(" -i ");
        command.append(filePath);
        command.append(" -vf \"fps=1/3\" -qscale:v 2 ");
        command.append(frameFilePath);
        command.append("/video_frm_%05d.jpg");
        try {
            if (!executeCommandBatch(command.toString())) {
                return null;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return frameFilePath;
    }

3、執行cmmond命令方法

/**
     * 批量命令執行,等待返回結果
     *
     * @param cmd
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    private static boolean executeCommandBatch(String cmd) throws IOException, InterruptedException {
        System.out.println(cmd);
        Process p = Runtime.getRuntime().exec(cmd);
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            String readLine = br.readLine();
            StringBuilder builder = new StringBuilder();
            while (readLine != null) {
                readLine = br.readLine();
                builder.append(readLine + "\n");
            }
            p.waitFor();
            int i = p.exitValue();
            if (i == 0) {
                System.out.println(builder);
                return true;
            } else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (br != null) {
                br.close();
            }
        }
    }

3、違規圖片識別方法

/**
     * 圖片違規處理 僅支持單線程調用
     *
     * @param filePath 文件目錄
     */
    public synchronized void violationIdentificationByDyFile(Long fileId, String filePath) {
        boolean flagViolation = false;
        Path path = Paths.get(filePath);
        byte[] imageBytes = null;
        try {
            imageBytes = Files.readAllBytes(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
        float prediction = nsfwService.getPrediction(imageBytes);
        if (prediction >= MAXPREDICTION) {
            flagViolation = true;
        }
        if (flagViolation) {
            // 違規文件
           
        } else {
            // 文件未違規
           
        }
    }

4、MAXPREDICTION是我定義的一個靜態變量,prediction 是係數,一般來說,0.8以上的文件都屬於違規了。

5、違規審覈需要結合人工,因爲有些情況下會誤判定,不能全靠自動識別。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章