Skip to content

Commit

Permalink
image
Browse files Browse the repository at this point in the history
  • Loading branch information
i-evi committed Jan 8, 2021
1 parent 900f5ae commit a962a7b
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 32 deletions.
17 changes: 6 additions & 11 deletions demo/vgg16.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,15 @@ void vgg16(cc_tensor_t *in, cc_tensor_t **out);

int main(int argc, const char *argv[])
{
UTIM_IMG *img, *img_read;
cc_tensor_t *input, *output;
cc_float32 v;
cc_int32 i, j;
cc_float32 v;
cc_tensor_t *input, *output;
arg_parser(argc, (char**)argv);
cc_tsrmgr_import(parameters_path);
img_read = utim_read(image_path);
img = utim_resize(img_read, INPUT_H, INPUT_W, 0);
input = cc_image2tensor(img, "input");
utim_free_image(img);
utim_free_image(img_read);
input = cc_cast(input, CC_FLOAT32, "input");
v = 255.;
input = cc_scalar(input, '/', &v, "input");
input = cc_imread(image_path,
INPUT_H, INPUT_W, CC_RESIZE_LINEAR, CC_RGB, "input");
cc_image_norm(input, CC_IM_NORM_MINMAX_RGB);
cc_image_norm(input, CC_IM_NORM_ZSCORE_RGB);
vgg16(input, &output);
cc_tsrmgr_list();
v = 0.;
Expand Down
4 changes: 3 additions & 1 deletion src/cc_basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,11 @@ cc_tensor_t *cc_cast(cc_tensor_t *tensor,
cc_free(cast);
return NULL;
}
if (!name)
return cast;
list_rename(cast->container, name);
cast->name = cast->container->name;
if (!name || !strcmp(name, tensor->name)) {
if (!strcmp(name, tensor->name)) {
#ifdef AUTO_TSRMGR
cc_tsrmgr_replace(cast);
#else
Expand Down
125 changes: 119 additions & 6 deletions src/cc_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,84 @@
#include "cc_assert.h"
#include "cc_array.h"
#include "cc_basic.h"
#include "util_log.h"
#define _CC_IMAGE_C_
#include "cc_image.h"

cc_tensor_t *cc_imread(const char *pathname, cc_ssize h, cc_ssize w,
int mode, enum cc_colorspace color, const char *name)
{
UTIM_IMG *rd, *img;
cc_tensor_t *tensor;
cc_assert_ptr(rd = utim_read(pathname));
switch (color) {
case CC_GRAY:
utim_img2gray(rd);
break;
case CC_RGB:
utim_img2rgb (rd);
break;
case CC_RGBA:
utim_img2rgba(rd);
break;
default:
utlog_format(UTLOG_ERR,
"cc_image: unsupported color space\n");
break;
}
if (rd->xsize != w || rd->ysize != h) {
img = utim_resize(rd, w, h, mode);
utim_free_image(rd);
} else {
img = rd;
}
tensor = cc_image2tensor(img, name);
utim_free_image(img);
tensor = cc_cast(tensor, CC_FLOAT32, name);
return tensor;
}

int cc_imsave(const char *pathname, cc_ssize h, cc_ssize w,
int mode, enum cc_colorspace color, cc_tensor_t *tensor)
{
int ret;
UTIM_IMG *img, *tsrimg;
tsrimg = cc_tensor2image(tensor);
switch (color) {
case CC_GRAY:
utim_img2gray(tsrimg);
break;
case CC_RGB:
utim_img2rgb (tsrimg);
break;
case CC_RGBA:
utim_img2rgba(tsrimg);
break;
default:
utlog_format(UTLOG_ERR,
"cc_image: unsupported color space\n");
break;
}
if (tsrimg->xsize != w || tsrimg->ysize != h) {
img = utim_resize(tsrimg, w, h, mode);
utim_free_image(tsrimg);
} else {
img = tsrimg;
}
ret = utim_write(pathname, img);
utim_free_image(img);
return ret;
}

cc_tensor_t *cc_image2tensor(const UTIM_IMG *img, const char *name)
{
cc_uint8 *ptr;
cc_ssize i, j, ch_size;
cc_ssize shape[4] = {0}; /* [C, H, W, \0] */
cc_tensor_t *tensor;
shape[CC_IT_SHAPE_C] = img->channels;
shape[CC_IT_SHAPE_H] = img->ysize;
shape[CC_IT_SHAPE_W] = img->xsize;
shape[CC_IM_SHAPE_C] = img->channels;
shape[CC_IM_SHAPE_H] = img->ysize;
shape[CC_IM_SHAPE_W] = img->xsize;
cc_assert_ptr(tensor = cc_create(shape, CC_UINT8, name));
ch_size = img->xsize * img->ysize;
ptr = tensor->data;
Expand All @@ -35,10 +101,10 @@ UTIM_IMG *cc_tensor2image(const cc_tensor_t *tensor)
cc_uint8 *pxls, *ptr;
cc_ssize i, j, ch_size, npxls;
const cc_ssize *sptr = tensor->shape;
if (cc_dimension(tensor) != 3) /* [C, H, W] */
if (cc_dimension(tensor) != CC_IM_DIM) /* [C, H, W] */
return NULL;
img = utim_create(sptr[CC_IT_SHAPE_W],
sptr[CC_IT_SHAPE_H], sptr[CC_IT_SHAPE_C], 0);
img = utim_create(sptr[CC_IM_SHAPE_W],
sptr[CC_IM_SHAPE_H], sptr[CC_IM_SHAPE_C], 0);
ch_size = img->xsize * img->ysize;
npxls = ch_size * img->channels;
cc_assert_alloc(pxls = (cc_uint8*)malloc(npxls));
Expand All @@ -51,3 +117,50 @@ UTIM_IMG *cc_tensor2image(const cc_tensor_t *tensor)
free(pxls);
return img;
}

static void cc_image_norm_minmax_rgb(cc_tensor_t *tsrimg)
{
cc_float32 v = 255.f;
/* experimental function for fp32 only */
cc_assert(*tsrimg->dtype == CC_FLOAT32);
tsrimg = cc_scalar(tsrimg, '/', &v, tsrimg->name);
}

static const cc_float32 im_zs_rgb_mean[] = {0.485, 0.456, 0.406};
static const cc_float32 im_zs_rgb_std [] = {0.229, 0.224, 0.225};

static void cc_image_norm_zscore_rgb(cc_tensor_t *tsrimg)
{
cc_ssize i, ch_size;
cc_float32 *obj;
const cc_float32 *mp, *sp;
/* experimental function for fp32 only */
cc_assert(*tsrimg->dtype == CC_FLOAT32);
cc_assert(cc_dimension(tsrimg) == CC_IM_DIM);
cc_assert(tsrimg->shape[CC_IM_SHAPE_C] == 3); /* RGB only */
ch_size = tsrimg->shape[CC_IM_SHAPE_H] *
tsrimg->shape[CC_IM_SHAPE_W];
for (i = 0; i < 3; ++i) {
obj = ((cc_float32*)tsrimg->data) + ch_size * i;
mp = im_zs_rgb_mean + i;
sp = im_zs_rgb_std + i;
cc_array_sub_by(obj, ch_size, obj, mp, CC_FLOAT32);
cc_array_div_by(obj, ch_size, obj, sp, CC_FLOAT32);
}
}

void cc_image_norm(cc_tensor_t *tsrimg, enum cc_image_norm_mode mode)
{
switch (mode) {
case CC_IM_NORM_MINMAX_RGB:
cc_image_norm_minmax_rgb(tsrimg);
break;
case CC_IM_NORM_ZSCORE_RGB:
cc_image_norm_zscore_rgb(tsrimg);
break;
default:
utlog_format(UTLOG_ERR,
"cc_image: unsupported normalization mode\n");
break;
}
}
38 changes: 32 additions & 6 deletions src/cc_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,47 @@
#include "cc_tensor.h"
#include "util_image.h"

#define CC_RESIZE_NEAREST UTIM_RESIZE_NEAREST
#define CC_RESIZE_LINEAR UTIM_RESIZE_LINEAR

/*
* Create tensor from image, [C, H, W] format
*/
#define CC_IT_SHAPE_C 0
#define CC_IT_SHAPE_H 1
#define CC_IT_SHAPE_W 2
#define CC_IM_DIM 3
#define CC_IM_SHAPE_C 0
#define CC_IM_SHAPE_H 1
#define CC_IM_SHAPE_W 2

enum cc_colorspace {
CC_GRAY,
CC_RGB,
CC_RGBA
};

cc_tensor_t *cc_imread(const char *pathname, cc_ssize h, cc_ssize w,
int mode, enum cc_colorspace color, const char *name);

int cc_imsave(const char *pathname, cc_ssize h, cc_ssize w,
int mode, enum cc_colorspace color, cc_tensor_t *tensor);

cc_tensor_t *cc_image2tensor(const UTIM_IMG *img, const char *name);

UTIM_IMG *cc_tensor2image(const cc_tensor_t *tensor);

enum cc_image_norm_mode {
/* CC_IM_NORM_MINMAX, */
CC_IM_NORM_MINMAX_RGB,
/* CC_IM_NORM_ZSCORE, */
CC_IM_NORM_ZSCORE_RGB
};

void cc_image_norm(cc_tensor_t *tsrimg, enum cc_image_norm_mode mode);

#ifndef _CC_IMAGE_C_
#undef CC_IT_SHAPE_C
#undef CC_IT_SHAPE_H
#undef CC_IT_SHAPE_W
#undef CC_IM_DIM
#undef CC_IM_SHAPE_C
#undef CC_IM_SHAPE_H
#undef CC_IM_SHAPE_W
#endif

#ifdef __cplusplus
Expand Down
5 changes: 2 additions & 3 deletions src/cc_tsrmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,8 @@ void cc_tsrmgr_reg(cc_tensor_t *tensor)
void cc_tsrmgr_replace(cc_tensor_t *tensor)
{
struct pair *ptr;
#ifdef ENABLE_CC_ASSERT
cc_assert_ptr(tensor->name);
#endif
if (!tensor->name)
return; /* Nothing happen */
if (!g_tsrmgr) {
utlog_format(UTLOG_WARN, "cc_tsrmgr: not initialized\n");
return;
Expand Down
12 changes: 8 additions & 4 deletions src/util_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,15 +419,19 @@ UTIM_IMG *utim_resize(UTIM_IMG *img, int x, int y, int mode)
return NULL;
}
break;
#ifdef USE3RD_STB_IMAGE
case UTIM_RESIZE_LINEAR:
#ifdef USE3RD_STB_IMAGE
resize->pixels = _image_resize_linear(img, x, y);
#else
fprintf(stderr,
"WARNING: Interpolation mode LINEAR not impl yet, using NEAREST\n");
resize->pixels = _image_resize_nearest(img, x, y);
#endif
if (!resize->pixels) {
free(resize);
return NULL;
}
break;
#endif
default:
return NULL;
}
Expand Down Expand Up @@ -748,7 +752,7 @@ UTIM_IMG *utim_rgb_by_gray(UTIM_IMG *gray)
return rgb;
}

UTIM_IMG *utim_create(int x, int y, int nch, int c)
UTIM_IMG *utim_create(int x, int y, int nch, int init)
{
UTIM_IMG *img;
int size = x * y * nch;
Expand All @@ -762,7 +766,7 @@ UTIM_IMG *utim_create(int x, int y, int nch, int c)
free(img);
return NULL;
}
memset(img->pixels, c, size);
memset(img->pixels, init, size);
img->xsize = x;
img->ysize = y;
img->channels = nch;
Expand Down
2 changes: 1 addition & 1 deletion src/util_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ int utim_write_ctrl(const char *filename,
UTIM_IMG *img, int comp, int quality);

UTIM_IMG *utim_clone(UTIM_IMG *img);
UTIM_IMG *utim_create(int x, int y, int nch, int c);
UTIM_IMG *utim_create(int x, int y, int nch, int init);

void utim_free_image(UTIM_IMG *img);

Expand Down

0 comments on commit a962a7b

Please sign in to comment.