노드의 얼굴 검사.녹슬고 WebAssembly가 있는 js

우리는 지난 문장에서 소개했다.본고는 어떻게 노드를 작성하는지 소개할 것이다.js 기반의 인공지능 즉 서비스 응용 프로그램.
오늘날 인공지능의 주류 프로그래밍 언어는 Python이다.그러나 웹 프로그래밍 언어는 JavaScript입니다.인공지능 기능을 웹 서비스로 제공하기 위해서는 인공지능 알고리즘을 자바스크립트, 특히 노드에 봉인해야 한다.js.
그러나 Python과 JavaScript 자체는 컴퓨팅 집약형 AI 응용 프로그램에 적합하지 않다.그것들은 고급 언어, 즉 속도가 느린 언어로 매우 무거운 운행을 가지고 있다.그것들의 용이성은 낮은 성능을 대가로 한다.Python은 원생 C/C++ 모듈에 인공지능 계산을 포장하여 이 문제를 해결한다.노드js도 이렇게 할 수 있지만, 우리는 더 좋은 방법이 있다. WebAssembly.
WebAssembly VM은 노드와 긴밀하게 통합됩니다.js 및 기타 JavaScript가 실행될 때그것들은 고성능, 메모리 안전, 기본 안전, 그리고 여러 운영체제의 이식성을 가지고 있다.그러나 우리의 방법은 WebAssembly와 본 컴퓨터 코드의 가장 좋은 특성을 결합시켰다.

작업 원리


