SWITCH_CONVERT_FMT_YUYV = 0
} switch_convert_fmt_t;
+struct switch_png_opaque_s;
+typedef struct switch_png_opaque_s switch_png_opaque_t;
+typedef struct switch_png_s {
+ switch_png_opaque_t *pvt;
+ int w;
+ int h;
+} switch_png_t;
+
+
+
/*!\brief Open a descriptor, allocating storage for the underlying image
*
* Returns a descriptor for storing an image of the given format. The
SWITCH_DECLARE(void) switch_img_patch_hole(switch_image_t *IMG, switch_image_t *img, int x, int y, switch_image_rect_t *rect);
-SWITCH_DECLARE(switch_image_t *) switch_img_read_png(const char* file_name);
-SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char* file_name);
-SWITCH_DECLARE(switch_status_t) switch_img_patch_png(switch_image_t *img, int x, int y, const char *file_name);
+
+SWITCH_DECLARE(switch_status_t) switch_png_patch_img(switch_png_t *use_png, switch_image_t *img, int x, int y);
+SWITCH_DECLARE(switch_image_t *) switch_img_read_png(const char *file_name);
+SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char *file_name);
+SWITCH_DECLARE(switch_status_t) switch_png_open(switch_png_t **pngP, const char *file_name);
+SWITCH_DECLARE(void) switch_png_free(switch_png_t **pngP);
SWITCH_DECLARE(void) switch_img_get_yuv_pixel(switch_image_t *img, switch_yuv_color_t *yuv, int x, int y);
float avg;
};
+struct shape {
+ int x;
+ int y;
+ int x2;
+ int y2;
+ int w;
+ int h;
+ int cx;
+ int cy;
+ int radius;
+};
+
+#define MAX_SHAPES 32
+
typedef struct cv_context_s {
CvBGCodeBookModel* model;
bool ch[NCHANNELS];
struct detect_stats nestDetected;
int detect_event;
int nest_detect_event;
+ switch_png_t *png;
+ struct shape shape[MAX_SHAPES];
+ int shapeidx;
+ int x_off;
+ int y_off;
} cv_context_t;
if (context->nestedCascade) {
delete context->nestedCascade;
}
+
+ if (context->png) {
+ switch_png_free(&context->png);
+ }
}
-static void init_context(cv_context_t *context, const char *cascade_name, const char *nested_cascade_name)
+static void init_context(cv_context_t *context, const char *cascade_name, const char *nested_cascade_name, int x_off, int y_off)
{
for (int i = 0; i < NCHANNELS; i++) {
context->ch[i] = true;
context->cascade->load(cascade_name);
if (nested_cascade_name) {
- context->nestedCascade = new CascadeClassifier;
- context->nestedCascade->load(nested_cascade_name);
+ if (switch_stristr(".png", nested_cascade_name)) {
+ switch_png_open(&context->png, nested_cascade_name);
+ context->x_off = x_off;
+ context->y_off = y_off;
+ } else {
+ context->nestedCascade = new CascadeClassifier;
+ context->nestedCascade->load(nested_cascade_name);
+ }
}
} else {
context->model = cvCreateBGCodeBookModel();
parse_stats(&context->detected, detectedObjs.size());
//printf("SCORE: %d %f %d\n", context->detected.simo_count, context->detected.avg, context->detected.last_score);
+
+ context->shapeidx = 0;
+ memset(context->shape, 0, sizeof(context->shape[0]) * MAX_SHAPES);
for( vector<Rect>::iterator r = detectedObjs.begin(); r != detectedObjs.end(); r++, i++ ) {
Mat smallImgROI;
Point center;
Scalar color = colors[i%8];
int radius;
-
+
double aspect_ratio = (double)r->width/r->height;
+
+ if (context->shapeidx >= MAX_SHAPES) {
+ break;
+ }
+
if(0.75 < aspect_ratio && aspect_ratio < 1.3 ) {
center.x = cvRound((r->x + r->width*0.5)*scale);
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
- circle( img, center, radius, color, 3, 8, 0 );
+
+ if (!context->png) {
+ circle( img, center, radius, color, 3, 8, 0 );
+ }
+
+ context->shape[context->shapeidx].x = center.x - radius;
+ context->shape[context->shapeidx].y = center.y - radius;
+ context->shape[context->shapeidx].cx = center.x;
+ context->shape[context->shapeidx].cy = center.y;
+ context->shape[context->shapeidx].radius = radius;
+ context->shapeidx++;
+
} else {
- rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)),
- cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)),
- color, 3, 8, 0);
+ context->shape[context->shapeidx].x = cvRound(r->x*scale);
+ context->shape[context->shapeidx].y = cvRound(r->y*scale);
+ context->shape[context->shapeidx].x2 = cvRound((r->x + r->width-1)*scale);
+ context->shape[context->shapeidx].y2 = cvRound((r->y + r->height-1)*scale);
+ context->shape[context->shapeidx].w = context->shape[context->shapeidx].x2 - context->shape[context->shapeidx].x;
+ context->shape[context->shapeidx].h = context->shape[context->shapeidx].y2 - context->shape[context->shapeidx].y;
+ context->shape[context->shapeidx].cx = context->shape[context->shapeidx].x + (context->shape[context->shapeidx].w / 2);
+ context->shape[context->shapeidx].cy = context->shape[context->shapeidx].y + (context->shape[context->shapeidx].h / 2);
+
+ if (!context->png) {
+ rectangle( img, cvPoint(context->shape[context->shapeidx].x, context->shape[context->shapeidx].y),
+ cvPoint(context->shape[context->shapeidx].x2, context->shape[context->shapeidx].y2),
+ color, 3, 8, 0);
+ }
+
+ context->shapeidx++;
}
if(!context->nestedCascade || context->nestedCascade->empty() ) {
int w = context->rawImage->width;
int h = context->rawImage->height;
- libyuv::RGB24ToI420((uint8_t *)context->rawImage->imageData, w * 3,
- frame->img->planes[0], frame->img->stride[0],
- frame->img->planes[1], frame->img->stride[1],
- frame->img->planes[2], frame->img->stride[2],
- context->rawImage->width, context->rawImage->height);
-
+ if (context->png && context->shapeidx && context->shape[0].x) {
+ int x = 0, y = 0;
+
+ x = context->shape[0].cx - (context->png->w / 2) + context->x_off;
+ y = context->shape[0].cy - (context->png->h / 2) + context->y_off;
+
+ switch_png_patch_img(context->png, frame->img, x, y);
+ } else {
+ libyuv::RGB24ToI420((uint8_t *)context->rawImage->imageData, w * 3,
+ frame->img->planes[0], frame->img->stride[0],
+ frame->img->planes[1], frame->img->stride[1],
+ frame->img->planes[2], frame->img->stride[2],
+ context->rawImage->width, context->rawImage->height);
+ }
+
}
return SWITCH_STATUS_SUCCESS;
char *nested_cascade_name;
char *argv[6];
int argc;
-
+ int x_off = 0, y_off = 0;
if (data && (lbuf = switch_core_session_strdup(session, data))
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
cascade_name = argv[0];
nested_cascade_name = argv[1];
+
+ if (argv[2]) {
+ x_off = atoi(argv[2]);
+ }
+
+ if (argv[3]) {
+ y_off = atoi(argv[3]);
+ }
}
- init_context(&context, cascade_name, nested_cascade_name);
+ init_context(&context, cascade_name, nested_cascade_name, x_off, y_off);
switch_channel_answer(channel);
switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
cv_context_t context;
char *cascade_name;
char *nested_cascade_name;
+ int x_off;
+ int y_off;
};
static switch_bool_t cv_bug_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
case SWITCH_ABC_TYPE_INIT:
{
switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
- init_context(&cvh->context, cvh->cascade_name, cvh->nested_cascade_name);
+ init_context(&cvh->context, cvh->cascade_name, cvh->nested_cascade_name, cvh->x_off, cvh->y_off);
}
break;
case SWITCH_ABC_TYPE_CLOSE:
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
cascade_name = argv[1];
nested_cascade_name = argv[2];
+
+ if (argv[3]) {
+ cvh->x_off = atoi(argv[3]);
+ }
+
+ if (argv[4]) {
+ cvh->y_off = atoi(argv[4]);
+ }
+
}
cvh->session = session;
#define PNG_SKIP_SETJMP_CHECK
#include <png.h>
+
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED /* available from libpng 1.6.0 */
-SWITCH_DECLARE(switch_status_t) switch_img_patch_png(switch_image_t *img, int x, int y, const char *file_name)
+struct switch_png_opaque_s {
+ png_image png;
+ png_bytep buffer;
+};
+
+
+
+SWITCH_DECLARE(switch_status_t) switch_png_open(switch_png_t **pngP, const char *file_name)
{
- png_image png = { 0 };
- png_bytep buffer = NULL;
+ switch_png_t *use_png;
switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_rgb_color_t *rgb_color;
- switch_yuv_color_t yuv_color;
- uint8_t alpha;
- int i, j;
- png.version = PNG_IMAGE_VERSION;
+ switch_zmalloc(use_png, sizeof(*use_png));
+ switch_zmalloc(use_png->pvt, sizeof(struct switch_png_opaque_s));
+ use_png->pvt->png.version = PNG_IMAGE_VERSION;
+
+ if (!png_image_begin_read_from_file(&use_png->pvt->png, file_name)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error read PNG %s\n", file_name);
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
+ }
+
+ use_png->pvt->png.format = PNG_FORMAT_RGBA;
- if (!png_image_begin_read_from_file(&png, file_name)) {
+ use_png->pvt->buffer = malloc(PNG_IMAGE_SIZE(use_png->pvt->png));
+ switch_assert(use_png->pvt->buffer);
+
+ if (!png_image_finish_read(&use_png->pvt->png, NULL/*background*/, use_png->pvt->buffer, 0, NULL)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error read PNG %s\n", file_name);
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
- // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "png format: %d, size: %dx%d\n", png.format, png.width, png.height);
- // if (png.format | PNG_FORMAT_FLAG_ALPHA) {
- // printf("Alpha\n");
- // }
- png.format = PNG_FORMAT_RGBA;
+ use_png->w = use_png->pvt->png.width;
+ use_png->h = use_png->pvt->png.height;
- buffer = malloc(PNG_IMAGE_SIZE(png));
- switch_assert(buffer);
+end:
- if (!png_image_finish_read(&png, NULL/*background*/, buffer, 0, NULL)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error read PNG %s\n", file_name);
- switch_goto_status(SWITCH_STATUS_FALSE, end);
+ if (status == SWITCH_STATUS_SUCCESS) {
+ *pngP = use_png;
+ } else {
+ switch_png_free(&use_png);
+ *pngP = NULL;
}
- for (i = 0; i < png.height; i++) {
- for (j = 0; j < png.width; j++) {
- alpha = buffer[i * png.width * 4 + j * 4 + 3];
+ return status;
+}
+
+SWITCH_DECLARE(void) switch_png_free(switch_png_t **pngP)
+{
+ switch_png_t *use_png;
+
+ if (pngP) {
+ use_png = *pngP;
+ *pngP = NULL;
+ png_image_free(&use_png->pvt->png);
+ switch_safe_free(use_png->pvt->buffer);
+ switch_safe_free(use_png->pvt);
+ switch_safe_free(use_png);
+ }
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_png_patch_img(switch_png_t *use_png, switch_image_t *img, int x, int y)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_rgb_color_t *rgb_color;
+ switch_yuv_color_t yuv_color;
+ uint8_t alpha;
+ int i, j;
+
+ switch_assert(use_png);
+
+ for (i = 0; i < use_png->pvt->png.height; i++) {
+ for (j = 0; j < use_png->pvt->png.width; j++) {
+ alpha = use_png->pvt->buffer[i * use_png->pvt->png.width * 4 + j * 4 + 3];
// printf("%d, %d alpha: %d\n", j, i, alpha);
if (alpha) { // todo, mux alpha with the underlying pixel
- rgb_color = (switch_rgb_color_t *)(buffer + i * png.width * 4 + j * 4);
+ rgb_color = (switch_rgb_color_t *)(use_png->pvt->buffer + i * use_png->pvt->png.width * 4 + j * 4);
switch_color_rgb2yuv(rgb_color, &yuv_color);
- switch_img_draw_pixel(img, x + j, i, &yuv_color);
+ switch_img_draw_pixel(img, x + j, y + i, &yuv_color);
}
}
}
-end:
- png_image_free(&png);
- switch_safe_free(buffer);
return status;
}
+#else /* libpng < 1.6.0 */
+
+SWITCH_DECLARE(switch_status_t) switch_png_open(switch_png_t **pngP, const char *file_name)
+{
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT IMPLEMENTED\n");
+ return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_DECLARE(void) switch_png_free(switch_png_t **pngP)
+{
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT IMPLEMENTED\n");
+}
+
+SWITCH_DECLARE(switch_status_t) switch_png_patch_img(switch_png_t *use_png, switch_image_t *img, int x, int y)
+{
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT IMPLEMENTED\n");
+ return SWITCH_STATUS_FALSE;
+}
+
+#endif
+
+
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED /* available from libpng 1.6.0 */
+
SWITCH_DECLARE(switch_image_t *) switch_img_read_png(const char* file_name)
{
png_image png = { 0 };
#else /* libpng < 1.6.0 */
-SWITCH_DECLARE(switch_status_t) switch_img_patch_png(switch_image_t *img, int x, int y, const char *file_name)
-{
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This function is not implemented on libpng < 1.6.0\n");
- return SWITCH_STATUS_FALSE;
-}
-
// ref: most are out-dated, man libpng :)
// http://zarb.org/~gc/html/libpng.html
// http://www.libpng.org/pub/png/book/toc.html