Skip to main content
Version: 3.22.2

Processing Block

Requirements

  • Added links to the library FacerecCSharpWrapper.dll and OpenCvSharp4

Create a processing block

The ProcessingBlock object is used for face detection and image quality assessment. Block type Modification

The sequence of actions when using the ProcessingBlock object:

  1. Create a ProcessingBlock object.
ProcessingBlock processingBlock = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "<Block type>" },
{ "modification", "<Modification>" },
{ "version", <Version> }
}
);
  1. Read an image from a file.
byte[] imageData = File.ReadAllBytes(imagePath);
  1. Create Context
Context data = service.CreateContextFromImage(imageData);
  1. Call Invoke method of ProcessingBlock
processingBlock.Invoke(data);
  1. Output data is in data["objects"]
Data usage example

Getting the coordinates of the top left and bottom right bbox points

for (int i = 0; i < (int)objects.Length(); i++)
{
Context obj = objects[i];
Context bbox = obj["bbox"];

// Top left bbox point
double x1 = bbox[0].GetDouble() * <image width>;
double y1 = bbox[1].GetDouble() * <image height>;

// Bottom right bbox point
double x2 = bbox[2].GetDouble() * <image width>;
double y2 = bbox[3].GetDouble() * <image height>;
}

1. Create a ProcessingBlock FaceDetector

FaceDetector is used to detect faces in an image.

ProcessingBlock faceDetector = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_DETECTOR" },
{ "modification", "uld" },
{ "precision_level", 3 }
}
);

2. Create a ProcessingBlock FaceFitter

FaceFitter is used to find key points of faces in an image For some ProcessingBlocks to work, you need to use the combination FaceDetector + FaceFitter

ProcessingBlock fitter = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_FITTER" },
{ "modification", "tddfa" }
}
);

3. Verification (1:1)

FaceTemplateExtractor is used to extract the face template VerificationModule is used for 1:1 verification

static Context ExtractTemplates(string imagePath, FacerecService service, List<ProcessingBlock> pipeline)
{
byte[] imageData = File.ReadAllBytes(imagePath);

Context data = service.CreateContextFromImage(imageData);

foreach (ProcessingBlock processingBlock in pipeline)
{
processingBlock.Invoke(data);
}

return data;
}

static void Main(string[] args)
{
FacerecService service = FacerecService.createService
(
"<Path to /conf/facerec>",
"<Path to /license>"
);
string firstImagePath = "<Path to first image>";
string secondImagePath = "<Path to second image>";

ProcessingBlock faceDetector = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_DETECTOR" },
{ "modification", "uld" },
{ "precision_level", 3 }
}
);
ProcessingBlock faceFitter = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_FITTER" },
{ "modification", "tddfa" }
}
);
ProcessingBlock faceTemplateExtractor = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_TEMPLATE_EXTRACTOR" },
{ "modification", "1000" }
}
);
ProcessingBlock verificationModule = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "VERIFICATION_MODULE" },
{ "modification", "1000" }
}
);

List<ProcessingBlock> pipeline = [
faceDetector,
faceFitter,
faceTemplateExtractor
];

Context first = ExtractTemplates(firstImagePath, service, pipeline);
Context second = ExtractTemplates(secondImagePath, service, pipeline);

Context verificationData = service.CreateContext
(
new Dictionary<object, object>
{
{ "template1", first["objects"][0]["template"] },
{ "template2", second["objects"][0]["template"] }
}
);

verificationModule.Invoke(verificationData);

double distance = verificationData["result"]["distance"].GetDouble();
double score = verificationData["result"]["score"].GetDouble();
double far = verificationData["result"]["far"].GetDouble();
double frr = verificationData["result"]["frr"].GetDouble();

Console.WriteLine($"Verification result\ndistance: {distance}\nscore: {score}\nfar: {far}\nfrr: {frr}");
}

4. Identification (1:N)

FaceTemplateExtractor is used to extract the face template. TemplateIndex is used to search for templates. MatcherModule is used for 1:N identification.

static Context ExtractTemplates(string imagePath, FacerecService service, List<ProcessingBlock> pipeline)
{
byte[] imageData = File.ReadAllBytes(imagePath);

Context data = service.CreateContextFromImage(imageData);

foreach (ProcessingBlock processingBlock in pipeline)
{
processingBlock.Invoke(data);
}

return data;
}

static void Main(string[] args)
{
FacerecService service = FacerecService.createService
(
"<Path to /conf/facerec>",
"<Path to /license>"
);
string firstImagePath = "<Path to first image>";
string secondImagePath = "<Path to second image>";

ProcessingBlock faceDetector = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_DETECTOR" },
{ "modification", "uld" },
{ "precision_level", 3 }
}
);
ProcessingBlock faceFitter = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_FITTER" },
{ "modification", "tddfa" }
}
);
ProcessingBlock faceTemplateExtractor = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "FACE_TEMPLATE_EXTRACTOR" },
{ "modification", "1000" }
}
);
ProcessingBlock templateIndex = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "TEMPLATE_INDEX" },
{ "modification", "1000" }
}
);
ProcessingBlock matcherModule = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "MATCHER_MODULE" },
{ "modification", "1000" }
}
);
Context templates = service.CreateContext(new());

List<ProcessingBlock> pipeline = [
faceDetector,
faceFitter,
faceTemplateExtractor
];

Context first = ExtractTemplates(firstImagePath, service, pipeline);
Context second = ExtractTemplates(secondImagePath, service, pipeline);

for (int i = 0; i < (int)second["objects"].Length(); i++)
{
templates.PushBack(second["objects"][i]["template"]);
}

second["templates"] = templates;

templateIndex.Invoke(second);

Context matcherData = service.CreateContext
(
new Dictionary<object, object>
{
{ "knn", 1 },
{ "template_index", second["template_index"] },
{ "queries", new List<object> { first["objects"][0] } }
}
);

matcherModule.Invoke(matcherData);

long findIndex = matcherData["results"][0]["index"].GetLong();
double distance = matcherData["results"][0]["distance"].GetDouble();
double score = matcherData["results"][0]["score"].GetDouble();

Console.WriteLine($"Identify result\ndistance: {distance}\nscore: {score}\nindex: {findIndex}");
}