ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
face_follow_image.c
Go to the documentation of this file.
4#include <math.h>
5
18
20 if (!context)
21 return;
22 image_destroy(context->output);
23 context->output = NULL;
24 SAFE_FREE(context);
25}
26
28 int max_width, int max_height) {
29 if (!source || source->w <= 0 || source->h <= 0)
30 return source;
31 if (!*context && !enabled && !debug)
32 return source;
33 if (!*context) {
34 *context = SAFE_CALLOC(1, sizeof(face_follow_image_t), face_follow_image_t *);
35 if (!*context)
36 return source;
37 face_follow_init(&(*context)->state);
38 }
39 face_follow_image_t *ctx = *context;
40 if (source->w != ctx->source_width || source->h != ctx->source_height) {
42 ctx->last_detection = -1;
43 ctx->source_width = source->w;
44 ctx->source_height = source->h;
45 }
46 if ((enabled || debug) && now - ctx->last_detection >= 0.1) {
47 float scale = fminf((float)FACE_FOLLOW_DETECT_WIDTH / source->w, (float)FACE_FOLLOW_DETECT_HEIGHT / source->h);
48 int width = (int)fmaxf(1, source->w * scale), height = (int)fmaxf(1, source->h * scale);
49 for (int y = 0; y < height; y++) {
50 for (int x = 0; x < width; x++) {
51 rgb_pixel_t p = source->pixels[(size_t)(y * source->h / height) * source->w + x * source->w / width];
52 size_t offset = ((size_t)y * width + x) * 3;
53 ctx->bgr[offset] = p.b;
54 ctx->bgr[offset + 1] = p.g;
55 ctx->bgr[offset + 2] = p.r;
56 }
57 }
59 size_t count;
61 face_follow_observe(&ctx->state, faces, count, now);
62 ctx->last_detection = now;
63 }
64 face_follow_tick(&ctx->state, now, enabled);
65 if (!enabled && !debug && ctx->state.crop.w == 1)
66 return source;
67 // Keep output geometry stable while bounding the cost of high-resolution cameras.
68 float output_scale = fminf(1, fminf((float)max_width / source->w, (float)max_height / source->h));
69 int output_width = (int)fmaxf(1, source->w * output_scale);
70 int output_height = (int)fmaxf(1, source->h * output_scale);
71 if (!ctx->output || ctx->output->w != output_width || ctx->output->h != output_height) {
73 ctx->output = image_new(output_width, output_height);
74 if (!ctx->output)
75 return source;
76 }
77 face_follow_rect_t crop = ctx->state.crop;
78 face_follow_rect_t face = ctx->state.face;
79 float side = fmaxf(face.w * source->w, face.h * source->h);
80 float fx = (face.x + face.w * 0.5f) * source->w, fy = (face.y + face.h * 0.5f) * source->h;
81 float thickness = 2 * fmaxf(3, source->w * crop.w / 90);
82 for (int y = 0; y < output_height; y++) {
83 int sy = (int)fminf(source->h - 1, (crop.y + (float)y / output_height * crop.h) * source->h);
84 for (int x = 0; x < output_width; x++) {
85 int sx = (int)fminf(source->w - 1, (crop.x + (float)x / output_width * crop.w) * source->w);
86 rgb_pixel_t p = source->pixels[(size_t)sy * source->w + sx];
87 if (debug && ctx->state.detected && now - ctx->state.last_seen < 0.3) {
88 float dx = fabsf(sx - fx), dy = fabsf(sy - fy);
89 if ((fabsf(dx - side * 0.5f) < thickness && dy <= side * 0.5f + thickness) ||
90 (fabsf(dy - side * 0.5f) < thickness && dx <= side * 0.5f + thickness))
91 p = (rgb_pixel_t){255, 0, 0};
92 }
93 ctx->output->pixels[(size_t)y * output_width + x] = p;
94 }
95 }
96 return ctx->output;
97}
Synchronized per-thread pending error stacks and value snapshots. SET_ERRNO pushes,...
void face_follow_detect(unsigned char *results, unsigned char *bgr, int width, int height, face_follow_detection_t *faces, size_t capacity, size_t *count)
void face_follow_tick(face_follow_state_t *state, double now, bool enabled)
void face_follow_init(face_follow_state_t *state)
Definition face_follow.c:13
void face_follow_observe(face_follow_state_t *state, const face_follow_detection_t *faces, size_t count, double now)
Definition face_follow.c:25
#define FACE_FOLLOW_RESULT_BUFFER_SIZE
Definition face_follow.h:6
#define FACE_FOLLOW_DETECT_HEIGHT
Definition face_follow.h:5
#define FACE_FOLLOW_DETECT_WIDTH
Definition face_follow.h:4
#define FACE_FOLLOW_MAX_DETECTIONS
Definition face_follow.h:7
image_t * face_follow_image_process(face_follow_image_t **context, image_t *source, double now, bool enabled, bool debug, int max_width, int max_height)
void face_follow_image_destroy(face_follow_image_t *context)
struct face_follow_image face_follow_image_t
audio_visualization_source_t source
Definition fft.c:24
unsigned int height
Definition fft.c:23
unsigned int width
Definition fft.c:23
bool enabled
Is filtering active?
Definition grep.c:62
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
void image_destroy(image_t *image)
Destroy an image allocated with image_new().
image_t * image_new(size_t width, size_t height)
Create a new image with standard allocation.
🔢 Mathematical Utility Functions
face follow image is intentionally a small, concrete record. Fields such as state,...
face_follow_state_t state
unsigned char results[FACE_FOLLOW_RESULT_BUFFER_SIZE]
unsigned char bgr[FACE_FOLLOW_DETECT_WIDTH *FACE_FOLLOW_DETECT_HEIGHT *3]
When code needs to work with face follow detection, it keeps box, confidence here instead of scatteri...
Definition face_follow.h:23
face follow state keeps the values that move through the subsystem: crop, target, face,...
Definition face_follow.h:36
face_follow_rect_t crop
Definition face_follow.h:37
face_follow_rect_t face
Definition face_follow.h:37
SIMD-friendly storage for one RGB pixel. r, g, and b hold the color channels and padding keeps the la...
int w
Image width in pixels (must be > 0).
int h
Image height in pixels (must be > 0).
rgb_pixel_t * pixels
Pixel data array (width * height RGB pixels, row-major order).
uint8_t b
Blue color component (0-255).
uint8_t g
Green color component (0-255).
uint8_t r
Red color component (0-255).