人究竟可以懒到什么程度

文章目录

临近春节,愈发不想干活了,心里只期待着早点放假…

公司最近布置了个任务,给每个人发了几千张图片,要求把每张图片的人脸标注出来。做深度学习的童鞋可能会有了解,标注这个过程就是用 LabelMe 这个软件一直做一些重复的机械劳动。懒如我,标了几张就觉得麻烦了,然后用 rust 写了个脚本实现标注完自动切换。脚本很简单,就是设置了触发后按照一定顺序自动帮你按下几个按键。

 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
use std::{thread::sleep, time::Duration};

use inputbot::{*, KeybdKey::*, MouseButton::*};
use inputbot::BlockInput::{Block, DontBlock};

fn main() {
    const SLEEP_TIME: u64 = 50;
    println!("按鼠标侧键触发自动切换");
    X2Button.bind(|| {
        LeftButton.press();
        LeftButton.release();
        sleep(Duration::from_millis(SLEEP_TIME));
        EnterKey.press();
        EnterKey.release();
        sleep(Duration::from_millis(SLEEP_TIME));
        EnterKey.press();
        EnterKey.release();
        sleep(Duration::from_millis(SLEEP_TIME));
        DKey.press();
        DKey.release();
        sleep(Duration::from_millis(SLEEP_TIME));
        EnterKey.press();
        EnterKey.release();
        sleep(Duration::from_millis(SLEEP_TIME));
        EnterKey.press();
        EnterKey.release();
        sleep(Duration::from_millis(SLEEP_TIME));
        EnterKey.press();
        EnterKey.release();
    });
    handle_input_events();
}

用了这个脚本后,标注的时间的确大大减小了,我也就这么标了1000张,但是想到后面还有几千张,我吐了。为什么不做一个自动标注工具呢?说干就干,Let’s Roll~

分析了一下 LabelMe 的标注结果,其实就是标完点后生成了一个记录标的点的位置的 json 文件。因此,我们可以使用第三方人脸识别sdk来实现人脸检测,并把检测到的人脸坐标生成标注信息存储在 json 文件里,就大功告成了。

以下是整个过程核心方法的具体实现。通过这个工具,几千个标注瞬间干完了,省下的大把时间,又可以用来愉快的摸鱼了,奥里给!

 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
fun generateJsonFiles(path: String) {
    val libDir = File("Win64")
    val faceEngine = FaceEngine(libDir.absolutePath)
    var errorCode = faceEngine.activeOnline(
        "yourAppId",
        "yourSdkKey"
    )
    if (errorCode != ErrorInfo.MOK.value && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.value) {
        println("引擎激活失败")
        return
    } else {
        println("引擎激活成功")
    }

    //引擎配置
    val engineConfiguration = EngineConfiguration()
    engineConfiguration.detectMode = DetectMode.ASF_DETECT_MODE_IMAGE
    engineConfiguration.detectFaceOrientPriority = DetectOrient.ASF_OP_ALL_OUT
    engineConfiguration.detectFaceMaxNum = 10
    engineConfiguration.detectFaceScaleVal = 16
    //功能配置
    val functionConfiguration = FunctionConfiguration()
    functionConfiguration.isSupportFaceDetect = true
    functionConfiguration.isSupportFaceRecognition = true
    engineConfiguration.functionConfiguration = functionConfiguration

    //初始化引擎
    errorCode = faceEngine.init(engineConfiguration)

    if (errorCode != ErrorInfo.MOK.value) {
        println("初始化引擎失败")
        return
    } else {
        println("初始化引擎成功")
    }
    val fileTree = File(path).walk().maxDepth(1)
    fileTree.filter { it.isFile && it.extension == "jpg" }
        .forEach { imageFile ->
            val imageInfo = ImageFactory.getRGBData(imageFile)
            val faceInfoList = ArrayList<FaceInfo>()
            faceEngine.detectFaces(
                imageInfo.imageData,
                imageInfo.width,
                imageInfo.height,
                imageInfo.imageFormat,
                faceInfoList
            )
            if (faceInfoList.isNotEmpty()) {
                val faces = mutableListOf<FloatArray>()
                for (faceInfo in faceInfoList) {
                    //在此处微调人脸框大小
                    faces.add(floatArrayOf(faceInfo.rect.left.toFloat() + 10, faceInfo.rect.top.toFloat() - 10))
                    faces.add(floatArrayOf(faceInfo.rect.right.toFloat() - 10, faceInfo.rect.bottom.toFloat() + 5))
                }
                val imageData = encodeToBase64(imageFile.absolutePath)
                val label = Label(
                    shapes = listOf(Shape(points = faces)),
                    imageData = imageData,
                    imagePath = imageFile.name
                )
                val json = jsonAdapter.toJson(label)
                File(imageFile.parent, imageFile.nameWithoutExtension + ".json").writeText(json)
                println("已处理${imageFile.name}")
            } else {
                println("未检测到人脸,跳过${imageFile.name}")
            }
        }
}

评论正在加载中...如果评论较长时间无法加载,你可以 搜索对应的 issue 或者 新建一个 issue