Skip to main content

drawFaces

warning

The document is a continuation of the previous document, if you have landed directly on this page then, Please read from page Get started.

What is drawFaces component ?

drawFaces component is used to draw face data(detected faces information) on face image.

  • Description : drawFaces() takes an input(through STDIN) as image in base64 format, and detected faces information(bounding boxes, probability and 5 landmarks)(inputJson) and returns base64 string with drawn values on image(outputJson). Check Input and output parameters for details.
  • Parameters :
    • Input(Via STDIN) : drawFaces.stdin() << inputJson << std::endl;
      • An inputJson String with following parameters:
        • Parameter1: For each detected face
          • Bounding box co-ordinates
          • Probability being face
          • 5 Landmarks co-ordinates values
        • Parameter2: Original image in base64 string format
    • Output(Via STDOUT) : drawFaces.stdout() >> outputJson;
      • A outputJson string with following contents
        • Base64 image string with drawn landmarks, bounding boxes and probability
        • int requestID
  • Using drawFaces component
    • With our detectFaces component: To understand how to use drawFaces with detectFaces component, check this section
    • You can also use drawFaces with any other detectFaces component but inputJson for drawFaces should be in the format of outputJson of detectFaces component.

List of drawFaces features in shunya stack

  1. Get Image with drawn face detections

Using drawFaces

Requirements to use drawFaces

  1. Shunya OS installed (supported Arm devices) or Shunya OS docker container (X86 based windows/linux devices)
  2. Shunya AI installed in Shunya OS.

Steps to use drawFaces

  1. Read inputJson.
  2. Call API binary
  3. Store the image with drawn faceInfo
note

Run the steps given below inside Shunya OS installed (supported Arm devices) or Shunya OS docker container (X86 based windows/linux devices) terminals.

Lets take an example use case: Say we need to

  1. Give detected faces information as as input in JSON file
  2. Get JSON output of all the detected faces drawn on image.

Steps are

Step 1. Read inputJson.

  1. Start with an ready to use template for drawing faces on image.

    git clone https://gitlab.iotiot.in/repo-public/examples.git
  2. Open the examples in a text editor and modify as per your usecase.

    • For CPP you will find the examples in the folder shunya-ai-examples/indiv-components/cpp-examples/face-detection/drawFaces
    • Open the file draw_faces.cpp
    • Modify the line to set the input json filename.
    • IMP Note: inputJsonRaw.json file contains the parameter1 and parameter2 of input. If you want to see how it looks you can check below.
    /* Reading the json file and convert it into the Json string format */
    std::ifstream ifs { R"(inputJsonRaw.json)" };
    if ( !ifs.is_open() )
    {
    std::cerr << "Could not open file for reading!\n";
    return EXIT_FAILURE;
    }
    IStreamWrapper isw { ifs };

    Document doc {};
    doc.ParseStream( isw );

    StringBuffer buffer {};
    Writer<StringBuffer> writer { buffer };
    doc.Accept( writer );

    if ( doc.HasParseError() )
    {
    std::cout << "Error : " << doc.GetParseError() << '\n'
    << "Offset : " << doc.GetErrorOffset() << '\n';
    return EXIT_FAILURE;
    }
    /* Finally we get inputJson string */
    const std::string inputJson { buffer.GetString() };

Step 2. Call API binary

  1. We will now call API binary by giving input image(parameter1) and face info(parameter2) as an input through STDIN.
    /*########### Call drawFaces Component ###############*/
    subprocess::popen drawFaces("/usr/bin/drawFaces", {});
    /* Passing inputJson to the API */
    drawFaces.stdin() << inputJson << std::endl;
    drawFaces.close();
    std::string drawFacesOut;
    /* Getting output in outputJson */
    drawFaces.stdout() >> outputJson;
  2. You will get output in outputJson string.

Step 3. Store the image with drawn faceInfo

  1. Code to print the json output, got from drawFaces API.
    /* ---- Parse outputJson  ---- */
    rapidjson::Document drawFaceOutJSON = readJsonString(outputJson);
    std::string b64Img(drawFaceOutJSON["data"]["image"].GetString(),
    drawFaceOutJSON["data"]["image"].GetStringLength());
    cv::Mat image = base642Mat(b64Img);
    /* Storing image with draw drawnFace.jpg in system */
    cv::imwrite("drawnFace.jpg",image);

