/* * Copyright (C) 2019 Hertz Wang 1989wanghang@163.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see http://www.gnu.org/licenses * * Any non-GPL usage of this software or parts of this software is strictly * forbidden. * */ #include "rockx_draw.h" #include #include "npu_pp_output.h" #if HAVE_ROCKX #include #endif namespace NPU_UVC_ROCKX_DEMO { static SDLFont fga_sdl_font(red, 40); bool RockxFaceGenderAgeDraw(SDL_Renderer *renderer, const SDL_Rect &render_rect, const SDL_Rect &coor_rect, int rotate, NPUPostProcessOutput *output, void *buffer, Uint32 sdl_fmt) { SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(renderer, 0xFF, 0x10, 0xEB, 0xFF); int npu_w = output->npuwh.width; int npu_h = output->npuwh.height; char gender_age[32] = {0}; static const char *man = "Gender: Man, Age:"; static const char *women = "Gender: Women, Age:"; auto face = (struct aligned_rockx_face_gender_age *)(output->pp_output); for (uint32_t i = 0; i < output->count; i++) { assert(sizeof(float) == 4); float score; auto fga = face + i; memcpy(&score, fga->score, 4); if (score < 0.85) continue; snprintf(gender_age, sizeof(gender_age), "%s %d", fga->gender ? man : women, (int)fga->age); int x1 = fga->left; int y1 = fga->top; int x2 = fga->right; int y2 = fga->bottom; SDL_Rect rect = {x1 * render_rect.w / npu_w + render_rect.x, y1 * render_rect.h / npu_h + render_rect.y, (x2 - x1) * render_rect.w / npu_w, (y2 - y1) * render_rect.h / npu_h}; rect = transform(rect, coor_rect, rotate); int status = draw_rect(renderer, &rect, buffer, sdl_fmt); if (status) fprintf(stderr, "draw rect status: %d <%s>\n", status, SDL_GetError()); int fontw = 0, fonth = 0; SDL_Surface *str = fga_sdl_font.GetFontPicture( gender_age, strlen(gender_age), 32, &fontw, &fonth); if (str) { SDL_Rect texture_dimension; SDL_Texture *texture = load_texture(str, renderer, &texture_dimension); SDL_FreeSurface(str); SDL_Rect dst_dimension; switch (rotate) { case 0: dst_dimension.x = rect.x; dst_dimension.y = rect.y - 36; break; case 90: dst_dimension.x = rect.x + rect.w + texture_dimension.h / 2 - texture_dimension.w / 2; dst_dimension.y = rect.y + rect.h / 2 - texture_dimension.h / 2; break; default: fprintf(stderr, "TODO: rotate=%d\n", rotate); dst_dimension.x = rect.x; dst_dimension.y = rect.y; break; } dst_dimension.w = texture_dimension.w; dst_dimension.h = texture_dimension.h; SDL_RenderCopyEx(renderer, texture, &texture_dimension, &dst_dimension, rotate, NULL, SDL_FLIP_NONE); SDL_DestroyTexture(texture); } } return true; } bool RockxFaceDetectDraw(SDL_Renderer *renderer, const SDL_Rect &render_rect, const SDL_Rect &coor_rect, int rotate, NPUPostProcessOutput *output, void *buffer, Uint32 sdl_fmt) { SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(renderer, 0xFF, 0x10, 0xEB, 0xFF); int npu_w = output->npuwh.width; int npu_h = output->npuwh.height; auto fr = (struct aligned_rockx_face_rect *)(output->pp_output); for (uint32_t i = 0; i < output->count; i++) { assert(sizeof(float) == 4); float score; auto face = fr + i; memcpy(&score, face->score, 4); if (score < FACEDETECT_SCROE_THRESHOLD) { fprintf(stderr, "%s %d, ****************************************face score %f\n", __FUNCTION__, __LINE__, score); continue; } int x1 = face->left; int y1 = face->top; int x2 = face->right; int y2 = face->bottom; SDL_Rect rect = {x1 * render_rect.w / npu_w + render_rect.x, y1 * render_rect.h / npu_h + render_rect.y, (x2 - x1) * render_rect.w / npu_w, (y2 - y1) * render_rect.h / npu_h}; // fprintf(stderr, "%s %d, face left top right bottom [%d %d %d %d] score // %f\n",__FUNCTION__,__LINE__, // x1, y1, x2, y2, score); rect = transform(rect, coor_rect, rotate); int status = draw_rect(renderer, &rect, buffer, sdl_fmt); if (status) fprintf(stderr, "draw rect status: %d <%s>\n", status, SDL_GetError()); } return true; } bool RockxFaceLandMarkDraw(SDL_Renderer *renderer, const SDL_Rect &render_rect, const SDL_Rect &coor_rect, int rotate, NPUPostProcessOutput *output, void *buffer, Uint32 sdl_fmt) { SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(renderer, 0xEE, 0x00, 0x00, 0xFF); int npu_w = output->npuwh.width; int npu_h = output->npuwh.height; auto face_landmark = static_cast(output->pp_output); for (uint32_t i = 0; i < output->count; i++) { SDL_Point *points = new SDL_Point[68]{}; rockx_face_landmark_t *rockx_face_landmark = face_landmark[i].marks; for (int j = 0; j < rockx_face_landmark->landmarks_count; j++) { points[j].x = rockx_face_landmark->landmarks[j].x; //* render_rect.w / npu_w ; points[j].y = rockx_face_landmark->landmarks[j].y; //* render_rect.h / npu_h ; #if 0 fprintf(stderr, "%s %d , points[%d].x points[%d].y : %d %d, landmarks.x landmarks.y : %d %d render_rect [%d %d %d %d] npu [%d %d]\n", __FUNCTION__, __LINE__, j, j, points[j].x, points[j].y, rockx_face_landmark->landmarks[j].x, rockx_face_landmark->landmarks[j].y, render_rect.w, render_rect.h, render_rect.x, render_rect.y, npu_w, npu_h); #endif } int status = draw_points(renderer, points, rockx_face_landmark->landmarks_count, buffer, sdl_fmt); if (status) fprintf(stderr, "draw rect status: %d <%s>\n", status, SDL_GetError()); if (points) free(points); points = nullptr; } return true; } } // namespace NPU_UVC_ROCKX_DEMO