Skip to content

Commit

Permalink
Merge pull request OpenPTV#64 from yosefm/alex55
Browse files Browse the repository at this point in the history
Preparing image for detection.
  • Loading branch information
yosefm committed Oct 20, 2015
2 parents 82bacd9 + 07f5d5c commit 5b33ffd
Show file tree
Hide file tree
Showing 3 changed files with 333 additions and 3 deletions.
7 changes: 7 additions & 0 deletions liboptv/include/image_processing.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ void lowpass_3(unsigned char *img, unsigned char *img_lp, control_par *cpar);
int fast_box_blur(int filt_span, unsigned char *src, unsigned char *dest,
control_par *cpar);
void split(unsigned char *img, int half_selector, control_par *cpar);
void subtract_img(unsigned char *img1, unsigned char *img2, unsigned char *img_new,
control_par *cpar);
void subtract_mask(unsigned char *img1, unsigned char *img_mask, unsigned char *img_new,
control_par *cpar);
void copy_images(unsigned char *img1, unsigned char *img2, control_par *cpar);
int prepare_image(unsigned char *img, unsigned char *img_hp, int dim_lp,
int filter_hp, char *filter_file, control_par *cpar);

#endif

141 changes: 141 additions & 0 deletions liboptv/src/image_processing.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
***************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include "image_processing.h"

/* This would be a function, only the original writer of these filters put a
Expand Down Expand Up @@ -276,3 +277,143 @@ void split(unsigned char *img, int half_selector, control_par *cpar) {
*ptr = 2;
}


/* subtract_img() is a simple image arithmetic function that subtracts img2 from
img1.
Arguments:
unsigned char *img1, *img2 - pointers to the original images.
unsigned char *img_new - pointer to result image buffer.
control_par *cpar - contains image size parameters.
*/
void subtract_img (unsigned char *img1,unsigned char *img2,unsigned char *img_new, control_par *cpar)
{
register unsigned char *ptr1, *ptr2, *ptr3;
int i;
int image_size = cpar->imx * cpar->imy;

for (i = 0, ptr1 = img1, ptr2 = img2, ptr3 = img_new; i < image_size;
ptr1++, ptr2++, ptr3++, i++)
{
if ((*ptr1 - *ptr2) < 0)
*ptr3 = 0;
else
*ptr3 = *ptr1 - *ptr2;
}
}


/* Subtract_mask(), by Matthias Oswald, Juli 08
Compares img with img_mask and creates a masked image img_new.
Pixels that are equal to zero in the img_mask are overwritten with a
default value (=0) in img_new.
Arguments:
unsigned char *img - original image.
unsigned char *img_new - resulting image buffer.
control_par *cpar - contains image size parameters.
*/
void subtract_mask (unsigned char *img, unsigned char *img_mask,
unsigned char *img_new, control_par *cpar)
{
register unsigned char *ptr1, *ptr2, *ptr3;
int i;
int image_size = cpar->imx * cpar->imy;

for (i = 0, ptr1 = img, ptr2 = img_mask, ptr3 = img_new; i < image_size;
ptr1++, ptr2++, ptr3++, i++)
{
if (*ptr2 == 0)
*ptr3 = 0;
else
*ptr3 = *ptr1;
}
}

/* copy_images() is a simple image arithmetic function that copies one image
into another. It is basically equivalent to a memcpy(), but more
future-proof, we hope.
Arguments:
unsigned char *src, *dest - unsigned char array pointers to source and
destination of copy, respectively.
control_par *cpar - contains image size parameters.
*/
void copy_images (unsigned char *src, unsigned char *dest, control_par *cpar)
{
register unsigned char *ptr1, *ptr2;
unsigned char *end;
int image_size = cpar->imx * cpar->imy;

for (end = src + image_size, ptr1 = src, ptr2 = dest; ptr1 < end;
ptr1++, ptr2++)
{
*ptr2 = *ptr1;
}
}

/* prepare_image() - perform the steps necessary for preparing an image to
particle detection: an averaging (smoothing) filter on an image, optionally
followed by additional user-defined filter.
Arguments:
unsigned char *img - the source image to filter.
unsigned char *img_hp - result buffer for filtered image. Same size as img.
int dim_lp - dimension of subtracted lowpass image.
int filter_hp - flag for additional filtering of _hp. 1 for lowpass, 2 for
general 3x3 filter given in parameter ``filter_file``.
char *filter_file - path to a text file containing the filter matrix to be
used in case ```filter_hp == 2```. One line per row, white-space
separated columns.
control_par *cpar - image details such as size and image half for interlaced
cases.
Returns:
1 on success, 0 on failure of memory allocation or filter file reading.
*/
int prepare_image(unsigned char *img, unsigned char *img_hp, int dim_lp,
int filter_hp, char *filter_file, control_par *cpar)
{
register int i;
FILE *fp;
unsigned char *img_lp;
int image_size = cpar->imx * cpar->imy;
filter_t filt; /* for when filter_hp == 2 */

register unsigned char *ptr1, *ptr2, *ptr3;

img_lp = (unsigned char *) calloc (image_size, 1);
if ( ! img_lp) {
puts ("calloc for img_lp --> error");
return 0;
}
fast_box_blur(dim_lp, img, img_lp, cpar);
subtract_img (img, img_lp, img_hp, cpar);

/* consider field mode */
if (cpar->chfield == 1 || cpar->chfield == 2)
split (img_hp, cpar->chfield, cpar);

/* filter highpass image, if wanted */
switch (filter_hp) {
case 0: break;
case 1: lowpass_3 (img_hp, img_hp, cpar); break;
case 2:
/* read filter elements from parameter file */
fp = fopen (filter_file, "r");
for (i = 0; i < 9; i++) {
if (fscanf(fp, "%lf", (double *)filt + i) == 0) {
fclose(fp);
return 0;
}
}
fclose (fp);

filter_3 (img_hp, img_hp, filt, cpar);
break;
}

free (img_lp);
return 1;
}

