CoreFlow 1.0.0
A modern orchestration and execution runtime
Loading...
Searching...
No Matches
skinToneDetector.cpp

Skin Tone Detector Sample.

Skin Tone Detector Sample

Version
0.1
Date
2025-09-03
#include <string>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
#include <VX/vx.h>
using namespace cv;
using namespace std;
#define ERROR_CHECK_STATUS(status) \
{ \
vx_status status_ = (status); \
if (status_ != VX_SUCCESS) \
{ \
printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
exit(1); \
} \
}
#define ERROR_CHECK_OBJECT(obj) \
{ \
vx_status status_ = vxGetStatus((vx_reference)(obj)); \
if (status_ != VX_SUCCESS) \
{ \
printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
exit(1); \
} \
}
static void VX_CALLBACK log_callback(vx_context context, vx_reference ref, vx_status status,
const vx_char string[])
{
(void)context;
(void)ref;
(void)status;
size_t len = strlen(string);
if (len > 0)
{
printf("%s", string);
if (string[len - 1] != '\n') printf("\n");
fflush(stdout);
}
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf(
"Usage:\n"
"./skinToneDetect --image <imageName>\n"
"./skinToneDetect --live \n");
return 0;
}
// set image height & width
int width = 720, height = 480;
// create OpenVX context
vxRegisterLogCallback(context, log_callback, vx_false_e);
// create OpenVX Graph using the created context
vx_graph graph = vxCreateGraph(context);
// create input & output images
vx_image input_rgb_image = vxCreateImage(context, width, height, VX_DF_IMAGE_RGB);
vx_image output_skinTone_image = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);
ERROR_CHECK_OBJECT(input_rgb_image);
ERROR_CHECK_OBJECT(output_skinTone_image);
// create intermediate images which are not accessed by the user to be mem optimized
vx_image R_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image G_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image B_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image RmG_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image RmB_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image R95_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image G40_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image B20_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image RmG15_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image RmB0_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image and1_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image and2_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
vx_image and3_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
ERROR_CHECK_OBJECT(RmG_image);
ERROR_CHECK_OBJECT(RmB_image);
ERROR_CHECK_OBJECT(R95_image);
ERROR_CHECK_OBJECT(G40_image);
ERROR_CHECK_OBJECT(B20_image);
ERROR_CHECK_OBJECT(RmG15_image);
ERROR_CHECK_OBJECT(RmB0_image);
ERROR_CHECK_OBJECT(and1_image);
ERROR_CHECK_OBJECT(and2_image);
ERROR_CHECK_OBJECT(and3_image);
// create threshold values
vx_int32 thresValue95 = 95;
sizeof(vx_int32));
ERROR_CHECK_OBJECT(thresh95);
vx_int32 thresValue40 = 40;
sizeof(vx_int32));
ERROR_CHECK_OBJECT(thresh40);
vx_int32 thresValue20 = 20;
sizeof(vx_int32));
ERROR_CHECK_OBJECT(thresh20);
vx_int32 thresValue15 = 15;
sizeof(vx_int32));
ERROR_CHECK_OBJECT(thresh15);
vx_int32 thresValue0 = 0;
// add nodes to the graph
vx_node nodes[] = {
// extract R,G,B channels and compute R-G and R-B
vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_R, R_image),
vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_G, G_image),
vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_B, B_image),
vxSubtractNode(graph, R_image, G_image, VX_CONVERT_POLICY_SATURATE, RmG_image),
vxSubtractNode(graph, R_image, B_image, VX_CONVERT_POLICY_SATURATE, RmB_image),
// compute threshold
vxThresholdNode(graph, R_image, thresh95, R95_image),
vxThresholdNode(graph, G_image, thresh40, G40_image),
vxThresholdNode(graph, B_image, thresh20, B20_image),
vxThresholdNode(graph, RmG_image, thresh15, RmG15_image),
vxThresholdNode(graph, RmB_image, thresh0, RmB0_image),
// aggregate all thresholded values to produce SKIN pixels
vxAndNode(graph, R95_image, G40_image, and1_image),
vxAndNode(graph, and1_image, B20_image, and2_image),
vxAndNode(graph, RmG15_image, RmB0_image, and3_image),
vxAndNode(graph, and2_image, and3_image, output_skinTone_image)};
for (vx_size i = 0; i < sizeof(nodes) / sizeof(nodes[0]); i++)
{
ERROR_CHECK_OBJECT(nodes[i]);
}
// verify graph
string option = argv[1];
Mat input, input_rgb;
cv::namedWindow("VX SkinTone Detect", cv::WINDOW_GUI_EXPANDED);
if (option == "--image")
{
string imageLocation = argv[2];
input = imread(imageLocation.c_str());
if (input.empty())
{
printf("Image not found\n");
return -1;
}
resize(input, input, Size(width, height));
cvtColor(input, input_rgb, COLOR_BGR2RGB);
imshow("inputWindow", input);
vx_rectangle_t cv_rgb_image_region;
cv_rgb_image_region.start_x = 0;
cv_rgb_image_region.start_y = 0;
cv_rgb_image_region.end_x = width;
cv_rgb_image_region.end_y = height;
vx_imagepatch_addressing_t cv_rgb_image_layout{};
cv_rgb_image_layout.dim_x = input_rgb.cols;
cv_rgb_image_layout.dim_y = input_rgb.rows;
cv_rgb_image_layout.stride_x = input_rgb.elemSize();
cv_rgb_image_layout.stride_y = input_rgb.step;
vx_uint8 *cv_rgb_image_buffer = input_rgb.data;
ERROR_CHECK_STATUS(vxCopyImagePatch(input_rgb_image, &cv_rgb_image_region, 0,
&cv_rgb_image_layout, cv_rgb_image_buffer,
vx_rectangle_t rect = {0, 0, (vx_uint32)width, (vx_uint32)height};
vx_map_id map_id;
void *ptr;
ERROR_CHECK_STATUS(vxMapImagePatch(output_skinTone_image, &rect, 0, &map_id, &addr, &ptr,
Mat mat(height, width, CV_8U, ptr, addr.stride_y);
imshow("VX SkinTone Detect", mat);
waitKey(0);
ERROR_CHECK_STATUS(vxUnmapImagePatch(output_skinTone_image, map_id));
}
else if (option == "--live")
{
VideoCapture cap(0);
if (!cap.isOpened())
{
printf("Unable to open camera\n");
return -1;
}
for (;;)
{
cap >> input;
resize(input, input, Size(width, height));
cvtColor(input, input_rgb, COLOR_BGR2RGB);
imshow("inputWindow", input);
if (waitKey(30) >= 0) break;
vx_rectangle_t cv_rgb_image_region;
cv_rgb_image_region.start_x = 0;
cv_rgb_image_region.start_y = 0;
cv_rgb_image_region.end_x = width;
cv_rgb_image_region.end_y = height;
vx_imagepatch_addressing_t cv_rgb_image_layout;
cv_rgb_image_layout.stride_x = 3;
cv_rgb_image_layout.stride_y = input_rgb.step;
vx_uint8 *cv_rgb_image_buffer = input_rgb.data;
ERROR_CHECK_STATUS(vxCopyImagePatch(input_rgb_image, &cv_rgb_image_region, 0,
&cv_rgb_image_layout, cv_rgb_image_buffer,
vx_rectangle_t rect = {0, 0, (vx_uint32)width, (vx_uint32)height};
vx_map_id map_id;
void *ptr;
ERROR_CHECK_STATUS(vxMapImagePatch(output_skinTone_image, &rect, 0, &map_id, &addr,
Mat mat(height, width, CV_8U, ptr, addr.stride_y);
imshow("VX SkinTone Detect", mat);
if (waitKey(30) >= 0) break;
ERROR_CHECK_STATUS(vxUnmapImagePatch(output_skinTone_image, map_id));
}
}
else
{
printf(
"Usage:\n"
"./skinToneDetect --image <imageName>\n"
"./skinToneDetect --live \n");
return -1;
}
// release objects
for (vx_size i = 0; i < sizeof(nodes) / sizeof(nodes[0]); i++)
{
}
ERROR_CHECK_STATUS(vxReleaseImage(&input_rgb_image));
ERROR_CHECK_STATUS(vxReleaseImage(&output_skinTone_image));
return 0;
}
int main()
Definition blur_pipeline.cpp:15
#define ERROR_CHECK_OBJECT(obj)
Definition bubble_pop.cpp:28
#define ERROR_CHECK_STATUS(status)
Definition bubble_pop.cpp:20
uint32_t vx_uint32
A 32-bit unsigned value.
Definition vx_types.h:85
size_t vx_size
A wrapper of size_t to keep the naming convention uniform.
Definition vx_types.h:186
vx_enum vx_status
A formal status type with known fixed size.
Definition vx_types.h:550
int32_t vx_int32
A 32-bit signed value.
Definition vx_types.h:105
struct _vx_rectangle_t vx_rectangle_t
The rectangle data structure that is shared with the users. The area of the rectangle can be computed...
char vx_char
An 8 bit ASCII character.
Definition vx_types.h:70
uint8_t vx_uint8
An 8-bit unsigned value.
Definition vx_types.h:75
#define VX_CALLBACK
Defines calling convention for user callbacks.
Definition vx_types.h:63
@ VX_DF_IMAGE_RGB
A single plane of 24-bit pixel as 3 interleaved 8-bit units of R then G then B data....
Definition vx_types.h:816
@ VX_DF_IMAGE_U8
A single plane of unsigned 8-bit data. The range of data is not specified, as it may be extracted fro...
Definition vx_types.h:855
@ vx_false_e
The "false" value.
Definition vx_types.h:404
@ VX_TYPE_UINT8
A vx_uint8.
Definition vx_types.h:437
@ VX_CONVERT_POLICY_SATURATE
Results are saturated to the bit depth of the output operand.
Definition vx_types.h:803
@ VX_CHANNEL_B
Use to extract the BLUE channel, no matter the byte or packing order.
Definition vx_types.h:1319
@ VX_CHANNEL_G
Use to extract the GREEN channel, no matter the byte or packing order.
Definition vx_types.h:1317
@ VX_CHANNEL_R
Use to extract the RED channel, no matter the byte or packing order.
Definition vx_types.h:1315
struct Context * vx_context
An opaque reference to the implementation context.
Definition vx_types.h:274
VX_API_ENTRY vx_context VX_API_CALL vxCreateContext(void)
Creates a vx_context.
VX_API_ENTRY vx_status VX_API_CALL vxReleaseContext(vx_context *context)
Releases the OpenVX object context.
@ VX_READ_ONLY
The memory shall be treated by the system as if it were read-only. If the User writes to this memory,...
Definition vx_types.h:1515
@ VX_WRITE_ONLY
The memory shall be treated by the system as if it were write-only. If the User reads from this memor...
Definition vx_types.h:1519
@ VX_MEMORY_TYPE_HOST
The default memory type to import from the Host.
Definition vx_types.h:1338
VX_API_ENTRY vx_status VX_API_CALL vxVerifyGraph(vx_graph graph)
Verifies the state of the graph before it is executed. This is useful to catch programmer errors and ...
VX_API_ENTRY vx_status VX_API_CALL vxReleaseGraph(vx_graph *graph)
Releases a reference to a graph. The object may not be garbage collected until its total reference co...
VX_API_ENTRY vx_graph VX_API_CALL vxCreateGraph(vx_context context)
Creates an empty graph.
struct Graph * vx_graph
An opaque reference to a graph.
Definition vx_types.h:263
VX_API_ENTRY vx_status VX_API_CALL vxProcessGraph(vx_graph graph)
This function causes the synchronous processing of a graph. If the graph has not been verified,...
VX_API_ENTRY vx_image VX_API_CALL vxCreateVirtualImage(vx_graph graph, vx_uint32 width, vx_uint32 height, vx_df_image color)
Creates an opaque reference to an image buffer with no direct user access. This function allows setti...
struct _vx_imagepatch_addressing_t vx_imagepatch_addressing_t
The addressing image patch structure is used by the Host only to address pixels in an image patch....
VX_API_ENTRY vx_status VX_API_CALL vxUnmapImagePatch(vx_image image, vx_map_id map_id)
Unmap and commit potential changes to a image object patch that were previously mapped....
VX_API_ENTRY vx_status VX_API_CALL vxMapImagePatch(vx_image image, const vx_rectangle_t *rect, vx_uint32 plane_index, vx_map_id *map_id, vx_imagepatch_addressing_t *addr, void **ptr, vx_enum usage, vx_enum mem_type, vx_uint32 flags)
Allows the application to get direct access to a rectangular patch of an image object plane.
struct Image * vx_image
An opaque reference to an image.
Definition vx_types.h:219
VX_API_ENTRY vx_status VX_API_CALL vxReleaseImage(vx_image *image)
Releases a reference to an image object. The object may not be garbage collected until its total refe...
uintptr_t vx_map_id
Holds the address of a variable where the map/unmap functions return a map identifier.
Definition vx_types.h:196
VX_API_ENTRY vx_status VX_API_CALL vxCopyImagePatch(vx_image image, const vx_rectangle_t *image_rect, vx_uint32 image_plane_index, const vx_imagepatch_addressing_t *user_addr, void *user_ptr, vx_enum usage, vx_enum user_mem_type)
Allows the application to copy a rectangular patch from/into an image object plane.
VX_API_ENTRY vx_image VX_API_CALL vxCreateImage(vx_context context, vx_uint32 width, vx_uint32 height, vx_df_image color)
Creates an opaque reference to an image buffer.
@ VX_NOGAP_X
No Gap.
Definition vx_types.h:1969
VX_API_ENTRY void VX_API_CALL vxRegisterLogCallback(vx_context context, vx_log_callback_f callback, vx_bool reentrant)
Registers a callback facility to the OpenVX implementation to receive error logs.
struct Node * vx_node
An opaque reference to a kernel node.
Definition vx_types.h:253
VX_API_ENTRY vx_status VX_API_CALL vxReleaseNode(vx_node *node)
Releases a reference to a Node object. The object may not be garbage collected until its total refere...
VX_API_ENTRY vx_status VX_API_CALL vxSetThresholdAttribute(vx_threshold thresh, vx_enum attribute, const void *ptr, vx_size size)
Sets attributes on the threshold object.
struct Threshold * vx_threshold
The Threshold Object. A thresholding object contains the types and limit values of the thresholding r...
Definition vx_types.h:338
VX_API_ENTRY vx_status VX_API_CALL vxReleaseThreshold(vx_threshold *thresh)
Releases a reference to a threshold object. The object may not be garbage collected until its total r...
@ VX_THRESHOLD_TYPE_BINARY
A threshold with only 1 value.
Definition vx_types.h:1165
VX_API_ENTRY vx_node VX_API_CALL vxAndNode(vx_graph graph, vx_image in1, vx_image in2, vx_image out)
[Graph] Creates a bitwise AND node.
VX_API_ENTRY vx_node VX_API_CALL vxChannelExtractNode(vx_graph graph, vx_image input, vx_enum channel, vx_image output)
[Graph] Creates a channel extract node.
VX_API_ENTRY vx_node VX_API_CALL vxSubtractNode(vx_graph graph, vx_image in1, vx_image in2, vx_enum policy, vx_image out)
[Graph] Creates an arithmetic subtraction node.
VX_API_ENTRY vx_node VX_API_CALL vxThresholdNode(vx_graph graph, vx_image input, vx_threshold thresh, vx_image output)
[Graph] Creates a Threshold node and returns a reference to it.
vx_int32 stride_y
Stride in Y dimension in bytes.
Definition vx_types.h:1644
vx_int32 stride_x
Stride in X dimension in bytes.
Definition vx_types.h:1643
vx_uint32 start_x
The Start X coordinate.
Definition vx_types.h:1771
vx_uint32 start_y
The Start Y coordinate.
Definition vx_types.h:1772
vx_uint32 end_y
The End Y coordinate.
Definition vx_types.h:1774
vx_uint32 end_x
The End X coordinate.
Definition vx_types.h:1773
The top level OpenVX Header.
#define VX_THRESHOLD_THRESHOLD_VALUE
Definition vx_compatibility.h:156
VX_API_ENTRY vx_threshold VX_API_CALL vxCreateThreshold(vx_context c, vx_enum thresh_type, vx_enum data_type)
struct Reference * vx_reference
Definition vx_types.h:173