Run ready to use example.

  1. Run example by yourself.

    mkdir build && cd build
    cmake ../
    make
    # before running drawFacesCpp make sure you have inputJsonRaw.json in build directory
    ./drawFacesCpp
  2. Running the codes will print the JSON output on the terminal (to STDOUT).

    For Example:

    • Lets say the input image is

      Oops!, No Image to display.
    • Input JSON containing face data is

      {
      "apiVersion":"1.2.0",
      "requestId":1617287578,
      "data":{
      "faces":[{
      "faceId":"face0",
      "boundingBox":{
      "top":40.26805877685547,
      "left":222.78062438964845,
      "width":121.15028381347656,
      "height":163.424560546875
      },
      "confidence":0.9954631924629211,
      "landmarks":[{
      "type":"pupilLeft",
      "x":255.1230926513672,
      "y":104.38592529296875
      },
      {
      "type":"pupilRight",
      "x":310.427734375,
      "y":94.43948364257813
      },
      {
      "type":"noseTip",
      "x":288.96661376953127,
      "y":122.54252624511719
      },
      {
      "type":"mouthLeft",
      "x":265.7955017089844,
      "y":161.14794921875
      },
      {
      "type":"mouthRight",
      "x":314.17901611328127,
      "y":152.65420532226563
      }]
      }],
      "image": "/e98239u9r93ynm9rfumu02398r8umc9ejmrc8ew0r374y8uhmcwe,=="
      }
      }
    • Then the JSON output is

      {
      "apiVersion": "1.2.0",
      "requestId": 1606318527,
      "data": {
      "image": "lkdn=sdfsdfin/slnsfd"
      }
      }

Understand this component with an example (ready to use code)

  • This is an example for face-detection and here we will be using 2 components: detectFaces and drawFaces

  • Check this ready to use example in c++

  • Download the code

    git clone https://gitlab.iotiot.in/repo-public/examples.git
    cd example/shunya-ai-examples/cpp-examples/face-detection
  • In this folder there is a file, face_detect.cpp

  • Using video component for capturing images from video

    /* --- Capturing image from video using Video component --- */
    captureObj src = newCaptureDevice("video-source"); /* Create capture Instance */
    cv::Mat inputImage;
    int32_t outIndex = 0;

    /*################## Call Video Component functions ################*/
    inputImage = captureFrameToMem(&src); /* Capture one frame at a time in a loop*/

    if (inputImage.empty()) {
    fprintf(stderr, "End of video file!.");
    closeCapture(&src);
    return 0;
    }
  • Using detectFace component

    /* ---- Create Input JSON ---- */
    std::string b64InpImg = mat2Base64(inputImage);
    rapidjson::Document inputJson;
    inputJson.SetObject();
    rapidjson::Value inpImage;

    /* Set face detection probability */
    float probability = 0.8;

    inpImage.SetString(b64InpImg.c_str(), strlen(b64InpImg.c_str()), inputJson.GetAllocator());
    inputJson.AddMember("inputImage", inpImage, inputJson.GetAllocator());
    inputJson.AddMember("probability", probability, inputJson.GetAllocator());
    /*################## Call detectFaces Component ################*/
    subprocess::popen detectFaces("/usr/bin/detectFaces", {});
    detectFaces.stdin() << jsonDoc2Text(inputJson) << std::endl;
    detectFaces.close();
    std::string detectFacesOut;
    detectFaces.stdout() >> detectFacesOut;

  • Using drawFaces component

    rapidjson::Document detectFacesJson = readJsonString(detectFacesOut);
    if (detectFacesJson.HasMember("data")) {
    rapidjson::Value &results = detectFacesJson["data"]["faces"];
    assert(results.IsArray());
    if(results.Size()>0){
    /* Reading from json file and add it in the structure */
    for (rapidjson::SizeType i = 0; i < results.Size(); i++) {
    // calling drawFaces
    rapidjson::Value &drawFacesjson = detectFacesJson["data"];
    rapidjson::Document inDrawface;
    inDrawface.SetObject();
    inDrawface.AddMember("data",drawFacesjson,inDrawface.GetAllocator());
    subprocess::popen drawFace("/usr/bin/drawFaces", {});
    //std::cout<<"\nprinting drawFace input: "<<jsonDoc2Text(inDrawface);
    drawFace.stdin() << jsonDoc2Text(inDrawface) << std::endl;
    drawFace.close();
    std::string drawFaceOut;
    drawFace.stdout() >> drawFaceOut;
    //std::cout<<"drawFaceOutput:"<<drawFaceOut;
    rapidjson::Document drawFaceOutJSON = readJsonString(drawFaceOut);
    std::string b64Img(drawFaceOutJSON["data"]["image"].GetString(),
    drawFaceOutJSON["data"]["image"].GetStringLength());
    cv::Mat image = base642Mat(b64Img);
    cv::imwrite("drawnFace.jpg",image);
    std::cout<<"\nImage Stored !";
    }
    }
    else{
    std::cout<<"\nThere is no data member in json";
    }
  • Run code by yourself

    mkdir build && cd build
    cmake .. && make
    ./faceDetectCpp
    • You will get a new image stored in system.
    Oops!, No Image to display.

Facing errors with the component?