188 changes: 185 additions & 3 deletions liboptv/tests/check_image_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,7 @@ END_TEST

START_TEST(test_split)
{
/* A 3x3 box-blur is equivalent to lowpass_3, so that's the comparison
we'll make here. Only difference is highpass_3 wraps around rows so
it has different values at the edges. */

int elem;

unsigned char img[5][5] = {
Expand Down Expand Up @@ -190,6 +188,174 @@ START_TEST(test_split)
}
END_TEST

START_TEST(test_subtract_img)
{

int elem;

unsigned char img[5][5] = {
{ 0, 0, 0, 0, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 0, 0, 0, 0}
};

unsigned char img_zero[5][5] = {
{ 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0}
};

control_par cpar = {
.imx = 5,
.imy = 5,
};

unsigned char *img1 = (unsigned char *) malloc(cpar.imx*cpar.imy* \
sizeof(unsigned char));
// memcpy(img1, img, 25);

subtract_img(img, img_zero, img1, &cpar);
fail_unless(images_equal(img1, img, 5, 5, 0, 0));

unsigned char *img2 = (unsigned char *) malloc(cpar.imx*cpar.imy* \
sizeof(unsigned char));
subtract_img(img, img1, img2, &cpar);
fail_unless(images_equal(img2, img_zero, 5, 5, 0, 0));

free(img1);
free(img2);
}
END_TEST

START_TEST(test_subtract_mask)
{

int elem;

unsigned char img[5][5] = {
{ 0, 0, 0, 0, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 0, 0, 0, 0}
};

unsigned char img_mask1[5][5] = {
{ 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1}
};

unsigned char img_mask2[5][5] = {
{ 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1},
{ 1, 1, 0, 1, 1},
{ 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1}
};

unsigned char img_correct[5][5] = {
{ 0, 0, 0, 0, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 0, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 0, 0, 0, 0}
};


control_par cpar = {
.imx = 5,
.imy = 5,
};

unsigned char *img_new = (unsigned char *) malloc(cpar.imx*cpar.imy* \
sizeof(unsigned char));

subtract_mask(img, img_mask1, img_new, &cpar);
fail_unless(images_equal(img_new, img, 5, 5, 0, 0));

subtract_mask(img, img_mask2, img_new, &cpar);
fail_unless(images_equal(img_new, img_correct, 5, 5, 0, 0));

free(img_new);
}
END_TEST

START_TEST(test_copy_img)
{

int elem;

unsigned char img[6][5] = {
{ 0, 0, 0, 0, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1}
};

control_par cpar = {
.imx = 6,
.imy = 5,
};

unsigned char *img_new = (unsigned char *) malloc(cpar.imx*cpar.imy* \
sizeof(unsigned char));
unsigned char *img1 = (unsigned char *) malloc(cpar.imx*cpar.imy* \
sizeof(unsigned char));

copy_images(img, img_new, &cpar);
fail_unless(images_equal(img_new, img, cpar.imx, cpar.imy, 0, 0));

memcpy(img1,img,cpar.imx*cpar.imy);
fail_unless(images_equal(img_new, img1, cpar.imx, cpar.imy, 0, 0));

free(img_new);
}
END_TEST

START_TEST(test_highpass)
{
unsigned char img[5][5] = {
{ 0, 0, 0, 0, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 255, 255, 255, 0},
{ 0, 0, 0, 0, 0}
};

unsigned char img_correct[5][5] = {
{ 0, 0, 0, 0, 0},
{ 0, 142, 85, 142, 0},
{ 0, 85, 0, 85, 0},
{ 0, 142, 85, 142, 0},
{ 0, 0, 0, 0, 0}
};

control_par cpar = {
.imx = 5,
.imy = 5,
};

unsigned char *img_hp = (unsigned char *) malloc(cpar.imx*cpar.imy* \
sizeof(unsigned char));

prepare_image(img, img_hp, 1, 0, 0, &cpar);

fail_unless(images_equal(img_hp, img_correct, 5, 5, 6, 6));

free(img_hp);
}
END_TEST


Suite* fb_suite(void) {
Suite *s = suite_create ("Image processing");

Expand All @@ -208,6 +374,22 @@ Suite* fb_suite(void) {
tc = tcase_create ("Split image");
tcase_add_test(tc, test_split);
suite_add_tcase (s, tc);

tc = tcase_create ("Subtract image");
tcase_add_test(tc, test_subtract_img);
suite_add_tcase (s, tc);

tc = tcase_create ("Subtract mask");
tcase_add_test(tc, test_subtract_mask);
suite_add_tcase (s, tc);

tc = tcase_create ("Copy images");
tcase_add_test(tc, test_copy_img);
suite_add_tcase (s, tc);

tc = tcase_create ("High-pass");
tcase_add_test(tc, test_highpass);
suite_add_tcase (s, tc);

return s;
}
Expand Down

0 comments on commit 5b33ffd

Please sign in to comment.