https://github.com/ma-tech/Woolz
Tip revision: 5ab012fff0fb50186d6ea8508f0d8b3063c45dc3 authored by Bill Hill on 15 August 2022, 13:30:41 UTC
README now Readme.md.
README now Readme.md.
Tip revision: 5ab012f
WlzSepFilterObj.c
#if defined(__GNUC__)
#ident "University of Edinburgh $Id$"
#else
static char _WlzSepFilterObj_c[] = "University of Edinburgh $Id$";
#endif
/*!
* \file binWlz/WlzSepFilterObj.c
* \author Bill Hill
* \date November 2016
* \version $Id$
* \par
* Address:
* MRC Human Genetics Unit,
* MRC Institute of Genetics and Molecular Medicine,
* University of Edinburgh,
* Western General Hospital,
* Edinburgh, EH4 2XU, UK.
* \par
* Copyright (C), [2016],
* The University Court of the University of Edinburgh,
* Old College, Edinburgh, UK.
*
* 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 2
* 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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
* \brief Seperable spatial convolution kernel base filters
* for 2 and 3D objects.
* \ingroup BinWlz
*
* \par Binary
* \ref wlzsepfilterobj "WlzSepFilterObj"
*/
/*!
\ingroup BinWlz
\defgroup wlzsepfilterobj WlzSepFilterObj
\par Name
WlzSepFilterObj - seperable spatial convolution filter for domain objects
with grey values.
\par Synopsis
\verbatim
WlzSepFilterObj - [-h] [-v] [-o<output object>] [-m#,#,#] [-n#,#,#]
[-g <t>] [-t <flags>] [-P <p>] [-p#] [-G] [-S a|c|s]
[<input object>]
\endverbatim
\par Options
<table width="500" border="0">
<tr>
<td><b>-h</b></td>
<td>Help, prints usage message.</td>
</tr>
<tr>
<td><b>-v</b></td>
<td>Verbose output with parameter values and execution time.</td>
</tr>
<tr>
<td><b>-o</b></td>
<td>Output object file name.</td>
</tr>
<tr>
<td><b>-m</b></td>
<td>Filter parameters; for a Gaussian these are the sigma
values for each orthogonal direction (x, y and z). Default
values are 1,1,1.</td>
</tr>
<tr>
<td><b>-n</b></td>
<td>Order parameters; for a Gaussian these are the order of the
Gaussian's derivatives (eg 0 for no derivative, 1 for 1st
derivative), default 0,0,0.</td>
</tr>
<tr>
<td><b>-g</b></td>
<td>Required grey type, default is the same as the input object's,
with 'i', 's', 'u', 'f' and 'd' used to request int, short,
unsigned byte, float or double grey values.</td>
</tr>
<tr>
<td><b>-t</b></td>
<td>Filter directions, eg x filter along lines and x, y filter
along lines then through columns.</td>
</tr>
<tr>
<td><b>-P</b></td>
<td>Type of padding to use, default is to use the background value,
with 'b', 'e', 'v' and 'z' used to select background, end, given
value and zero padding.</td>
</tr>
<tr>
<td><b>-p</b></td>
<td>Used to supply given padding value, default 0.0.</td>
</tr>
<tr>
<td><b>-G</b></td>
<td>Use Gaussian filter, default.</td>
</tr>
<tr>
<td><b>-S</b></td>
<td>Use the input object for each of the directional filters rather
than the output of the previous directional filter. The seperate
filter outputs are then combined to form a compound object (<b>c</b>),
the sum (<b>a</b>) or the square root of the sum of the squared
values of the filter passes (<b>s</b>).</td>
</tr>
</table>
\par Description
Applies a seperable filter to a Woolz domain object with grey values.
The input object is read from stdin and the filtered object is written
to stdout unless the filenames are given.
\par Examples
\verbatim
WlzSepFilterObj -m ,3.0,2.0 -t x,y,z -o smooth.wlz in.wlz
\endverbatim
The input Woolz object is read from in.wlz, and filtered using a
Gaussian filter with sigma values of 1.0, 3.0 and 2.0 in the x, y and z
directions. The filtered object is then written to the file smoothed.wlz.
\par File
\ref WlzSepFilterObj.c "WlzSepFilterObj.c"
\par See Also
\ref BinWlz "WlzIntro(1)"
\ref wlzgauss "WlzGauss(1)"
\ref WlzRsvFilterObj "WlzRsvFilterObj(1)"
\ref WlzGaussFilter "WlzGaussFilter(3)"
\ref WlzSepFilter "WlzSepFilter(3)"
*/
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include <Wlz.h>
extern int getopt(int argc, char * const *argv, const char *optstring);
extern char *optarg;
extern int optind,
opterr,
optopt;
int main(int argc, char **argv)
{
int option,
ok = 1,
sep = 0,
usage = 0,
verbose = 0;
double padVal = 0.0;
WlzDVertex3 param[] = {{1.0, 1.0, 1.0}, {0.0, 0.0, 0.0}};
WlzIVertex3 order = {0, 0, 0};
AlgPadType pad = ALG_PAD_NONE;
WlzGreyType gType = WLZ_GREY_ERROR;
WlzIVertex3 action = {1, 1, 1};
WlzObject *inObj = NULL,
*outObj = NULL;
struct timeval times[3];
const char *errMsgStr;
WlzErrorNum errNum = WLZ_ERR_NONE;
char *outFileStr,
*inObjFileStr;
static char optList[] = "Ghvg:o:m:n:P:p:t:S:",
defFile[] = "-";
opterr = 0;
outFileStr = defFile;
inObjFileStr = defFile;
while(ok && ((option = getopt(argc, argv, optList)) != -1))
{
switch(option)
{
case 'o':
outFileStr = optarg;
break;
case 'h':
usage = 1;
break;
case 'v':
verbose = 1;
break;
case 'g':
switch(*optarg)
{
case 'i':
gType = WLZ_GREY_INT;
break;
case 's':
gType = WLZ_GREY_SHORT;
break;
case 'u':
gType = WLZ_GREY_UBYTE;
break;
case 'f':
gType = WLZ_GREY_FLOAT;
break;
case 'd':
gType = WLZ_GREY_DOUBLE;
break;
default:
usage = 1;
break;
}
break;
case 'm':
if((optarg == NULL) ||
(sscanf(optarg, "%lg,%lg,%lg",
&(param[0].vtX), &(param[0].vtY), &(param[0].vtZ)) < 1))
{
usage = 1;
}
break;
case 'n':
if((optarg == NULL) ||
(sscanf(optarg, "%d,%d,%d",
&(order.vtX), &(order.vtY), &(order.vtZ)) < 1))
{
usage = 1;
}
break;
case 'P':
switch(*optarg)
{
case 'b':
pad = ALG_PAD_NONE;
break;
case 'e':
pad = ALG_PAD_END;
break;
case 'v':
pad = ALG_PAD_VALUE;
break;
case 'z':
pad = ALG_PAD_ZERO;
break;
default:
usage = 1;
break;
}
break;
case 'p':
if((optarg == NULL) || (sscanf(optarg, "%lg", &padVal) != 1))
{
usage = 1;
}
break;
case 'G':
/* Only have Gaussian implemented. */
break;
case 't':
if(optarg)
{
char *actStr;
action.vtX = 0;
action.vtY = 0;
action.vtZ = 0;
actStr = strtok(optarg, ",");
while(actStr && ok)
{
if(strcmp(actStr, "x") == 0)
{
action.vtX = 1;
}
else if(strcmp(actStr, "y") == 0)
{
action.vtY = 1;
}
else if(strcmp(actStr, "z") == 0)
{
action.vtZ = 1;
}
else
{
usage = 1;
}
actStr = strtok(NULL, ",");
}
}
break;
case 'S':
if(!optarg || (strlen(optarg) > 1))
{
usage = 1;
}
else
{
switch(*optarg)
{
case 'c':
sep = 1;
break;
case 'a':
sep = 2;
break;
case 's':
sep = 3;
break;
default:
usage = 1;
break;
}
}
break;
default:
usage = 1;
break;
}
}
if(!usage)
{
if(optind < argc)
{
if((optind + 1) != argc)
{
usage = 1;
}
else
{
inObjFileStr = *(argv + optind);
}
}
}
ok = !usage;
if(ok)
{
FILE *fP = NULL;
if(verbose)
{
(void )fprintf(stderr,
"%s: Reading object from %s\n",
*argv, strcmp(inObjFileStr, "-")? inObjFileStr: "stdin");
}
if(((fP = (strcmp(inObjFileStr, "-")?
fopen(inObjFileStr, "r"): stdin)) == NULL) ||
((inObj= WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) ||
(errNum != WLZ_ERR_NONE))
{
ok = 0;
(void )fprintf(stderr,
"%s: Failed to read object from file %s\n",
*argv, inObjFileStr);
}
if(fP && strcmp(inObjFileStr, "-"))
{
fclose(fP);
}
}
if(ok && (pad == ALG_PAD_NONE))
{
WlzPixelV bgd;
bgd = WlzGetBackground(inObj, &errNum);
if(errNum == WLZ_ERR_NONE)
{
WlzValueConvertPixel(&bgd, bgd, WLZ_GREY_DOUBLE);
padVal = bgd.v.dbv;
pad = ALG_PAD_VALUE;
}
else
{
ok = 0;
(void )WlzStringFromErrorNum(errNum, &errMsgStr);
(void )fprintf(stderr,
"%s: Failed to get object background value (%s).\n",
*argv, errMsgStr);
}
}
if(ok)
{
if(verbose)
{
(void )fprintf(stderr,
"%s: Filtering object with:\n"
" param[0] = (%g, %g, %g)\n"
" param[1] = (%g, %g, %g)\n"
" order = (%d, %d, %d)\n"
" action = (%d, %d, %d)\n"
" gType = %d\n"
" pad = %d\n"
" padVal = %lg\n"
" sep = %d\n",
*argv,
param[0].vtX, param[0].vtY, param[0].vtZ,
param[1].vtX, param[1].vtY, param[1].vtZ,
order.vtX, order.vtY, order.vtZ,
action.vtX, action.vtY, action.vtZ,
gType, pad, padVal, sep);
gettimeofday(times + 0, NULL);
}
outObj = WlzAssignObject(
WlzGaussFilter(inObj, param[0], order, action, gType,
pad, padVal, sep, &errNum),
NULL);
if(verbose)
{
gettimeofday(times + 1, NULL);
ALC_TIMERSUB(times + 1, times + 0, times + 2);
(void )fprintf(stderr,
"%s: Elapsed time for WlzGaussFilter() %gus\n",
argv[0], (1.0e06 * times[2].tv_sec) + times[2].tv_usec);
}
if(errNum != WLZ_ERR_NONE)
{
ok = 0;
(void )WlzStringFromErrorNum(errNum, &errMsgStr);
(void )fprintf(stderr,
"%s: Failed to filter object (%s).\n",
*argv, errMsgStr);
}
}
if(ok)
{
FILE *fP = NULL;
if(verbose)
{
(void )fprintf(stderr,
"%s: Writing object to %s\n",
*argv, strcmp(outFileStr, "-")? outFileStr: "stdout");
}
errNum = WLZ_ERR_FILE_OPEN;
if(((fP = (strcmp(outFileStr, "-")?
fopen(outFileStr, "w"): stdout)) == NULL) ||
((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE))
{
ok = 0;
(void )WlzStringFromErrorNum(errNum, &errMsgStr);
(void )fprintf(stderr,
"%s: Failed to write output object (%s).\n",
*argv,
errMsgStr);
}
if(fP && strcmp(outFileStr, "-"))
{
fclose(fP);
}
}
(void )WlzFreeObj(inObj);
(void )WlzFreeObj(outObj);
if(usage)
{
(void )fprintf(stderr,
"Usage: %s%s%s%sExample: %s%s",
*argv,
" [-h] [-o<output object>] [-m#,#,#] [-n#,#,#]\n"
"\t[-g <t>] [-t <flags>] [-P <p>] [-p#] [-G]\n"
"\t[-S a|c|s] [-v] [<input object>]\n"
"Version: ",
WlzVersion(),
"\n"
"Options:\n"
" -h Prints this usage information\n"
" -o Output object file name.\n"
" -m Filter parameters; for a Gaussian these are the sigma values\n"
" for each orthogonal direction (x, y and z). Default values are\n"
" 1,1,1.\n"
" -n Order parameters; for a Gaussian these are the order of the\n"
" Gaussian's derivatives (eg 0 for no derivative, 1 for 1st\n"
" derivative), default 0,0,0.\n"
" -g Required grey type, default is the same as the input object's,\n"
" with 'i', 's', 'u', 'f' and 'd' used to request int, short,\n"
" unsigned byte, float or double grey values.\n"
" -P Type of padding to use, default is to use the background value,\n"
" with 'b', 'e', 'v' and 'z' used to select background, end, given\n"
" value and zero padding.\n"
" -p Used to supply given padding value, default 0.0.\n"
" -G Use a Gaussain filter (default).\n"
" -S Use the input object for each of the directional filters rather\n"
" than the output of the previous directional filter. The seperate\n"
" filter outputs are then combined to form a compound object (c),\n"
" the sum (a) or the square root of the sum of the squared values\n"
" of the filter passes (s).\n"
" -t Filter directions, eg x filter along lines and x, y filter\n"
" along lines then through columns.\n"
" -v Verbose output with parameter values and execution time.\n"
"Applies a seperable filter to a Woolz domain object with grey values.\n"
"The input object is read from stdin and the filtered object is\n"
"written to stdout unless the filenames are given.\n",
*argv,
" -m ,3.0,2.0 -t x,y,z -o smooth.wlz in.wlz\n"
"The input Woolz object is read from in.wlz, and filtered using a\n"
"Gaussian filter with sigma values of 1.0, 3.0 and 2.0 in the x, y\n"
"and z directions. The filtered object is then written to the file\n"
"smoothed.wlz.\n");
}
return(!ok);
}
#endif /* DOXYGEN_SHOULD_SKIP_THIS */