From 27d62fdf3535d510588ae58fab671b670e7d7e7a Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sun, 3 Jan 2010 20:05:29 +0000 Subject: Add -normalize git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1090 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/pnmconvol.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 2 deletions(-) (limited to 'editor') diff --git a/editor/pnmconvol.c b/editor/pnmconvol.c index b1f4adc8..93e99e84 100644 --- a/editor/pnmconvol.c +++ b/editor/pnmconvol.c @@ -66,6 +66,7 @@ struct cmdlineInfo { const char ** matrixfile; unsigned int matrixSpec; struct matrixOpt matrix; + unsigned int normalize; }; @@ -313,6 +314,8 @@ parseCommandLine(int argc, char ** argv, &matrixfileSpec, 0) OPTENT3(0, "nooffset", OPT_FLAG, NULL, &cmdlineP->nooffset, 0); + OPTENT3(0, "normalize", OPT_FLAG, NULL, + &cmdlineP->normalize, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ @@ -527,6 +530,52 @@ convKernelDestroy(struct convKernel * const convKernelP) { +static void +normalizeKernelPlane(struct convKernel * const convKernelP, + unsigned int const plane) { + + unsigned int row; + float sum; + + for (row = 0, sum = 0.0; row < convKernelP->rows; ++row) { + unsigned int col; + + for (col = 0; col < convKernelP->cols; ++col) { + + sum += convKernelP->weight[plane][row][col]; + } + } + + { + float const scaler = 1.0/sum; + + unsigned int row; + + for (row = 0; row < convKernelP->rows; ++row) { + unsigned int col; + + for (col = 0; col < convKernelP->cols; ++col) + convKernelP->weight[plane][row][col] *= scaler; + } + } +} + + + +static void +normalizeKernel(struct convKernel * const convKernelP) { +/*---------------------------------------------------------------------------- + Modify *convKernelP by scaling every weight in a plane by the same factor + such that the weights in the plane all add up to 1. +-----------------------------------------------------------------------------*/ + unsigned int plane; + + for (plane = 0; plane < convKernelP->planes; ++plane) + normalizeKernelPlane(convKernelP, plane); +} + + + static void getKernelPnm(const char * const fileName, unsigned int const depth, @@ -552,9 +601,20 @@ getKernelPnm(const char * const fileName, static void convKernelCreateMatrixOpt(struct matrixOpt const matrixOpt, + bool const normalize, unsigned int const depth, struct convKernel ** const convKernelPP) { +/*---------------------------------------------------------------------------- + Create a convolution kernel as described by a -matrix command line + option. + + The option value is 'matrixOpt'. + If 'normalize' is true, we normalize whatever numbers the option specifies + so that they add up to one; otherwise, we take the numbers as we find them, + so they may form a biased matrix -- i.e. one which brightens or dims the + image overall. +-----------------------------------------------------------------------------*/ struct convKernel * convKernelP; unsigned int plane; @@ -579,6 +639,9 @@ convKernelCreateMatrixOpt(struct matrixOpt const matrixOpt, matrixOpt.weight[row][col]; } } + if (normalize) + normalizeKernel(convKernelP); + *convKernelPP = convKernelP; } @@ -742,9 +805,21 @@ copyWeight(float ** const srcWeight, static void convKernelCreateSimpleFile(const char ** const fileNameList, + bool const normalize, unsigned int const depth, struct convKernel ** const convKernelPP) { +/*---------------------------------------------------------------------------- + Create a convolution kernel as described by a convolution matrix file. + This is the simple file with floating point numbers in it, not the + legacy pseudo-PNM thing. + + The name of the file is 'fileNameList'. + If 'normalize' is true, we normalize whatever numbers we find in the file + so that they add up to one; otherwise, we take the numbers as we find them, + so they may form a biased matrix -- i.e. one which brightens or dims the + image overall. +-----------------------------------------------------------------------------*/ struct convKernel * convKernelP; unsigned int fileCt; unsigned int planeCt; @@ -792,6 +867,10 @@ convKernelCreateSimpleFile(const char ** const fileNameList, &convKernelP->weight[plane]); } } + + if (normalize) + normalizeKernel(convKernelP); + convKernelP->cols = width; convKernelP->rows = height; *convKernelPP = convKernelP; @@ -803,16 +882,25 @@ static void getKernel(struct cmdlineInfo const cmdline, unsigned int const depth, struct convKernel ** const convKernelPP) { +/*---------------------------------------------------------------------------- + Figure out what the convolution kernel is. It can come from various + sources in various forms, as described on the command line, represented + by 'cmdline'. + We generate a kernel object in standard form (free of any indication of + where it came from) and return a handle to it as *convKernelPP. +-----------------------------------------------------------------------------*/ struct convKernel * convKernelP; if (cmdline.pnmMatrixFileName) getKernelPnm(cmdline.pnmMatrixFileName, depth, cmdline.nooffset, &convKernelP); else if (cmdline.matrixfile) - convKernelCreateSimpleFile(cmdline.matrixfile, depth, &convKernelP); + convKernelCreateSimpleFile(cmdline.matrixfile, cmdline.normalize, + depth, &convKernelP); else if (cmdline.matrixSpec) - convKernelCreateMatrixOpt(cmdline.matrix, depth, &convKernelP); + convKernelCreateMatrixOpt(cmdline.matrix, cmdline.normalize, + depth, &convKernelP); warnBadKernel(convKernelP); -- cgit 1.4.1