Esempio n. 1
0
void install_paint_reference_object(
  WlzObject	*obj)
{
  Widget		toggle;
  WlzPixelV		bckgrnd;
  WlzPixelV		min, max, Min, Max;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  if( globals.orig_obj != NULL ){
    WlzFreeObj( globals.orig_obj );
  }
  globals.orig_obj = WlzAssignObject(obj, &errNum);
  obj = NULL;

  /* check input object for grey-value type
     convert if necessary */
  if( errNum == WLZ_ERR_NONE ){
    bckgrnd = WlzGetBackground(globals.orig_obj, &errNum);
    Min.type = WLZ_GREY_INT;
    Max.type = WLZ_GREY_INT;
    Min.v.inv = 0;
    Max.v.inv = 255;
  }
  
  if( errNum == WLZ_ERR_NONE ){
    switch( bckgrnd.type ){
    case WLZ_GREY_LONG:
      WlzGreyRange(globals.orig_obj, &min, &max);
      if( (min.v.lnv < 0) || (max.v.lnv > 255) ){
	if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){
	  WlzGreySetRange(obj, min, max, Min, Max, 0);
	  bckgrnd = WlzGetBackground(obj, &errNum);
	}
      }
      break;
    case WLZ_GREY_INT:
      WlzGreyRange(globals.orig_obj, &min, &max);
      if( (min.v.inv < 0) || (max.v.inv > 255) ){
	obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum);
	WlzGreySetRange(obj, min, max, Min, Max, 0);
	bckgrnd = WlzGetBackground(obj, &errNum);
      }
      break;
    case WLZ_GREY_SHORT:
      WlzGreyRange(globals.orig_obj, &min, &max);
      if( (min.v.shv < 0) || (max.v.shv > 255) ){
	if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_SHORT, &errNum))){
	  WlzGreySetRange(obj, min, max, Min, Max, 0);
	  bckgrnd = WlzGetBackground(obj, &errNum);
	}
      }
      break;
    case WLZ_GREY_FLOAT:
      WlzGreyRange(globals.orig_obj, &min, &max);
      if( (min.v.flv < 0) || (max.v.flv > 255) ){
	if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){
	  WlzGreySetRange(obj, min, max, Min, Max, 0);
	  bckgrnd = WlzGetBackground(obj, &errNum);
	}
      }
      break;
    case WLZ_GREY_DOUBLE:
      WlzGreyRange(globals.orig_obj, &min, &max);
      if( (min.v.dbv < 0) || (max.v.dbv > 255) ){
	if((obj = WlzConvertPix(globals.orig_obj, WLZ_GREY_INT, &errNum))){
	  WlzGreySetRange(obj, min, max, Min, Max, 0);
	  bckgrnd = WlzGetBackground(obj, &errNum);
	}
      }
      break;

    default:
    case WLZ_GREY_UBYTE:
      break;
    }
  }

  /* copy for later transform for display purposes,
     the original is kept for IP purposes note pixconvert loses
     the background value */
  if( errNum == WLZ_ERR_NONE ){
    if( globals.obj != NULL ){
      WlzFreeObj( globals.obj );
    }
    if( obj ){
      globals.obj =
	WlzAssignObject(WlzConvertPix(obj, WLZ_GREY_UBYTE, &errNum), NULL);
      WlzFreeObj(globals.orig_obj);
      globals.orig_obj = WlzAssignObject(obj, NULL);
    }
    else {
      globals.obj =
	WlzAssignObject(WlzConvertPix(globals.orig_obj,
				      WLZ_GREY_UBYTE, &errNum), NULL);
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    min.type = WLZ_GREY_UBYTE;
    max.type = WLZ_GREY_UBYTE;
    Min.type = WLZ_GREY_UBYTE;
    Max.type = WLZ_GREY_UBYTE;
    min.v.ubv = 0;
    max.v.ubv = 255;
    Min.v.ubv = globals.cmapstruct->gmin;
    Max.v.ubv = globals.cmapstruct->gmax;
    errNum = WlzGreySetRange(globals.obj, min, max, Min, Max, 0);
  }

  /* also convert the background values */
  if( errNum == WLZ_ERR_NONE ){
/*  min = WlzGetBackground(globals.orig_obj, NULL);*/
    WlzValueConvertPixel(&bckgrnd, bckgrnd, WLZ_GREY_INT);
    max.type = WLZ_GREY_INT;
    max.v.inv = ((bckgrnd.v.inv * (Max.v.ubv - Min.v.ubv)) / 255) + Min.v.ubv;
    WlzSetBackground(globals.obj, max);

    /* fill blank planes here - should be a resource option */
    if( (toggle = XtNameToWidget(read_obj_dialog, "*.fill_blanks")) ){
      Boolean	fill_blanks, min_domain;
      XtVaGetValues(toggle, XmNset, &fill_blanks, NULL);
      if( fill_blanks ){
	if( (toggle = XtNameToWidget(read_obj_dialog, "*.min_domain")) ){
	  XtVaGetValues(toggle, XmNset, &min_domain, NULL);
	  if( min_domain ){
	    WlzFillBlankPlanes(globals.obj, 1);
	  } else {
	    WlzFillBlankPlanes(globals.obj, 0);
	  }
	}
	else {
	  WlzFillBlankPlanes(globals.obj, 1);
	}
      }
    }

    /* setup the display list and properties dialog */
    setup_ref_display_list_cb(read_obj_dialog, NULL, NULL);
    setup_obj_props_cb(read_obj_dialog, NULL, NULL);
  }

  /* log the object size */
  if( (errNum == WLZ_ERR_NONE) && globals.logfileFp ){
    char strBuf[64];
    sprintf(strBuf, "(%d, %d, %d, %d, %d, %d)",
	    globals.obj->domain.p->kol1, globals.obj->domain.p->line1,
	    globals.obj->domain.p->plane1, globals.obj->domain.p->lastkl,
	    globals.obj->domain.p->lastln, globals.obj->domain.p->lastpl);
    MAPaintLogData("BoundingBox", strBuf, 0, NULL);
    sprintf(strBuf, "%d", (int) WlzVolume(globals.obj, NULL));
    MAPaintLogData("Volume", strBuf, 0, NULL);
  }

  if( errNum != WLZ_ERR_NONE ){
    MAPaintReportWlzError(globals.topl,
			  "install_paint_reference_object", errNum);
  }
  return;
}
int main(
  int   argc,
  char  **argv)
{
  FILE		*inFile=stdin;
  char 		optList[] = "p:h";
  int		option;
  WlzErrorNum	errNum=WLZ_ERR_NONE;
  /* int	type; */
  WlzObject	*obj, *obj1;
  int		i;
  double	x, y, z, val;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;

  /* read the argument list and check for an input file */
  opterr = 0;
  x = y = z = 0.0;
  while( (option = getopt(argc, argv, optList)) != EOF ){
    switch( option ){

    case 'p':
      if( sscanf(optarg, "%lf,%lf,%lf", &x, &y, &z) != 3 ){
	fprintf(stderr, "%s: not enough values for vertex\n", argv[0]);
	usage(argv[0]);
	return 1;
      }
      break;

    case 't':
      /* type = atoi(optarg); */
      break;

    case 'h':
    default:
      usage(argv[0]);
      return 1;

    }
  }

  /* get objects from stdin */
  if((obj = WlzReadObj(inFile, &errNum)) != NULL){
    switch( obj->type ){
    case WLZ_2D_DOMAINOBJ:
      break;

    case WLZ_3D_DOMAINOBJ: /* to be done */
    default:
      fprintf(stderr, "%s: invalid object type: %d\n", argv[0],
	      obj->type);
      usage(argv[0]);
      return 1;
    }
  }
  else {
    fprintf(stderr, "%s: can't read object\n", argv[0]);
    usage(argv[0]);
    return 1;
  }

  /* scan through object setting distance values
     use integer values */
  if((obj1 = WlzConvertPix(obj, WLZ_GREY_FLOAT, &errNum)) != NULL){
    WlzInitGreyScan(obj1, &iwsp, &gwsp);
    while( WlzNextGreyInterval(&iwsp) == 0 ){

      gptr = gwsp.u_grintptr;
      switch (gwsp.pixeltype) {

      case WLZ_GREY_INT:
	for (i=0; i<iwsp.colrmn; i++, gptr.inp++){
	  val = (iwsp.colpos + i - x)*(iwsp.colpos + i - x) \
	    + (iwsp.linpos - y) * (iwsp.linpos - y);
	  val = sqrt(val);
	  *gptr.flp = WLZ_NINT(val);
	}
	break;

      default:
	/* something gone badly wrong - quit */
	fprintf(stderr, "%s: something wrong, oops\n", argv[0]);
	return 1;
      }
    }
    
    WlzWriteObj(stdout, obj1);
    WlzFreeObj(obj1);
  }

  WlzFreeObj(obj);
  return 0;
}
Esempio n. 3
0
double WlzMixtureValue(
  WlzObject	*obj1,
  WlzObject	*obj2,
  int		numCatRows,
  int		numCatCols,
  double	**mixing,
  double	**contrib,
  WlzErrorNum	*dstErr)
{
  double	val, con;
  WlzObject	*tmpObj, *tmpObj1, *tmpObj2;
  WlzIntervalWSpace	iwsp;
  WlzGreyWSpace		gwsp;
  WlzGreyP		gptr;
  WlzGreyValueWSpace	*gVWSp;
  WlzPixelV		minP, maxP;
  int		i;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* objects must be same type with grey-values */
  if( (obj1 == NULL) || (obj2 == NULL) ){
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else {
    switch( obj1->type ){
    case WLZ_2D_DOMAINOBJ:
      if( obj2->type != obj1->type ){
	errNum = WLZ_ERR_OBJECT_TYPE;
      }
      else {
	if((obj1->values.core == NULL) || (obj2->values.core == NULL)){
	  errNum = WLZ_ERR_VALUES_NULL;
	}
	else {
	  /* convert to int and check range */
	  if((tmpObj1 = WlzConvertPix(obj1, WLZ_GREY_INT, &errNum)) != NULL){
	    errNum = WlzGreyRange(tmpObj1, &minP, &maxP);
	    if( errNum == WLZ_ERR_NONE ){
	      if((minP.v.inv < 1) || (minP.v.inv > numCatRows) ||
		 (maxP.v.inv < 1) || (maxP.v.inv > numCatRows)){
		errNum = WLZ_ERR_OBJECT_DATA;
		WlzFreeObj(tmpObj1);
	      }
	    }
	    else {
	      WlzFreeObj(tmpObj1);
	    }
	  }
	  if((errNum == WLZ_ERR_NONE) &&
	     (tmpObj2 = WlzConvertPix(obj2, WLZ_GREY_INT, &errNum)) ){
	    errNum = WlzGreyRange(tmpObj2, &minP, &maxP);
	    if( errNum == WLZ_ERR_NONE ){
	      if((minP.v.inv < 1) || (minP.v.inv > numCatCols) ||
		 (maxP.v.inv < 1) || (maxP.v.inv > numCatCols)){
		errNum = WLZ_ERR_OBJECT_DATA;
		WlzFreeObj(tmpObj1);
		WlzFreeObj(tmpObj2);
	      }
	    }
	    else {
	      WlzFreeObj(tmpObj1);
	      WlzFreeObj(tmpObj2);
	    }
	  }
	}
      }
      break;

    case WLZ_3D_DOMAINOBJ:
    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }

  /* get the intersection region */
  if( errNum == WLZ_ERR_NONE ){
    if((tmpObj = WlzIntersect2(tmpObj1, tmpObj2, &errNum)) != NULL){
      tmpObj->values = WlzAssignValues(tmpObj1->values, &errNum);
    }
    else {
      WlzFreeObj(tmpObj1);
      WlzFreeObj(tmpObj2);
    }
  }

  /* now calculate the mixture value */
  if( errNum == WLZ_ERR_NONE ){
    errNum = WlzInitGreyScan(tmpObj, &iwsp, &gwsp);
    gVWSp = WlzGreyValueMakeWSp(tmpObj2, &errNum);
    val = 0.0;
    con = 0.0;
    while((errNum == WLZ_ERR_NONE) &&
	  (errNum = WlzNextGreyInterval(&iwsp)) == WLZ_ERR_NONE ){

      gptr = gwsp.u_grintptr;
      for (i=0; i<iwsp.colrmn; i++, gptr.inp++){
	WlzGreyValueGet(gVWSp, 0, iwsp.linpos, iwsp.colpos+i);
	val += mixing[(*gptr.inp)-1][gVWSp->gVal[0].inv-1];
	con += contrib[(*gptr.inp)-1][gVWSp->gVal[0].inv-1];
      }
    }
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }
    WlzGreyValueFreeWSp(gVWSp);
    WlzFreeObj(tmpObj);
    WlzFreeObj(tmpObj1);
    WlzFreeObj(tmpObj2);
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  if( con > 0.0 ){
    return val/con;
  }
  else {
    return 0.0;
  }
}
Esempio n. 4
0
/*! 
* \ingroup      WlzValuesFilters
* \brief        Gaussian filter of grey-level 2D woolz object. x- and
 y-coordinate width parameters and derivative degree can be independently
 specified. For derivative zero, i.e. Gaussian smoothing, the filter is
 normalised. Derivatives are derivative of the normalised filter. RGB
 data will only return values for smoothing, higher derivatives are not
 implemented. The width parameter is the full-width half-height of the
 Gaussian distribution. Note RGB pixel types are converted to a compound 
 object with each channel returned with WLZ_GREY_SHORT pixel type.
*
* \return       Pointer to transformed object
* \param    obj	Input object
* \param    wx	x-direction width parameter
* \param    wy	y-direction width parameter
* \param    x_deriv	x-direction derivative
* \param    y_deriv	y-direction derivative
* \param    wlzErr	error return
* \par      Source:
*                WlzGauss.c
*/
WlzObject *WlzGauss2(
  WlzObject	*obj,
  double	wx,
  double	wy,
  int		x_deriv,
  int		y_deriv,
  WlzErrorNum	*wlzErr)
{
  WlzObject		*newobj=NULL;
  Wlz1DConvMask		x_params, y_params;
  float 		alpha, sum;
  int 			i, n, value;
  WlzErrorNum		errNum=WLZ_ERR_NONE;
    
  /* check object, don't need to check type etc. because WlzSepTrans
     does it */
  if( obj == NULL )
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* do need to check for rgb grey type */
  if( errNum == WLZ_ERR_NONE ){
    if( (obj->type == WLZ_2D_DOMAINOBJ) &&
        (WlzGreyTypeFromObj(obj, &errNum) == WLZ_GREY_RGBA) ){
      if( (x_deriv != 0) || (y_deriv != 0) ){
	/* implement this using a compond object since the
	   result should be a vector value */
	WlzCompoundArray *cobj;

	if((cobj = WlzRGBAToCompound(obj, WLZ_RGBA_SPACE_RGB,
	                             &errNum)) != NULL){
	  /* need to convert each to short for gradient calc */
	  for(i=0; i < 3; i++){
	    WlzObject *tmpObj;
	    tmpObj = cobj->o[i];
	    cobj->o[i] = WlzAssignObject(WlzConvertPix(tmpObj,
						       WLZ_GREY_SHORT,
						       &errNum), NULL);
	    WlzFreeObj(tmpObj);
	  }
	  newobj = WlzGauss2((WlzObject *) cobj, wx, wy, x_deriv, y_deriv,
			     &errNum);
	  WlzFreeObj((WlzObject *) cobj);
	  if( wlzErr ){
	    *wlzErr = errNum;
	  }
	  return newobj;
	}
      }
    }
  }

  /* now start work */
  if( errNum == WLZ_ERR_NONE ){
    alpha = (float )(4.0 * log((double )2.0));
    
    /* set up x function parameters */
    x_params.mask_size = (((int) wx * 4)/2)*2 + 1;
    if( (x_params.mask_values = (int *)
	 AlcMalloc(sizeof(int) * x_params.mask_size)) == NULL){
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else {
      n = x_params.mask_size / 2;
    
      switch( x_deriv ){

      case 0:
	for(i=0, sum = -AFACTOR; i <= n; i++){
	  value = (int )(AFACTOR * exp(((double) -alpha*i*i/wx/wx)));
	  *(x_params.mask_values+n-i) = value;
	  *(x_params.mask_values+n+i) = value;
	  sum += 2 * value;
	}
	x_params.norm_factor = sum;
	break;

      case 1:
	*(x_params.mask_values+n) = 0.0;
	for(i=1, sum = 0; i <= n; i++){
	  value = (int )(AFACTOR * i * exp(((double) -alpha*i*i/wx/wx)));
	  *(x_params.mask_values+n-i) = value;
	  *(x_params.mask_values+n+i) = -value;
	  sum += value;
	}
	/* sum *= -wx / 2 / sqrt( log( (double) 2 ) / WLZ_M_PI );*/
	if( n > 0 )
	  x_params.norm_factor = sum;
	else
	  x_params.norm_factor = 1;
	break;

      case 2:
	for(i=0; i <= n; i++){
	  value = (int )(AFACTOR * (alpha * i*i / wx/wx -1) *
	                 exp(((double) -alpha*i*i/wx/wx)));
	  *(x_params.mask_values+n-i) = value;
	  *(x_params.mask_values+n+i) = value;
	}
	x_params.norm_factor = (int )(*(x_params.mask_values+n) * wx*wx*wx /
	                              4 / alpha / sqrt(log((double )2) /
				      WLZ_M_PI ));
	break;

      default:
	AlcFree((void *) x_params.mask_values);
	x_params.mask_values = NULL;
	errNum = WLZ_ERR_PARAM_DATA;
	break;
      }
    }
  }
    
  /* set up y function parameters */
  if( errNum == WLZ_ERR_NONE ){
    y_params.mask_size = (((int) wy * 4)/2)*2 + 1;
    if( (y_params.mask_values = (int *)
	 AlcMalloc(sizeof(int) * y_params.mask_size)) == NULL){
      AlcFree((void *) x_params.mask_values);
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else {
      n = y_params.mask_size / 2;
    
      switch( y_deriv ){

      case 0:
	for(i=0, sum = -AFACTOR; i <= n; i++){
	  value = (int )(AFACTOR * exp(((double) -alpha*i*i/wy/wy)));
	  *(y_params.mask_values+n-i) = value;
	  *(y_params.mask_values+n+i) = value;
	  sum += 2 * value;
	}
	y_params.norm_factor = sum;
	break;

      case 1:
	*(y_params.mask_values+n) = 0.0;
	for(i=1, sum = 0; i <= n; i++){
	  value = (int )(AFACTOR * i * exp(((double) -alpha*i*i/wy/wy)));
	  *(y_params.mask_values+n-i) = value;
	  *(y_params.mask_values+n+i) = -value;
	  sum += value;
	}
	/* sum *= -wy / 2 / sqrt( log( (double) 2 ) /WLZ_M_PI );*/
	if( n > 0 )
	  y_params.norm_factor = sum;
	else
	  y_params.norm_factor = 1;
	break;

      case 2:
	for(i=0; i <= n; i++){
	  value = (int )(AFACTOR * (alpha * i*i / wy/wy -1) *
	                 exp(((double) -alpha*i*i/wy/wy)));
	  *(y_params.mask_values+n-i) = value;
	  *(y_params.mask_values+n+i) = value;
	}
	y_params.norm_factor = (int )(*(y_params.mask_values+n) * wy*wy*wy / 4 / alpha
	  / sqrt( log( (double) 2 ) / WLZ_M_PI ));
	break;

      default:
	AlcFree((void *) x_params.mask_values);
	AlcFree((void *) y_params.mask_values);
	x_params.mask_values = NULL;
	y_params.mask_values = NULL;
	errNum = WLZ_ERR_PARAM_DATA;
	break;
      }
    }
  }

  if( errNum == WLZ_ERR_NONE ){
    newobj = WlzSepTrans(obj,
			 Wlz1DConv, (void *) &x_params,
			 Wlz1DConv, (void *) &y_params,
			 &errNum);
    AlcFree((void *) x_params.mask_values);
    AlcFree((void *) y_params.mask_values);
  }

  if( wlzErr )
  {
    *wlzErr = errNum;
  }
  return(newobj);
}
Esempio n. 5
0
/*!
* \return	New filtered object with new values or NULL on error.
* \ingroup	WlzValuesFilters
* \brief	Applies a seperable filter to the given object using the given
* 		convolution kernels.
* \param	inObj			Input 2 or 3D spatial domain object
* 					to be filtered which must have scalar
* 					values.
* \param	cBufSz			Convolution kernel sizes (sz), each
* 					kernel buffer is sized (2 * sz) + 1
* 					with the centre indexed sz into the
* 					buffer.
* \param	cBuf			Convolution kernel buffers.
* \param	direc			Set to non-zero in directions for which
* 					the filter is to be applied.
* \param	gType			Required return object grey type.
* 					Passing in WLZ_GREY_ERROR will
* 					request the given input object's grey
* 					type.
* \param	pad			Type of padding.
* \param	padVal			Padding value, only used when
* 					pad == ALG_PAD_VALUE.
* \param	dstErr			Destination error pointer may be NULL.
*/
WlzObject			*WlzSepFilter(WlzObject *inObj,
				  WlzIVertex3 cBufSz,
				  double *cBuf[],
				  WlzIVertex3 direc,
				  WlzGreyType gType,
				  AlgPadType pad,
				  double padVal,
				  WlzErrorNum *dstErr)
{
  int		dim = 0,
  		vSz = 0,
  		nThr = 1;
  double	**iBuf = NULL,
  		**rBuf = NULL;
  double	*vBuf = NULL;
  WlzObject	*rnObj = NULL;
  WlzIVertex3	vBufSz = {0};
  WlzIBox3	bBox = {0};
  WlzErrorNum	errNum = WLZ_ERR_NONE;

#ifdef _OPENMP
#pragma omp parallel
  {
#pragma omp master
    {
      nThr = omp_get_num_threads();
    }
  }
#endif
  if(inObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(inObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(inObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else
  {
    switch(inObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
        dim = 2;
	break;
      case WLZ_3D_DOMAINOBJ:
        dim = 3;
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if((errNum == WLZ_ERR_NONE) && (gType == WLZ_GREY_ERROR))
  {
    gType = WlzGreyTypeFromObj(inObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(errNum == WLZ_ERR_NONE)
    {
      switch(gType)
      {
        case WLZ_GREY_INT:    /* FALLTHROUGH */
        case WLZ_GREY_SHORT:  /* FALLTHROUGH */
        case WLZ_GREY_UBYTE:  /* FALLTHROUGH */
        case WLZ_GREY_FLOAT:  /* FALLTHROUGH */
        case WLZ_GREY_DOUBLE:
	  break;
        default:
	  errNum = WLZ_ERR_GREY_TYPE;
	  break;
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    bBox = WlzBoundingBox3I(inObj, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      vBufSz.vtX = bBox.xMax - bBox.xMin + 1;
      vBufSz.vtY = bBox.yMax - bBox.yMin + 1;
      if(dim == 3)
      {
	vBufSz.vtZ = bBox.zMax - bBox.zMin + 1;
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    vSz = ALG_MAX3(vBufSz.vtX, vBufSz.vtY, vBufSz.vtZ);
    if(((iBuf = (double **)AlcMalloc(sizeof(double *) * 2 * nThr)) == NULL) ||
       ((vBuf = (double *)AlcMalloc(sizeof(double) * 2 * nThr * vSz)) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
    else
    {
      int	idt;

      rBuf = iBuf + nThr;
      for(idt = 0; idt < nThr; ++idt)
      {
        iBuf[idt] = vBuf + (idt * vSz);
	rBuf[idt] = vBuf + ((nThr + idt) * vSz);
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Convolve the object values. */
    if(direc.vtX)
    {
      rnObj = WlzSepFilterX(inObj, dim, nThr,
			    iBuf, rBuf, cBufSz.vtX, cBuf[0],
			    pad, padVal, &errNum);
    }
    if((errNum == WLZ_ERR_NONE) && direc.vtY)
    {
      WlzObject *tObj;

      tObj = WlzSepFilterY((rnObj)? rnObj: inObj, dim, nThr,
                            iBuf, rBuf, cBufSz.vtY, cBuf[1],
			    pad, padVal, &errNum);
      (void )WlzFreeObj(rnObj);
      rnObj = tObj;
    }
    if((errNum == WLZ_ERR_NONE) && (dim == 3) && direc.vtZ)
    {
      WlzObject *tObj;

      tObj = WlzSepFilterZ((rnObj)? rnObj: inObj, bBox, nThr,
                            iBuf, rBuf, cBufSz.vtZ, cBuf[2],
			    pad, padVal, &errNum);
      (void )WlzFreeObj(rnObj);
      rnObj = tObj;
    }
  }
  if((errNum == WLZ_ERR_NONE) && (rnObj != NULL) && (gType != WLZ_GREY_DOUBLE))
  {
    WlzObject *tObj;

    /* Convert object values to the required grey type. */
    tObj = WlzConvertPix((rnObj)? rnObj: inObj, gType, &errNum);
    (void )WlzFreeObj(rnObj);
    rnObj = tObj;
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(rnObj);
    rnObj = NULL;
  }
  AlcFree(iBuf);
  AlcFree(vBuf);
  return(rnObj);
}
Esempio n. 6
0
static WlzObject *WlzGreyTemplate3d(
  WlzObject	*obj,
  WlzObject	*tmpl,
  WlzPixelV	tmplVal,
  WlzErrorNum	*dstErr)
{
  WlzObject	*rtnObj=NULL;
  WlzObject	*tmpObj = NULL, *obj1 = NULL, *obj2 = NULL;
  WlzDomain	domain, *domains;
  WlzValues	values, *valuess;
  WlzPlaneDomain	*pdom;
  int		p;
  WlzErrorNum	errNum=WLZ_ERR_NONE;

  /* check the object - it is non-NULL and 3D but the
     domain needs checking */
  if( obj->domain.p == NULL ){
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else {
    switch( obj->domain.p->type ){
    case WLZ_2D_DOMAINOBJ:
      /* check there is a valuetable */
      if( obj->values.core == NULL ){
	errNum = WLZ_ERR_VALUES_NULL;
      } else if( WlzGreyTableIsTiled(obj->values.core->type) ){
	errNum = WLZ_ERR_VALUES_TYPE;
      }
      break;

    default:
      errNum = WLZ_ERR_DOMAIN_TYPE;
      break;
    }
  }

  /* check the template and create the return object */
  if( errNum == WLZ_ERR_NONE ){
    if( tmpl == NULL ){
      errNum = WLZ_ERR_OBJECT_NULL;
    }
    else {
      values.core = NULL;
      switch( tmpl->type ){
      case WLZ_2D_DOMAINOBJ:
	pdom = obj->domain.p;
	if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					  pdom->plane1, pdom->lastpl,
					  pdom->line1, pdom->lastpl,
					  pdom->kol1, pdom->lastkl,
					  &errNum)) != NULL){
	  domain.p->voxel_size[0] = pdom->voxel_size[0];
	  domain.p->voxel_size[1] = pdom->voxel_size[1];
	  domain.p->voxel_size[2] = pdom->voxel_size[2];
	  for(p=pdom->plane1; p <= pdom->lastpl; p++){
	    domain.p->domains[p - pdom->plane1] = WlzAssignDomain(tmpl->domain,
								  NULL);
	  }
	  rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, &errNum);
	}
	break;

      case WLZ_2D_POLYGON:
	pdom = obj->domain.p;
	if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					  pdom->plane1, pdom->lastpl,
					  pdom->line1, pdom->lastpl,
					  pdom->kol1, pdom->lastkl,
					  &errNum)) != NULL){
	  domain.p->voxel_size[0] = pdom->voxel_size[0];
	  domain.p->voxel_size[1] = pdom->voxel_size[1];
	  domain.p->voxel_size[2] = pdom->voxel_size[2];
	  obj1 = WlzPolyToObj(tmpl->domain.poly, WLZ_SIMPLE_FILL, &errNum);
	  for(p=pdom->plane1; p <= pdom->lastpl; p++){
	    domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain,
								  NULL);
	  }
	  WlzFreeObj(obj1);
	  rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, &errNum);
	}
	break;

      case WLZ_BOUNDLIST:
	pdom = obj->domain.p;
	if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					  pdom->plane1, pdom->lastpl,
					  pdom->line1, pdom->lastpl,
					  pdom->kol1, pdom->lastkl,
					  &errNum)) != NULL){
	  domain.p->voxel_size[0] = pdom->voxel_size[0];
	  domain.p->voxel_size[1] = pdom->voxel_size[1];
	  domain.p->voxel_size[2] = pdom->voxel_size[2];
	  obj1 = WlzBoundToObj(tmpl->domain.b, WLZ_SIMPLE_FILL, &errNum);
	  for(p=pdom->plane1; p <= pdom->lastpl; p++){
	    domain.p->domains[p - pdom->plane1] = WlzAssignDomain(obj1->domain,
								  NULL);
	  }
	  WlzFreeObj(obj1);
	  rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
			       NULL, NULL, &errNum);
	}
	break;

      case WLZ_3D_DOMAINOBJ:
	if( tmpl->domain.p ){
	  switch( tmpl->domain.p->type ){
	  case WLZ_2D_DOMAINOBJ:
	    domain.p = tmpl->domain.p;
	    break;

	  case WLZ_PLANEDOMAIN_POLYGON:
	  case WLZ_PLANEDOMAIN_CONV_HULL:
	    pdom = tmpl->domain.p;
	    if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					      pdom->plane1, pdom->lastpl,
					      pdom->line1, pdom->lastpl,
					      pdom->kol1, pdom->lastkl,
					      &errNum)) != NULL){
	      domain.p->voxel_size[0] = pdom->voxel_size[0];
	      domain.p->voxel_size[1] = pdom->voxel_size[1];
	      domain.p->voxel_size[2] = pdom->voxel_size[2];
	      for(p=pdom->plane1; p <= pdom->lastpl; p++){
		if( pdom->domains[p-pdom->plane1].core ){
		  obj1 = WlzPolyToObj(pdom->domains[p-pdom->plane1].poly,
				      WLZ_SIMPLE_FILL, &errNum);
		  domain.p->domains[p - pdom->plane1] =
		    WlzAssignDomain(obj1->domain, NULL);
		}
		WlzFreeObj(obj1);
	      }
	      values.core = NULL;
	      rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
				   NULL, NULL, &errNum);
	    }
	    break;

	  case WLZ_PLANEDOMAIN_BOUNDLIST:
	    pdom = tmpl->domain.p;
	    if((domain.p = WlzMakePlaneDomain(WLZ_PLANEDOMAIN_DOMAIN,
					      pdom->plane1, pdom->lastpl,
					      pdom->line1, pdom->lastpl,
					      pdom->kol1, pdom->lastkl,
					      &errNum)) != NULL){
	      domain.p->voxel_size[0] = pdom->voxel_size[0];
	      domain.p->voxel_size[1] = pdom->voxel_size[1];
	      domain.p->voxel_size[2] = pdom->voxel_size[2];
	      for(p=pdom->plane1; p <= pdom->lastpl; p++){
		if( pdom->domains[p-pdom->plane1].core ){
		  obj1 = WlzBoundToObj(pdom->domains[p-pdom->plane1].b,
				      WLZ_SIMPLE_FILL, &errNum);
		  domain.p->domains[p - pdom->plane1] =
		    WlzAssignDomain(obj1->domain, NULL);
		}
		WlzFreeObj(obj1);
	      }
	      values.core = NULL;
	      rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
				   NULL, NULL, &errNum);
	    }
	    break;

	  default:
	    errNum = WLZ_ERR_DOMAIN_TYPE;
	    break;
	  }
	  if( errNum == WLZ_ERR_NONE ){
	    rtnObj = WlzMakeMain(WLZ_3D_DOMAINOBJ, domain, values,
				 NULL, NULL, &errNum);
	  }
	}
	else {
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	break;

      case WLZ_EMPTY_OBJ:
	return WlzMakeEmpty(dstErr);

      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
      }
    }
  }

  /* now we have a 3D obj and 3D template so run through the template
     and map values as required, note we must check that all the valuetables
     have the same type ie switch to obj type if necessary */
  if( errNum == WLZ_ERR_NONE ){
    WlzDomain	*objDoms;
    WlzValues	*objVals;
    WlzGreyType	gtype=WLZ_GREY_UBYTE;

    /* attach a voxel table with empty values list */
    values.vox = WlzMakeVoxelValueTb(obj->values.vox->type,
				     rtnObj->domain.p->plane1,
				     rtnObj->domain.p->lastpl,
				     obj->values.vox->bckgrnd,
				     NULL, NULL);
    rtnObj->values = WlzAssignValues(values, NULL);

    /* set some local variables */
    pdom = rtnObj->domain.p;
    domains = rtnObj->domain.p->domains;
    valuess = rtnObj->values.vox->values;
    objDoms = obj->domain.p->domains;
    objVals = obj->values.vox->values;

    /* calculate the new valuetables */
    for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
      if(((*domains).core)){
	if((p >= obj->domain.p->plane1) &&
	   (p <= obj->domain.p->lastpl) &&
	   (objDoms[p - obj->domain.p->plane1].core) ){
	  tmpObj = WlzMakeMain(WLZ_2D_DOMAINOBJ,
				objDoms[p - obj->domain.p->plane1],
				objVals[p - obj->domain.p->plane1],
				NULL, NULL, NULL);
	  gtype = WlzGreyTableTypeToGreyType(tmpObj->values.core->type, NULL);
	}
	else {
	  tmpObj = WlzMakeEmpty(NULL);
	}
	tmpObj = WlzAssignObject(tmpObj, NULL);
	values.core = NULL;
	obj1 = WlzAssignObject(
	  WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, values,
		      NULL, NULL, NULL), NULL);
	if((obj2 = WlzGreyTemplate(tmpObj, obj1, tmplVal, &errNum)) != NULL){
	  *valuess = WlzAssignValues(obj2->values, NULL);
	  WlzFreeObj(obj2);
	}
	WlzFreeObj(obj1);
	WlzFreeObj(tmpObj);
      }
    }

    /* now check all valuetables have the same grey type */
    domains = rtnObj->domain.p->domains;
    valuess = rtnObj->values.vox->values;
    for(p=pdom->plane1; p <= pdom->lastpl; p++, domains++, valuess++){
      if((*domains).core &&
	 (WlzGreyTableTypeToGreyType((*valuess).core->type, NULL) != gtype)){
	obj1 = WlzAssignObject(
	  WlzMakeMain(WLZ_2D_DOMAINOBJ, *domains, *valuess,
		      NULL, NULL, NULL), NULL);
	if((obj2 = WlzConvertPix(obj1, gtype, &errNum)) != NULL){
	  /* substitute the valuetable in the voxel table array */
	  WlzFreeValues(*valuess);
	  *valuess = WlzAssignValues(obj2->values, NULL);
	  WlzFreeObj(obj2);
	}
	WlzFreeObj(obj1);
      }
    }
  }

  if( dstErr ){
    *dstErr = errNum;
  }
  return rtnObj;
}
Esempio n. 7
0
/*! 
* \ingroup      WlzValuesUtils
* \brief        Calculate the modulus of the grey-level gradient at each
 point. The gradient images are calculated using WlzGauss2() with width
parameter set to <tt>width</tt>. Will now calculate the modulus for each
object of a compound object if appropriate. 
*
* \return       Object with values set to the gradient modulus at each pixel.
* \param    obj	Input object.
* \param    width	Width parameter for the gaussian gradient operator.
* \param    dstErr	Error return.
* \par      Source:
*                WlzGreyModGradient.c
*/
WlzObject *WlzGreyModGradient(
  WlzObject	*obj,
  double	width,
  WlzErrorNum	*dstErr)
{
  WlzObject		*xobj, *yobj, *returnobj=NULL;
  WlzIntervalWSpace	iwsp1, iwsp2, iwsp3;
  WlzGreyWSpace		gwsp1, gwsp2, gwsp3;
  WlzCompoundArray	*cobj1, *cobj2;
  int			i;
  double		g1, g2, g3;
  WlzErrorNum		errNum=WLZ_ERR_NONE;

  /* check object */
  if( obj ){
    switch( obj->type ){
    case WLZ_2D_DOMAINOBJ:
      if( obj->domain.core ){
	switch( obj->domain.core->type ){
	case WLZ_EMPTY_DOMAIN:
	  returnobj = WlzMakeEmpty(&errNum);
	  break;

	default:
	  if( obj->values.core ){
	    if( (obj->values.core->type == WLZ_EMPTY_VALUES) ||
	        WlzGreyTableIsTiled(obj->values.core->type) ){
	      errNum = WLZ_ERR_VALUES_TYPE;
	    }
	  }
	  else {
	    errNum = WLZ_ERR_VALUES_NULL;
	  }
	  break;
	}
      }
      else {
	errNum = WLZ_ERR_DOMAIN_NULL;
      }
      /* one last check for rgb values */
      if(WlzGreyTableTypeToGreyType(obj->values.core->type, NULL)
	 == WLZ_GREY_RGBA){
	return WlzRGBAModGradient(obj, width, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      returnobj = WlzMakeEmpty(&errNum);
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      cobj1 = (WlzCompoundArray *) obj;
      if((cobj2 = WlzMakeCompoundArray(cobj1->type, 1, cobj1->n, NULL,
				       cobj1->otype, &errNum)) != NULL){
	/* transform each object, ignore type errors */
	for(i=0; i < cobj1->n; i++){
	  cobj2->o[i] =
	    WlzAssignObject(WlzGreyModGradient(cobj1->o[i],
					       width, &errNum), NULL);
	}
	return (WlzObject *) cobj2;
      }
      break;

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }
  else {
    errNum = WLZ_ERR_OBJECT_NULL;
  }

  /* if WlzUByte grey values then copy to int */
  if( (errNum == WLZ_ERR_NONE) && !returnobj ){
    if(WlzGreyTableTypeToGreyType(obj->values.core->type,
                                  NULL) == WLZ_GREY_UBYTE)
    {
      returnobj = WlzConvertPix(obj, WLZ_GREY_INT, NULL);
    }
    else
    {
      returnobj = WlzMakeMain(WLZ_2D_DOMAINOBJ, obj->domain,
			      WlzCopyValues(obj->type, obj->values,
					    obj->domain, &errNum),
			      NULL, NULL, NULL);
    }

    /* calculate gradient images */
    xobj = WlzGauss2(returnobj, width, width, 1, 0, NULL);
    yobj = WlzGauss2(returnobj, width, width, 0, 1, NULL);

    /* calculate modulus  - lockstep raster scan assumes equal domains */
    errNum = WlzInitGreyScan(returnobj, &iwsp1, &gwsp1);
    errNum = WlzInitGreyScan(xobj, &iwsp2, &gwsp2);
    errNum = WlzInitGreyScan(yobj, &iwsp3, &gwsp3);
    while((errNum == WLZ_ERR_NONE) && 
	  (WlzNextGreyInterval(&iwsp1) == WLZ_ERR_NONE) )
    {
      (void) WlzNextGreyInterval(&iwsp2);
      (void) WlzNextGreyInterval(&iwsp3);

      switch( gwsp1.pixeltype )
      {
      default:
      case WLZ_GREY_INT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.inp++;
	  g3 = *gwsp3.u_grintptr.inp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.inp++ = (int) g1;
	}
	break;

      case WLZ_GREY_SHORT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.shp++;
	  g3 = *gwsp3.u_grintptr.shp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.shp++ = (short) g1;
	}
	break;

      case WLZ_GREY_UBYTE:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.ubp++;
	  g3 = *gwsp3.u_grintptr.ubp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.ubp++ = (WlzUByte) g1;
	}
	break;

      case WLZ_GREY_FLOAT:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.flp++;
	  g3 = *gwsp3.u_grintptr.flp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.flp++ = (float) g1;
	}
	break;

      case WLZ_GREY_DOUBLE:
	for(i=0; i < iwsp1.colrmn; i++)
	{
	  g2 = *gwsp2.u_grintptr.dbp++;
	  g3 = *gwsp3.u_grintptr.dbp++;
	  g1 = sqrt( g2*g2 + g3*g3 );
	  *gwsp1.u_grintptr.dbp++ = (double) g1;
	}
	break;

      case WLZ_GREY_RGBA: /* RGBA to be done - should not get here */
	errNum = WLZ_ERR_GREY_TYPE;
	break;

      }
    }

    /* check for normal return */
    if( errNum == WLZ_ERR_EOO ){
      errNum = WLZ_ERR_NONE;
    }

    /* clean up */
    WlzFreeObj( xobj );
    WlzFreeObj( yobj );
  }

  /* check error return */
  if( dstErr ){
    *dstErr = errNum;
  }
  return( returnobj );
}
Esempio n. 8
0
int             main(int argc, char *argv[])
{
  int		option,
		nReg = 0,
		tNReg = 0,
  		ok = 1,
		usage = 0,
		verbose = 0,
		threshSet = 0,
		centreSet = 0;
  double	minArea = 2;
  char		*inExt,
		*dbgExt,
		*inDir,
		*dbgDir,
		*inFile,
		*dbgFile,
  		*inPath = NULL,
		*dbgPath = NULL,
		*outFile = NULL;
  WlzRadDistVal distSort = WLZ_RADDISTVAL_AREA;
  WlzRadDistRec	*distData = NULL;
  WlzPixelV	thrVal;
  WlzDVertex2	centre;
  WlzCompThreshType thrMtd = WLZ_COMPTHRESH_OTSU;
  WlzThresholdType thrMod = WLZ_THRESH_HIGH;
  WlzEffFormat	inFmt = WLZEFF_FORMAT_NONE,
  		dbgFmt = WLZEFF_FORMAT_NONE;
  WlzObject	*inObj = NULL,
		*disObj = NULL,
  		*segObj = NULL;
  WlzGreyValueWSpace *disGVWSp = NULL;
  WlzObject	**regObjs = NULL;
  FILE		*fP = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	maxObj = 1000000;
  char		pathBuf[FILENAME_MAX];
  const double	eps = 1.0e-06;
  const char	*errMsg;
  static char	optList[] = "hvAGDHELR:c:d:n:o:t:",
		defFile[] = "-";

  thrVal.type = WLZ_GREY_DOUBLE;
  thrVal.v.dbv = 0.0;
  outFile = defFile;
  while((usage == 0) && ok &&
        ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case 'A':
        distSort = WLZ_RADDISTVAL_AREA;
	break;
      case 'D':
        distSort = WLZ_RADDISTVAL_DIST;
	break;
      case 'G':
        distSort = WLZ_RADDISTVAL_ANGLE;
	break;
      case 'H':
        thrMod = WLZ_THRESH_HIGH;
	break;
      case 'E':
        thrMod = WLZ_THRESH_EQUAL;
	break;
      case 'L':
        thrMod = WLZ_THRESH_LOW;
	break;
      case 'R':
        distSort = WLZ_RADDISTVAL_RADIUS;
	break;
      case 'h':
        usage = 1;
	break;
      case 'v':
        verbose = 1;
	break;
      case 'c':
	centreSet = 1;
        if(sscanf(optarg, "%lg,%lg", &(centre.vtX), &(centre.vtY)) != 2)
	{
	  usage = 1;
	}
        break;
      case 'd':
        dbgPath = optarg;
	break;
      case 'o':
        outFile = optarg;
	break;
      case 'n':
        if(sscanf(optarg, "%lg", &minArea) != 1)
	{
	  usage = 1;
	}
	break;
      case 't':
	threshSet = 1;
        if(sscanf(optarg, "%lg", &(thrVal.v.dbv)) != 1)
	{
	  usage = 1;
	}
	break;
      default:
        usage = 1;
	break;
    }
  }
  ok = !usage;
  if(ok)
  {
    if((optind + 1) != argc)
    {
      usage = 1;
      ok = 0;
    }
    else
    {
      inPath = *(argv + optind);
    }
  }
  if(ok && verbose)
  {
    (void )fprintf(stderr, "inPath = %s\n", inPath);
  }
  /* Parse input file path into path + name + ext. */
  if(ok)
  {
    ok = (usage = WlzRadDistParsePath(inPath, &inDir, &inFile, &inExt,
                                      &inFmt)) == 0;
  }
  if(ok && verbose)
  {
    (void )fprintf(stderr, "inDir = %s\n", inDir);
    (void )fprintf(stderr, "inFile = %s\n", inFile);
    (void )fprintf(stderr, "inExt = %s\n", (inExt)? inExt: "(null)");
    (void )fprintf(stderr, "inFmt = %s\n",
    		   WlzEffStringFromFormat(inFmt, NULL));
  }
  /* Read image. */
  if(ok)
  {
    errNum = WLZ_ERR_READ_EOF;
    if(inExt)
    {
      (void )sprintf(pathBuf, "%s/%s.%s", inDir, inFile, inExt);
    }
    else
    {
      (void )sprintf(pathBuf, "%s/%s", inDir, inFile);
    }
    if(((inObj = WlzAssignObject(WlzEffReadObj(NULL, pathBuf, inFmt,
    					       0, 0, 0,
					       &errNum), NULL)) == NULL) ||
       (inObj->type != WLZ_2D_DOMAINOBJ))
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
      		     "%s: Failed to read 2D image object from file %s (%s)\n",
		     *argv, pathBuf, errMsg);
    }
  }
  if(ok && verbose)
  {
    (void )fprintf(stderr, "read input image ok.\n");
  }
  /* Convert to grey if needed, normalise 0 - 255 if needed and compute
   * threshold value unless already known. */
  if(ok)
  {
    if(WlzGreyTypeFromObj(inObj, NULL) == WLZ_GREY_RGBA)
    {
      WlzObject *ppObj;

      ppObj = WlzAssignObject(
	      WlzRGBAToModulus(inObj, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
	(void )WlzFreeObj(inObj);
	inObj = ppObj;
      }
    }
    if(threshSet == 0)
    {
      WlzObject *hObj = NULL;

      errNum = WlzGreyNormalise(inObj, 1);
      if(errNum == WLZ_ERR_NONE)
      {
        hObj = WlzHistogramObj(inObj, 256, 0.0, 1.0, &errNum);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	threshSet = 1;
        errNum = WlzCompThreshold(&thrVal.v.dbv, hObj, thrMtd, 0);
      }
      (void )WlzFreeObj(hObj);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to normalise object (%s)\n",
		     *argv, errMsg);
    }
  }
  /* Segment the object. */
  if(ok)
  {
    if(inObj->values.core == NULL)
    {
      segObj = WlzAssignObject(inObj, NULL);
    }
    else
    {
      segObj = WlzAssignObject(
               WlzThreshold(inObj, thrVal, thrMod, &errNum), NULL);
      if(errNum != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr, "%s: failed to segment image (%s)\n",
		       *argv, errMsg);
      }
    }
  }
  /* Compute object with the same domain as the input object but in which
   * the values are the minimum distance from an edge. */
  if(ok)
  {
    WlzObject	*bObj = NULL;

    bObj = WlzBoundaryDomain(inObj, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      disObj = WlzAssignObject(       
               WlzDistanceTransform(inObj, bObj, WLZ_OCTAGONAL_DISTANCE,
	       			    0.0, 0.0, &errNum), NULL);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      disGVWSp = WlzGreyValueMakeWSp(disObj, &errNum);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to compute distance object (%s)\n",
		     *argv, errMsg);
    }
    (void )WlzFreeObj(bObj);
  }
  /* Output the debug image if required. */
  if(ok && dbgPath)
  {
    WlzObject	*dbgObj;

    dbgObj = WlzAssignObject(WlzCopyObject(inObj, &errNum), NULL);
    if(errNum == WLZ_ERR_NONE)
    {
      WlzPixelV	iMin,
		iMax,
		oMin,
		oMax;

      if(dbgObj->values.core == NULL)
      {
        WlzValues tmpVal;

	oMax.type = WLZ_GREY_UBYTE;
	oMax.v.ubv = 255;
	tmpVal.v = WlzNewValueTb(dbgObj,
				 WlzGreyTableType(WLZ_GREY_TAB_RAGR,
				                  WLZ_GREY_UBYTE, NULL),
	                         oMax, &errNum);
        if(errNum == WLZ_ERR_NONE)
	{
	  dbgObj->values = WlzAssignValues(tmpVal, NULL);
	}
      }
      else
      {
        WlzObject *tmpObj = NULL;

	oMin.type = WLZ_GREY_UBYTE;
	oMin.v.ubv = 0;
	oMax.type = WLZ_GREY_UBYTE;
	oMax.v.ubv = 200;
	errNum = WlzGreyRange(dbgObj, &iMin, &iMax);
	if(errNum == WLZ_ERR_NONE)
	{
	  errNum = WlzGreySetRange(dbgObj, iMin, iMax, oMin, oMax, 0);
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  tmpObj = WlzMakeMain(inObj->type, segObj->domain, dbgObj->values,
	                       NULL, NULL, &errNum);
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  oMax.v.ubv = 255;
	  errNum = WlzGreySetValue(tmpObj, oMax);
	}
	(void )WlzFreeObj(tmpObj);
	if(errNum == WLZ_ERR_NONE)
	{
	  tmpObj = WlzConvertPix(dbgObj, WLZ_GREY_UBYTE, &errNum);
	  (void )WlzFreeObj(dbgObj);
	  dbgObj = WlzAssignObject(tmpObj, NULL);
	}
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      (void )WlzRadDistParsePath(dbgPath, &dbgDir, &dbgFile, &dbgExt,
      			         &dbgFmt);
      if(dbgExt)
      {
	(void )sprintf(pathBuf, "%s/%s.%s", dbgDir, dbgFile, dbgExt);
      }
      else
      {
	(void )sprintf(pathBuf, "%s/%s", dbgDir, dbgFile);
      }
      errNum = WlzEffWriteObj(NULL, pathBuf, dbgObj, dbgFmt);
    }
    (void )WlzFreeObj(dbgObj);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to output the debug image (%s)\n",
		     *argv, errMsg);
    }
  }
  /* Label the segmented object. */
  if(ok)
  {
    errNum = WlzLabel(segObj, &nReg, &regObjs, maxObj, 0, WLZ_8_CONNECTED);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      errNum = WLZ_ERR_MEM_ALLOC;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to split into components (%s)\n",
		     *argv, errMsg);
    }
    if(ok && verbose)
    {
      (void )fprintf(stderr, "nReg = %d\n", nReg);
    }
  }
  /* Compute centre of mass if not known. */
  if(ok)
  {
    if(centreSet == 0)                          
    {
      centre = WlzCentreOfMass2D(inObj, 1, NULL, &errNum);
      if(errNum != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr, "%s: failed to compute centre of mass (%s)\n",
		       *argv, errMsg);
      }
    }
    if(ok && verbose)
    {
      (void )fprintf(stderr, "centre = %lg,%lg\n", centre.vtX, centre.vtY);
    }
  }
  /* Allocate a radial distribution table. */
  if(ok)
  {
    if((distData = (WlzRadDistRec *)
                   AlcCalloc(nReg, sizeof(WlzRadDistRec))) == NULL)
    {
      ok = 0;
      errNum = WLZ_ERR_MEM_ALLOC;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr, "%s: failed to allocate result lable (%s)\n",
		     *argv, errMsg);
    }
    
  }
  /* Compute the redial distribution data. */
  if(ok)
  {
    int		idR = 0,
    		idS = 0;

    while((errNum == WLZ_ERR_NONE) && (idR < nReg))
    {
      double	mass;
      WlzDVertex2 com;

      com = WlzCentreOfMass2D(regObjs[idR], 1, &mass, NULL);
      if(mass > minArea - eps)
      {
	WlzGreyValueGet(disGVWSp, 0.0, com.vtY, com.vtX);
	distData[idS].pos = com;
	distData[idS].area = mass;
	WLZ_VTX_2_SUB(com, centre, com);
	distData[idS].radius = WLZ_VTX_2_LENGTH(com);
	distData[idS].angle = ALG_M_PI + atan2(com.vtY, com.vtX);
	switch(disGVWSp->gType)
	{
	  case WLZ_GREY_LONG:
	    distData[idS].dist = *(disGVWSp->gPtr[0].lnp);
	    break;
	  case WLZ_GREY_INT:
	    distData[idS].dist = *(disGVWSp->gPtr[0].inp);
	    break;
	  case WLZ_GREY_SHORT:
	    distData[idS].dist = *(disGVWSp->gPtr[0].shp);
	    break;
	  case WLZ_GREY_UBYTE:
	    distData[idS].dist = *(disGVWSp->gPtr[0].ubp);
	    break;
	  case WLZ_GREY_FLOAT:
	    distData[idS].dist = *(disGVWSp->gPtr[0].flp);
	    break;
	  case WLZ_GREY_DOUBLE:
	    distData[idS].dist = *(disGVWSp->gPtr[0].dbp);
	    break;
	  default:
	    distData[idS].dist = 0.0;
	    break;
	}
	++idS;
      }
      ++idR;
    }
    tNReg = idS;
    switch(distSort)
    {
      case WLZ_RADDISTVAL_AREA:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec),
		     WlzRadDistRecSortArea);
	break;
      case WLZ_RADDISTVAL_ANGLE:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec), 
		     WlzRadDistRecSortAngle);
	break;
      case WLZ_RADDISTVAL_RADIUS:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec),
		     WlzRadDistRecSortRadius);
	break;
      case WLZ_RADDISTVAL_DIST:
        (void )qsort(distData, tNReg, sizeof(WlzRadDistRec),
		     WlzRadDistRecSortDist);
	break;
    }
  }
  /* Output the sorted radial distribution table. */
  if(ok)
  {
    if(((fP = strcmp(outFile, "-")?
              fopen(outFile, "w"): stdout)) == NULL)
    {
      ok = 0;
      (void )fprintf(stderr, "%s: failed to open output file %s\n",
                     *argv, outFile);
    }
  }
  if(ok)
  {
    int		idR;

    for(idR = 0; idR < tNReg; ++idR)
    {
      double a;

      a = (distData[idR].angle > 0.0)?
	  0   + (180 * distData[idR].angle / ALG_M_PI):
          360 + (180 * distData[idR].angle / ALG_M_PI);
      (void )fprintf(fP, "%g %g %g %g,%g %g\n",
		     a,
                     distData[idR].radius,
		     distData[idR].area,
		     distData[idR].pos.vtX,
		     distData[idR].pos.vtY,
		     distData[idR].dist);
    }
  }
  if(strcmp(outFile, "-"))
  {
    (void )fclose(fP);
  }
  /* Tidy up. */
  AlcFree(distData);
  WlzGreyValueFreeWSp(disGVWSp);
  (void )WlzFreeObj(inObj);
  (void )WlzFreeObj(disObj);
  (void )WlzFreeObj(segObj);
  if(regObjs)
  {
    int		idR;

    for(idR = 0; idR < nReg; ++idR)
    {
      (void )WlzFreeObj(regObjs[idR]);
    }
    AlcFree(regObjs);
  }
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s [-h] [-v] [-A] [-D] [-G] [-H] [-E] [-L] [-R]\n"
    "\t\t[-c #,#] [-d <debug image>] [-n #]  [-o <out file>]\n"
    "\t\t[-t #] [<input image>]\n"
    "Segments the given object using a threshold value and outputs the \n"
    "radial distribution of the thresholded components.\n"
    "Version: %s\n"
    "Options:\n"
    "  -h  Help - prints this usage masseage.\n"
    "  -v  Verbose output.\n"
    "  -A  Sort output by area (default).\n"
    "  -D  Sort output by distance from boundary.\n"
    "  -G  Sort output by angle.\n"
    "  -H  Threshold high, use pixels at or above threshold (default).\n"
    "  -E  Threshold equal, use pixels at threshold.\n"
    "  -L  Threshold low, use pixels below threshold.\n"
    "  -R  Sort output by radial distance from centre.\n"
    "  -c  Centre (default is image centre).\n"
    "  -d  Debug image.\n"
    "  -n  Minimum area (default %g).\n"
    "  -t  Threshold value (default is to compute using Otsu's method).\n"
    "By default the input image object is read from the standard input and\n"
    "the radial distribution is written to the standard output.\n"
    "The image formats understood include wlz, jpg and tif.\n"
    "The output format is:\n"
    "  <angle> <dist from centre> <area> <x pos>,<y pos> <dist form boundary>\n"
    "Example:\n"
    "  %s -o out.txt -d debug.jpg in.tif\n"
    "The input image is read from in.tif, a debug image showing the\n"
    "segmented regions is written to debug.jpg and the radial distribution\n"
    "statistics are written to the file out.txt. With the output in\n"
    "out.txt, the following R code would plot the data as a set of circles\n"
    "with radius proportional to the square root of the component area:\n"
    "  data <- read.table(\"out.txt\")\n"
    "  attach(data)\n"
    "  symbols(x=data$V1, y=data$V2, circles=sqrt(data$V3))\n",
    argv[0],
    WlzVersion(),
    minArea,
    argv[0]);
  }
  return(!ok);
}
Esempio n. 9
0
/*!
* \return	Sobel filtered object.
* \ingroup	WlzValueFilters
* \brief	Applies a Sobel edge detection filter to the given
*               woolz object.
* \param	srcObj			Given source object.
* \param	hFlag			Apply horizontal edge kernel if
* 					non-zero.
* \param	vFlag			Apply vertical edge kernel if
* 					non-zero.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzObject	*WlzSobel(WlzObject *srcObj, int hFlag, int vFlag,
			  WlzErrorNum *dstErr)
{
  WlzObject	*dstObj = NULL,
		*tmpObj = NULL,
  		*objH = NULL,
		*objV = NULL;
  WlzGreyType	gType;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	sMaskHI[] =
  {
    -1, -2, -1,
     0,  0,  0,
     1,  2,  1
  },
  		sMaskVI[] =
  {
    -1,  0,  1,
    -2,  0,  2,
    -1,  0,  1
  };
  const double	sMaskHD[] =
  {
    -1.0, -2.0, -1.0,
     0.0,  0.0,  0.0,
     1.0,  2.0,  1.0
  },
  		sMaskVD[] =
  {
    -1.0,  0.0,  1.0,
    -2.0,  0.0,  2.0,
    -1.0,  0.0,  1.0
  };
  WlzConvolution sConv;

  WLZ_DBG((WLZ_DBG_LVL_1),
	  ("WlzSobel FE %p %d %d %p\n",
	   srcObj, hFlag, vFlag, dstErr));
  if(srcObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(srcObj->type != WLZ_2D_DOMAINOBJ)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if(srcObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(srcObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else
  {
    gType = WlzGreyTableTypeToGreyType(srcObj->values.core->type, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    sConv.linkcount = 0;
    sConv.xsize = 3;
    sConv.ysize = 3;
    sConv.cv = NULL;
    sConv.divscale = 1;
    sConv.offset = 0;
    sConv.modflag = 1;
    switch(gType)
    {
      case WLZ_GREY_INT:
      case WLZ_GREY_SHORT:
      case WLZ_GREY_UBYTE:
	tmpObj = srcObj;
        sConv.type = WLZ_CONVOLVE_INT;
        break;
      case WLZ_GREY_FLOAT:
      case WLZ_GREY_DOUBLE:
	tmpObj = srcObj;
        sConv.type = WLZ_CONVOLVE_FLOAT;
	break;
      case WLZ_GREY_RGBA:
        tmpObj = WlzAssignObject(
		 WlzConvertPix(srcObj, WLZ_GREY_SHORT, &errNum), NULL);
        sConv.type = WLZ_CONVOLVE_INT;
	break;
      default:
	errNum = WLZ_ERR_GREY_DATA;
        break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(hFlag)
    {
      sConv.cv = (sConv.type == WLZ_CONVOLVE_INT)?
      		 (int *)(&(sMaskHI[0])):
      		 (int *)(&(sMaskHD[0]));
      objH = WlzAssignObject(
             WlzConvolveObj(tmpObj, &sConv, 1, &errNum), NULL);
    }
    if((errNum == WLZ_ERR_NONE) && vFlag)
    {
      sConv.cv = (sConv.type == WLZ_CONVOLVE_INT)?
      		 (int *)(&(sMaskVI[0])):
      		 (int *)(&(sMaskVD[0]));
      objV = WlzAssignObject(
      	     WlzConvolveObj(tmpObj, &sConv, 1, &errNum), NULL);
    }
    if(errNum == WLZ_ERR_NONE)
    {
      if(objH && objV)
      {
	dstObj = WlzImageArithmetic(objV, objH, WLZ_BO_ADD, 1, &errNum);
	(void )WlzFreeObj(objV);
	objV = NULL;
	(void )WlzFreeObj(objH);
	objH = NULL;
      }
      else if(objH && (vFlag == 0))
      {
	dstObj = objH;
	objH = NULL;
      }
      else if(objV && (hFlag == 0))
      {
	dstObj = objV;
	objV = NULL;
      }
    }
  }
  if(tmpObj && (tmpObj != srcObj))
  {
    (void )WlzFreeObj(tmpObj);
  }
  (void )WlzFreeObj(objH);
  (void )WlzFreeObj(objV);
  if(dstErr)
  {
    *dstErr = errNum;
  }
  WLZ_DBG((WLZ_DBG_LVL_FN|WLZ_DBG_LVL_1),
	  ("WlzSobel FX %p\n",
	   dstObj));
  return(dstObj);
}