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:
- Create a
ProcessingBlock
object.
ProcessingBlock processingBlock = service.CreateProcessingBlock
(
new()
{
{ "unit_type", "<Block type>" },
{ "modification", "<Modification>" },
{ "version", <Version> }
}
);
- Read an image from a file.
byte[] imageData = File.ReadAllBytes(imagePath);
- Create
Context
Context data = service.CreateContextFromImage(imageData);
- Call
Invoke
method ofProcessingBlock
processingBlock.Invoke(data);
- 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}");
}