노드js 기반의 인공지능 즉 서비스 응용 프로그램은 세 부분으로 구성된다.
  • 노드.js 응용 프로그램은 웹 서비스를 제공하고 웹 Assembly 함수를 호출하여 계산 집약형 작업, 예를 들어 인공지능 추리를 수행한다.
  • 데이터 준비, 후처리 및 기타 시스템과의 통합은 WebAssembly 기능으로 이루어진다.처음에 우리는 녹슨 것을 지지했다.응용 프로그램 개발자는 반드시 이 함수를 작성해야 한다.
  • 인공지능 모델의 실제 실행은 본 컴퓨터 코드로 완성하여 성능을 최대한 향상시킨다.코드의 이 부분은 매우 간단하고 안전성에 대해 심사를 진행했다.응용 프로그램 개발자는 WebAssembly 함수에서 이 프로그램을 호출하기만 하면 됩니다. 이것은 Python과 Node에서 이 함수를 사용하는 방식과 매우 비슷합니다.오늘

  • 이제 예를 하나 봅시다!

    얼굴 검사 예


    face detection web service 사용자가 사진을 업로드하고 녹색 상자에 표시된 모든 그림을 표시할 수 있습니다.

    The Rust source code for executing the MTCNN face detection model is based on Cetra's excellent tutorial: Face Detection with Tensorflow Rust. We made changes to make the Tensorflow library work in WebAssembly.



    Node.js application 파일 업로드와 응답을 처리합니다.
    app.post('/infer', function (req, res) {
      let image_file = req.files.image_file;
      var result_filename = uuidv4() + ".png";
    
      // Call the infer() function from WebAssembly (SSVM)
      var res = infer(req.body.detection_threshold, image_file.data);
    
      fs.writeFileSync("public/" + result_filename, res);
      res.send('<img src="' +  result_filename + '"/>');
    });
    
    보시다시피 JavaScript 프로그램은 이미지 데이터와 detection_threshold라는 매개 변수를 infer() 함수에 전달하기만 하면 됩니다. 이 매개 변수는 검출할 최소 얼굴을 지정하고 반환 값을 서버의 이미지 파일에 저장합니다.The infer() function는 Rust로 작성되었으며 JavaScript에서 호출할 수 있도록 WebAssembly로 컴파일되었습니다.infer() 함수는 입력한 이미지 데이터를 하나의 수조로 평평하게 합니다.그것은 장량 흐름 모델을 구축하고 평평한 이미지 데이터를 모델의 입력으로 사용한다.TensorFlow 모델은 각 프레임의 네 개의 각도에 대한 좌표를 나타내는 일련의 숫자를 반환합니다.infer() 함수는 각 면 주위에 녹색 상자를 그린 다음 수정된 이미지를 웹 서버의 PNG 파일에 저장합니다.
    #[wasm_bindgen]
    pub fn infer(detection_threshold: &str, image_data: &[u8]) -> Vec<u8> {
        let mut dt = detection_threshold;
        ... ...
        let mut img = image::load_from_memory(image_data).unwrap();
    
        // Run the tensorflow model using the face_detection_mtcnn native wrapper
        let mut cmd = Command::new("face_detection_mtcnn");
        // Pass in some arguments
        cmd.arg(img.width().to_string())
            .arg(img.height().to_string())
            .arg(dt);
        // The image bytes data is passed in via STDIN
        for (_x, _y, rgb) in img.pixels() {
            cmd.stdin_u8(rgb[2] as u8)
                .stdin_u8(rgb[1] as u8)
                .stdin_u8(rgb[0] as u8);
        }
        let out = cmd.output();
    
        // Draw boxes from the result JSON array
        let line = Pixel::from_slice(&[0, 255, 0, 0]);
        let stdout_json: Value = from_str(str::from_utf8(&out.stdout).expect("[]")).unwrap();
        let stdout_vec = stdout_json.as_array().unwrap();
        for i in 0..stdout_vec.len() {
            let xy = stdout_vec[i].as_array().unwrap();
            let x1: i32 = xy[0].as_f64().unwrap() as i32;
            let y1: i32 = xy[1].as_f64().unwrap() as i32;
            let x2: i32 = xy[2].as_f64().unwrap() as i32;
            let y2: i32 = xy[3].as_f64().unwrap() as i32;
            let rect = Rect::at(x1, y1).of_size((x2 - x1) as u32, (y2 - y1) as u32);
            draw_hollow_rect_mut(&mut img, rect, *line);
        }   
        let mut buf = Vec::new();
        // Write the result image into STDOUT
        img.write_to(&mut buf, image::ImageOutputFormat::Png).expect("Unable to write");
        return buf;
    }
    
    The face_detection_mtcnn command 기본 코드에서 MTCNN TensorFlow 모델을 실행합니다.이미지 너비, 이미지 높이, 검출 한도값 등 세 가지 파라미터가 필요합니다.RGB 값을 벤드펴기 위해 준비된 실제 이미지 데이터는 infer()를 통해 WebAssemblySTDIN에서 전송됩니다.모델의 결과는 JSON으로 인코딩되고 STDOUT 를 통해 반환됩니다.
    모델 매개 변수detection_thresholdmin_size인 모델 장량을 어떻게 전달하고 input 장량을 사용하여 입력 이미지 데이터를 전달하는지 주의하십시오.box 장량은 모델에서 결과를 검색하는 데 사용됩니다.
    fn main() -> Result<(), Box<dyn Error>> {
        // Get the arguments passed in from WebAssembly
        let args: Vec<String> = env::args().collect();
        let img_width: u64 = args[1].parse::<u64>().unwrap();
        let img_height: u64 = args[2].parse::<u64>().unwrap();
        let detection_threshold: f32 = args[3].parse::<f32>().unwrap();
        let mut buffer: Vec<u8> = Vec::new();
        let mut flattened: Vec<f32> = Vec::new();
    
        // The image bytes are read from STDIN
        io::stdin().read_to_end(&mut buffer)?;
        for num in buffer {
            flattened.push(num.into());
        }
    
        // Load up the graph as a byte array and create a tensorflow graph.
        let model = include_bytes!("mtcnn.pb");
        let mut graph = Graph::new();
        graph.import_graph_def(&*model, &ImportGraphDefOptions::new())?;
    
        let mut args = SessionRunArgs::new();
        // The `input` tensor expects BGR pixel data from the input image
        let input = Tensor::new(&[img_height, img_width, 3]).with_values(&flattened)?;
        args.add_feed(&graph.operation_by_name_required("input")?, 0, &input);
    
        // The `min_size` tensor takes the detection_threshold argument
        let min_size = Tensor::new(&[]).with_values(&[detection_threshold])?;
        args.add_feed(&graph.operation_by_name_required("min_size")?, 0, &min_size);
    
        // Default input params for the model
        let thresholds = Tensor::new(&[3]).with_values(&[0.6f32, 0.7f32, 0.7f32])?;
        args.add_feed(&graph.operation_by_name_required("thresholds")?, 0, &thresholds);
        let factor = Tensor::new(&[]).with_values(&[0.709f32])?;
        args.add_feed(&graph.operation_by_name_required("factor")?, 0, &factor);
    
        // Request the following outputs after the session runs.
        let bbox = args.request_fetch(&graph.operation_by_name_required("box")?, 0);
    
        let session = Session::new(&SessionOptions::new(), &graph)?;
        session.run(&mut args)?;
    
        // Get the bounding boxes
        let bbox_res: Tensor<f32> = args.fetch(bbox)?;
        let mut iter = 0;
        let mut json_vec: Vec<[f32; 4]> = Vec::new();
        while (iter * 4) < bbox_res.len() {
            json_vec.push([
                bbox_res[4 * iter + 1], // x1
                bbox_res[4 * iter],     // y1
                bbox_res[4 * iter + 3], // x2
                bbox_res[4 * iter + 2], // y2
            ]);
            iter += 1;
        }
        let json_obj = json!(json_vec);
        // Return result JSON in STDOUT
        println!("{}", json_obj.to_string()); 
        Ok(())
    }
    
    우리의 목표는 유니버설 인공지능 모델을 위해 개발자가 라이브러리로 사용할 수 있도록 본 기기의 실행 패키지를 만드는 것이다.

    배포 얼굴 검사 예


    사전 요구 사항으로 Rust, Node를 설치해야 합니다.js, Second State WebAssembly VMssvmup 도구.Check out the instruction 단계 또는 간단하게 Docker 이미지를 사용합니다.기계에 TensorFlow 라이브러리가 필요합니다.
    $ wget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
    $ sudo tar -C /usr/ -xzf libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
    
    얼굴 검사 예시를 배치하기 위해서 우리는 본 컴퓨터의 TensorFlow 모델 드라이버에서 시작합니다.this project 의 원본 코드에서 컴파일할 수 있습니다.
    # in the native_model_zoo/face_detection_mtcnn directory
    $ cargo install --path .
    
    다음으로 이동web application project.ssvmup 명령을 실행하여 Rust에서 WebAssembly 함수를 구축합니다.이 WebAssembly 함수는 웹 응용 프로그램의 데이터 실행 논리를 준비합니다.
    # in the nodejs/face_detection_service directory
    $ ssvmup build
    
    WebAssembly 함수를 구축한 후 노드를 시작할 수 있습니다.js 응용 프로그램.
    $ npm i express express-fileupload uuid
    
    $ cd node
    $ node server.js
    
    웹 서비스는 현재 컴퓨터의 8080 포트에서 사용할 수 있습니다.자신의 셀카나 가족 사진과 단체 사진을 사용해 보세요!

    TensorFlow 모형동물원


    원생 녹판 상자 face_detection_mtcnn 는 Tensor Flow 라이브러리 주변의 깨지기 쉬운 포장이다.이것은 훈련을 거친 TensorFlow 모델(동결 저장된 모델)을 불러와서 모델에 입력을 설정하고 모델을 실행하며 모델에서 출력 값을 읽어들입니다.
    사실 우리의 포장기는 검출된 면 주위의 테두리 좌표만 검색한다.이 모델은 실제로 검출된 모든 사람의 얼굴과 눈, 입, 코가 모든 사람의 얼굴에 있는 위치에 대해 신뢰 수준을 제공한다.패키지는 모델의 검색 장량 이름을 변경하여 이 정보를 얻고 WASM 함수로 되돌아갈 수 있습니다.
    다른 모델을 사용하고 싶다면, 이 예시를 따르고 자신의 모델을 위한 포장기를 만드는 것이 상당히 쉬울 것입니다.장량 이름의 입력과 출력, 그리고 그것들의 데이터 형식만 알면 된다.
    이 목표를 실현하기 위해 우리는 native model zoo라는 프로젝트를 창설하여 가능한 한 많은 TensorFlow모델을 위해 기존의 녹 방지지를 개발하였다.

    다음은 무엇입니까


    본고에서 우리는 어떻게 노드에서 진실한 인공지능을 서비스 용례로 실현하는지 보여 주었다.js는 Rust 및 WebAssembly를 사용합니다.우리의 방법은'모델 동물원'에 기여하기 위해 전체 지역사회에 틀을 제공했다. 이 동물원은 더 많은 응용 프로그램 개발자의 인공지능 라이브러리가 될 수 있다.
    다음 강좌에서 우리는 이미지 분류에 사용되는 또 다른 Tensor Flow 모델을 되돌아보고 전체 종류의 유사한 모델을 지원하기 위해 포장기를 확장하는 방법을 보여 드리겠습니다.

    좋은 웹페이지 즐겨찾기