Example #1
0
/*!
* \return	New Woolz domain object with gradient grey values or
*		NULL on error.
* \ingroup      WlzValuesFilters
* \brief	Computes the gradient of the gray values in the
*               given Woolz 2D domain object.
* \param	dstGrdY			Destination pointer for the
*                                       gradient (partial derivative)
*                                       through lines, may be NULL.
* \param	dstGrdX			Destination pointer for the
*                                       gradient (partial derivative)
*                                       through columns, may be NULL.
* \param	srcObj			Given source object.
* \param	flt			Recursive filter to use.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
static WlzObject *WlzGreyGradient2D(WlzObject **dstGrdY, WlzObject **dstGrdX,
				    WlzObject *srcObj,
				    WlzRsvFilter *flt, WlzErrorNum *dstErr)
{
  WlzObject	*grdX = NULL,
  		*grdY = NULL,
		*dstObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(srcObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(srcObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(srcObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(WlzGreyTableIsTiled(srcObj->values.core->type))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    grdX = WlzRsvFilterObj(srcObj, flt, WLZ_RSVFILTER_ACTION_X, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    grdY = WlzRsvFilterObj(srcObj, flt, WLZ_RSVFILTER_ACTION_Y, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dstObj = WlzImageArithmetic(grdY, grdX, WLZ_BO_MAGNITUDE, 0, &errNum);
  }
  if(dstGrdX && (errNum == WLZ_ERR_NONE))
  {
    *dstGrdX = grdX;
  }
  else if(grdX)
  {
    WlzFreeObj(grdX);
  }
  if(dstGrdY && (errNum == WLZ_ERR_NONE))
  {
    *dstGrdY = grdY;
  }
  else if(grdY)
  {
    WlzFreeObj(grdY);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstObj);
}
Example #2
0
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Computes a metric which quantifies the extent to which
* 		the domain of one of the given objects is offset from 
* 		the domain of the second. This is a symetric metric, ie
* 		\f$OST(\Omega_0, \Omega_1) \equiv OST(\Omega_0, \Omega_1)\f$.
*		A domain is computed which is equidistant from the domains
*		of the two given objects, is within maxDist of each object's
*		domain and is within the convex hull of the union of the
*		domains of the two given objects. Within this domain the
*		1st, 2nd and 3rd quantiles of the distance
*		(\f$q_0\f$, \f$q_1\f$ and \f$q_2\f$) are found.
*		The object's domains are classified as offset if
*		\f[
		frac{q_1}{q_1 + (q_1  - q_0) + (q_2 - q_1)} \geq 0.5
		\f]
*		ie
*		\f[
		frac{q_1}{q_1 + q_2 - q_0} \geq 0.5
		\f]
*		Small equi-distant domains with a volume less than half
*		the maximum distance do not classify the relationship as
*		an overlap.
* \param	o			Array with the two given spatial
* 					domain objects, must not be NULL
* 					and nor must the objects.
* \param	t			Array of temporary objects as in
* 					WlzRCCTOIdx.
* \param	maxDist			Maximum distance for offset. This
* 					is used to compute a distance object,
* 					large distances will significantly
* 					increase the processing time.
* \param	dQ0			Destination pointer for 1st quantile
* 					offset distance, must not be NULL.
* \param	dQ1			Destination pointer for 2nd quantile
* 					(ie median) offset distance,
* 					must not be NULL.
* \param	dQ2			Destination pointer for 3rd quantile
* 					offset distance, must not be NULL.
*/
static WlzErrorNum		WlzRCCOffset(
				  WlzObject **o,
				  WlzObject **t,
				  int maxDist,
				  int *dQ0,
				  int *dQ1,
				  int *dQ2)
{
  int		empty = 0;
  int		q[3] = {0};
  int		*dHist = NULL;
  WlzObject	*eObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(((o[0]->type == WLZ_2D_DOMAINOBJ) &&
      (o[1]->type == WLZ_2D_DOMAINOBJ)) ||
     ((o[0]->type == WLZ_3D_DOMAINOBJ) &&
      (o[1]->type == WLZ_3D_DOMAINOBJ)))
  {
    if((o[0]->domain.core == NULL) || (o[1]->domain.core == NULL))
    {
      errNum = WLZ_ERR_DOMAIN_NULL;
    }
  }
  else
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  /* Compute distance transforms of the two given objects out to a given
   * maximum distance and then using these distances the equi-distant
   * domain between these two objects. The values of the eqi-distant object
   * are those of the distance between the objects.*/
  if(errNum == WLZ_ERR_NONE)
  {
    int		i;
    WlzObject	*sObj = NULL,
    		*cObj = NULL;
    WlzObject	*dObj[2];

    dObj[0] = dObj[1] = NULL;
    /* Create structuring element with which to dilate the given object
     * domains(by maxDist). */
    sObj = WlzAssignObject(
	   WlzMakeSphereObject(o[0]->type, maxDist, 0, 0, 0,
	                       &errNum), NULL);
    /* Create domain or convex hull of the union of the two given object
     * domains. */
    if(errNum == WLZ_ERR_NONE)
    {
      WlzObject	*uObj = NULL,
      		*xObj = NULL;

      errNum = WlzRCCMakeT(o, t, WLZ_RCCTOIDX_O0O1U);
      if(errNum == WLZ_ERR_NONE)
      {
	uObj = WlzAssignObject(t[WLZ_RCCTOIDX_O0O1U], NULL);
      }
      if(errNum == WLZ_ERR_NONE)
      {
        xObj = WlzAssignObject(
	       WlzObjToConvexHull(uObj, &errNum), NULL);
      }
      if(errNum == WLZ_ERR_NONE)
      {
        cObj = WlzAssignObject(
	       WlzConvexHullToObj(xObj, o[0]->type, &errNum), NULL);
      }
      (void )WlzFreeObj(xObj);
      (void )WlzFreeObj(uObj);
    }
    /* Dilate the two given objects and find the ntersection of the
     * dilated domains with each other and the convex hull computed
     * above. Within his domain compute the distances. */
    if(errNum == WLZ_ERR_NONE)
    {
      for(i = 0; i < 2; ++i)
      {
	WlzObject *tObj = NULL,
		  *rObj = NULL;

	tObj = WlzAssignObject(
	       WlzStructDilation(o[i], sObj, &errNum), NULL);
        if(errNum == WLZ_ERR_NONE)
	{
	  rObj = WlzAssignObject(
	         WlzIntersect2(tObj, cObj, &errNum), NULL);
	}
        (void )WlzFreeObj(tObj);
        if(errNum == WLZ_ERR_NONE)
	{
	  dObj[i] = WlzAssignObject(
		    WlzDistanceTransform(rObj, o[!i],
					 WLZ_OCTAGONAL_DISTANCE,
					 0.0, maxDist, &errNum), NULL);
	}
        (void )WlzFreeObj(rObj);
        if(errNum == WLZ_ERR_NONE)
	{
	  WlzPixelV bgdV;

	  bgdV.type = WLZ_GREY_INT;
	  bgdV.v.inv = maxDist;
	  errNum = WlzSetBackground(dObj[i], bgdV);
	}
        if(errNum != WLZ_ERR_NONE)
	{
	  break;
	}
      }
    }
    /* Find the domain which is equi-distant from the two given objects,
     * within the xDist range and within the convex hull of the union of
     * the two given object's domains. */
    (void )WlzFreeObj(sObj); sObj = NULL;
    if(errNum == WLZ_ERR_NONE)
    {
      WlzLong	vol = 0;
      WlzObject *qObj = NULL,
      		*tObj = NULL;

      qObj = WlzAssignObject(
             WlzImageArithmetic(dObj[0], dObj[1], WLZ_BO_EQ, 0, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
	WlzPixelV thrV;

	thrV.type = WLZ_GREY_INT;
	thrV.v.inv = 1;
        tObj = WlzAssignObject(
	       WlzThreshold(qObj, thrV, WLZ_THRESH_HIGH, &errNum), NULL);
      }
      /* Check that the eqi-distant domain is of a reasonable size ie has
       * a area or volume greater than half the maximum distance. */
      if(errNum == WLZ_ERR_NONE)
      {
        vol = WlzVolume(tObj, &errNum);
	if((maxDist / 2) >= vol)
	{
	  empty = 1;
	}
      }
      if((errNum == WLZ_ERR_NONE) && !empty)
      {
	WlzObject *mObj;
	WlzPixelV tmpV;

	tmpV.type = WLZ_GREY_INT;
	tmpV.v.inv = 0;
        mObj = WlzAssignObject(
	       WlzGreyTemplate(dObj[0], tObj, tmpV, &errNum), NULL);
        if(errNum == WLZ_ERR_NONE)
	{
	  tmpV.v.inv = 1;
	  eObj = WlzAssignObject(
	  	WlzThreshold(mObj, tmpV, WLZ_THRESH_HIGH, &errNum), NULL);
	}
	(void )WlzFreeObj(mObj);
      }
      (void )WlzFreeObj(tObj);
      (void )WlzFreeObj(qObj);
      if((errNum == WLZ_ERR_NONE) && !empty)
      {
	WlzLong vol;

	vol = WlzVolume(eObj, &errNum);
	if((maxDist / 2) >= vol)
	{
	  empty = 1;
	}
      }
    }
    (void )WlzFreeObj(cObj);
    (void )WlzFreeObj(sObj);
    (void )WlzFreeObj(dObj[0]);
    (void )WlzFreeObj(dObj[1]);
  }
  /* Compute a quantised distance histogram in which equi-distant distances
   * are quantized to integer values. */
  if((errNum == WLZ_ERR_NONE) && !empty)
  {
    if((dHist = (int *)AlcCalloc(maxDist + 1, sizeof(int))) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if((errNum == WLZ_ERR_NONE) && !empty)
  {
    if(eObj->type == WLZ_2D_DOMAINOBJ)
    {
      errNum = WlzRCCCompDistHist2D(maxDist, dHist, eObj);
    }
    else
    {
      errNum = WlzRCCCompDistHist3D(maxDist, dHist, eObj);
    }
#ifdef WLZ_RCC_DEBUG_OST
    {
      FILE *fP;

      fP = fopen("WLZ_RCC_DEBUG_OST.wlz", "w");
      (void )WlzWriteObj(fP, eObj);
      (void )fclose(fP);
    }
#endif
  }
  WlzFreeObj(eObj);
  if((errNum == WLZ_ERR_NONE) && !empty)
  {
    int		i,
    		n,
		s,
		nq;
    /* Compute the median, first and third quantile offset distances,
     * the ratio of median to the median plus inner inter-quantile range. */
    n = 0;
    for(i = 0; i < maxDist; ++i)
    {
      n += dHist[i];
    }
    i = 0;
    s = 0;
    nq = n / 4;
    while(s < nq)
    {
      s += dHist[i++];
    }
    q[0] = i;
    nq = n / 2;
    while(s < nq)
    {
      s += dHist[i++];
    }
    q[1] = i;
    nq = (3 * n) / 4;
    while(s < nq)
    {
      s += dHist[i++];
    }
    q[2] = i;
  }
  AlcFree(dHist);
  *dQ0 = q[0];
  *dQ1 = q[1];
  *dQ2 = q[2];
  return(errNum);
}
int main(int	argc,
	 char	**argv)
{
  char 		optList[] = "hv";
  int		option;
  /* int		verboseFlg=0; */
  WlzErrorNum	errNum=WLZ_ERR_NONE;
  char		*tiffFile=NULL;
  WlzObject	*inObj, *outObj, *obj, **objVec;
  int		i, objVecCount;
  WlzGreyType	gType;

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

    case 'v':
      /* verboseFlg = 1; */
      break;

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

  if( optind < argc ){
    tiffFile = *(argv+optind);
  }
  else {
    usage(argv[0]);
    return WLZ_ERR_UNSPECIFIED;
  }

  /* read the TIFF file */
  if( (inObj = WlzAssignObject(WlzEffReadObj(NULL, tiffFile,
  			                     WLZEFF_FORMAT_TIFF, 0, 0, 0,
					     &errNum), NULL)) == NULL ){
    usage(argv[0]);
    return errNum;
  }

  /* if 2D then that is the shade file, else take max of 3D stack */
  switch( inObj->type ){
  case WLZ_2D_DOMAINOBJ:
    outObj = inObj;
    break;

  case WLZ_3D_DOMAINOBJ:
    if( (errNum = WlzExplode3D(&objVecCount, &objVec, inObj)) != WLZ_ERR_NONE ){
      usage(argv[0]);
      return errNum;
    }
    gType = WlzGreyTypeFromObj(objVec[0], &errNum);
    outObj = WlzAssignObject(objVec[0], NULL);
    for(i=1; i < objVecCount; i++){
      if( gType == WLZ_GREY_RGBA ){
	obj = WlzRGBAImageArithmetic(outObj, objVec[i], WLZ_BO_MAX, 0, &errNum);
      }
      else {
	obj = WlzImageArithmetic(outObj, objVec[i], WLZ_BO_MAX, 0, &errNum);
      }
      if( obj ){
	WlzFreeObj(outObj);
	outObj = WlzAssignObject(obj, &errNum);
      }
      else {
	break;
      }
    }
    
    WlzFreeObj(inObj);
    break;

  default:
    WlzFreeObj(inObj);
    errNum = WLZ_ERR_OBJECT_TYPE;
  }

  /* write shade object */
  if( errNum == WLZ_ERR_NONE ){
    WlzWriteObj(stdout, outObj);
    WlzFreeObj(outObj);
  }
  else {
    usage(argv[0]);
  }
  return errNum;
}
Example #4
0
int             main(int argc, char **argv)
{
  int		idx,
		option,
		dither = 0,
		overwrite = 1,
		ok = 1,
		usage = 0;
  WlzImArNorm	norm = WLZ_IMARNORM_NONE;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  FILE		*fP = NULL;
  WlzObject	*outObj = NULL;
  WlzObject	*inObj[2];
  WlzBinaryOperatorType operator = WLZ_BO_ADD;
  char 		*outObjFileStr;
  char  	*inObjFileStr[2];
  WlzPixelV	gMin[3],
  		gMax[3];
  const char	*errMsg;
  static char	optList[] = "O:o:ab:dgilmsnNh",
		outObjFileStrDef[] = "-",
  		inObjFileStrDef[] = "-";

  opterr = 0;
  inObj[0] = NULL;
  inObj[1] = NULL;
  outObjFileStr = outObjFileStrDef;
  inObjFileStr[0] = inObjFileStrDef;
  inObjFileStr[1] = inObjFileStrDef;
  while(ok && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case 'O':
	if((sscanf(optarg, "%d", &overwrite) != 1) ||
	   (overwrite < 0) || (overwrite > 2))
	{
	  usage = 1;
	  ok = 0;
	}
	break;
      case 'o':
	outObjFileStr = optarg;
	break;
      case 'a':
	operator = WLZ_BO_ADD;
	break;
      case 'b':
	operator = atoi(optarg);
	switch( operator ){
	  case WLZ_BO_ADD:
	  case WLZ_BO_SUBTRACT:
	  case WLZ_BO_MULTIPLY:
	  case WLZ_BO_DIVIDE:
	  case WLZ_BO_MODULUS:
	  case WLZ_BO_EQ:
	  case WLZ_BO_NE:
	  case WLZ_BO_GT:
	  case WLZ_BO_GE:
	  case WLZ_BO_LT:
	  case WLZ_BO_LE:
	  case WLZ_BO_AND:
	  case WLZ_BO_OR:
	  case WLZ_BO_XOR:
	  case WLZ_BO_MAX:
	  case WLZ_BO_MIN:
	  case WLZ_BO_MAGNITUDE:
	    break;
	  default:
	    usage = 1;
	    ok = 0;
	    break;
	}
	break;
      case 'd':
	operator = WLZ_BO_DIVIDE;
	break;
      case 'g':
	operator = WLZ_BO_MAGNITUDE;
	break;
      case 'l':
	operator = WLZ_BO_MODULUS;
	break;
      case 'm':
	operator = WLZ_BO_MULTIPLY;
	break;
      case 's':
	operator = WLZ_BO_SUBTRACT;
	break;
      case 'n':
	norm = WLZ_IMARNORM_INPUT;
	break;
      case 'N':
	norm = WLZ_IMARNORM_256;
	break;
      case 'i':
	dither = 1;
	break;
      case 'h':
      default:
	usage = 1;
	ok = 0;
	break;
    }
  }
  if((inObjFileStr[0] == NULL) || (*inObjFileStr[0] == '\0') ||
     (inObjFileStr[1] == NULL) || (*inObjFileStr[1] == '\0') ||
     (outObjFileStr == NULL) || (*outObjFileStr == '\0'))
  {
    ok = 0;
    usage = 1;
  }
  if(ok && (optind < argc))
  {
    idx = 0;
    while((idx < 2) && (optind < argc))
    {
      inObjFileStr[idx] = *(argv + optind);
      ++optind;
      ++idx;
    }
  }
  if(ok && (optind != argc))
  {
    usage = 1;
    ok = 0;
  }
  if(ok)
  {
    idx = 0;
    while((errNum == WLZ_ERR_NONE) && (idx < 2))
    {
      errNum = WLZ_ERR_READ_EOF;
      if((inObjFileStr[idx] == NULL) ||
	  (*inObjFileStr[idx] == '\0') ||
	  ((fP = (strcmp(inObjFileStr[idx], "-")?
		  fopen(inObjFileStr[idx], "r"): stdin)) == NULL) ||
	  ((inObj[idx]= WlzAssignObject(WlzReadObj(fP,
	  					   &errNum), NULL)) == NULL))
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to read object %d from file %s (%s)\n",
		       *argv, idx, inObjFileStr[idx], errMsg);
      }
      if(fP && strcmp(inObjFileStr[idx], "-"))
      {
	fclose(fP);
      }
      ++idx;
    }
  }
  if(ok)
  {
    idx = 0;
    while((errNum == WLZ_ERR_NONE) && (idx < 2))
    {
      if((inObj[idx]->type != WLZ_2D_DOMAINOBJ) &&
         (inObj[idx]->type != WLZ_3D_DOMAINOBJ))
      {
        ok = 0;
	(void )fprintf(stderr, "%s: input object %d is not a domain object\n",
		       *argv, idx);
      }
      ++idx;
    }
  }
  if(ok && (norm == WLZ_IMARNORM_INPUT))
  {
    if(((errNum = WlzGreyRange(inObj[0], gMin, gMax)) != WLZ_ERR_NONE) ||
       ((errNum = WlzGreyRange(inObj[1], gMin + 1, gMax + 1)) != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
		     "%s: failed to find input objects grey range (%s)\n",
		     *argv, errMsg);
    }
  }
  if(ok)
  {
    if( WlzGreyTypeFromObj(inObj[0], &errNum) == WLZ_GREY_RGBA ){
      if((outObj = WlzRGBAImageArithmetic(inObj[0], inObj[1], operator, 1,
				      &errNum)) == NULL)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to compute new object (%s).\n",
		       *argv, errMsg);
      }
    }
    else if((outObj = WlzImageArithmetic(inObj[0], inObj[1], operator, 0,
				    &errNum)) == NULL)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
      		     "%s: failed to compute new object (%s).\n",
		     *argv, errMsg);
    }
  }
  if(ok &&
     (norm != WLZ_IMARNORM_NONE) &&
     (WlzGreyTypeFromObj(inObj[0], &errNum) != WLZ_GREY_RGBA) )
  {
    if((errNum = WlzGreyRange(outObj, gMin+ 2, gMax + 2)) != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
      		     "%s: failed to find output object's grey range (%s)\n",
		     *argv, errMsg);
    }
    if(ok)
    {
      if(norm == WLZ_IMARNORM_256)
      {
        gMin[0].type = WLZ_GREY_UBYTE;
	gMin[0].v.ubv = 0;
        gMax[0].type = WLZ_GREY_UBYTE;
	gMax[0].v.ubv = 255;
	(void )WlzValueConvertPixel(gMin, gMin[0], gMin[2].type);
	(void )WlzValueConvertPixel(gMax, gMax[0], gMax[2].type);
      }
      else
      {
	(void )WlzValueConvertPixel(gMin, gMin[0], gMin[2].type);
	(void )WlzValueConvertPixel(gMax, gMax[0], gMax[2].type);
	(void )WlzValueConvertPixel(gMin + 1, gMin[1], gMin[2].type);
	(void )WlzValueConvertPixel(gMax + 1, gMax[1], gMax[2].type);
	switch(gMin[2].type)
	{
	  case WLZ_GREY_INT:
	    if(gMin[1].v.inv < gMin[0].v.inv)
	    {
	      gMin[0].v.inv = gMin[1].v.inv;
	    }
	    if(gMax[1].v.inv > gMax[0].v.inv)
	    {
	      gMax[0].v.inv = gMax[1].v.inv;
	    }
	    break;
	  case WLZ_GREY_SHORT:
	    if(gMin[1].v.shv < gMin[0].v.shv)
	    {
	      gMin[0].v.shv = gMin[1].v.shv;
	    }
	    if(gMax[1].v.shv > gMax[0].v.shv)
	    {
	      gMax[0].v.shv = gMax[1].v.shv;
	    }
	    break;
	  case WLZ_GREY_UBYTE:
	    if(gMin[1].v.ubv < gMin[0].v.ubv)
	    {
	      gMin[0].v.ubv = gMin[1].v.ubv;
	    }
	    if(gMax[1].v.ubv > gMax[0].v.ubv)
	    {
	      gMax[0].v.ubv = gMax[1].v.ubv;
	    }
	    break;
	  case WLZ_GREY_FLOAT:
	    if(gMin[1].v.flv < gMin[0].v.flv)
	    {
	      gMin[0].v.flv = gMin[1].v.flv;
	    }
	    if(gMax[1].v.flv > gMax[0].v.flv)
	    {
	      gMax[0].v.flv = gMax[1].v.flv;
	    }
	    break;
	  case WLZ_GREY_DOUBLE:
	    if(gMin[1].v.dbv < gMin[0].v.dbv)
	    {
	      gMin[0].v.dbv = gMin[1].v.dbv;
	    }
	    if(gMax[1].v.dbv > gMax[0].v.dbv)
	    {
	      gMax[0].v.dbv = gMax[1].v.dbv;
	    }
	    break;
	  default:
	    errNum = WLZ_ERR_GREY_TYPE;
	    break;
	}
      }
    }
    if((errNum = WlzGreySetRange(outObj, gMin[2], gMax[2],
    				 gMin[0], gMax[0], dither)) != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
		     "%s: failed to set output object's grey range (%s)\n",
		     *argv, errMsg);
    }
  }
  if(ok)
  {
    errNum = WLZ_ERR_WRITE_EOF;
    if(((fP = (strcmp(outObjFileStr, "-")?  fopen(outObjFileStr, "w"):
	      				    stdout)) == NULL) ||
       ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
		     "%s: failed to write output object (%s).\n",
		     *argv, errMsg);
    }
    if(fP && strcmp(outObjFileStr, "-"))
    {
      fclose(fP);
    }
  }
  WlzFreeObj(inObj[0]);
  WlzFreeObj(inObj[1]);
  WlzFreeObj(outObj);
  if(usage)
  {

    fprintf(stderr,
	    "Usage: %s"
	    " [-O#] [-o<out file>] [-a] [-b <op>] [-d] [-g] [-i] [-l] [-m] [-s] [-h] "
	    "[<in object 0>] [<in object 1>]\n"
	    "Options:\n"
	    "  -O        Overwrite option (only useful for debugging)\n"
	    "  -o        Output file name.\n"
	    "  -a        Add the object's grey values.\n"
	    "  -b <op>   Apply binary operation to the grey-values.\n"
	    "            op =  %d - Add\n"   
	    "               =  %d - SUBTRACT\n"
	    "               =  %d - MULTIPLY\n"
	    "               =  %d - DIVIDE\n"
	    "               =  %d - MODULUS\n"
	    "               =  %d - EQ\n"
	    "               =  %d - NE\n"
	    "               =  %d - GT\n"
	    "               =  %d - GE\n"
	    "               =  %d - LT\n"
	    "               =  %d - LE\n"
	    "               =  %d - AND\n"
	    "               =  %d - OR\n"
	    "               =  %d - XOR\n"
	    "               =  %d - MAX\n"
	    "               =  %d - MIN\n"
	    "               =  %d - MAGNITUDE\n"
	    "  -d        Divide the grey values of the 1st object by those of the 2nd.\n"
	    "  -g        Vector magnitude of horizontal and vertical component objects\n"
	    "  -i        Dither values if setting range\n"
	    "  -l        Compute the modulus of the grey values of the 1st object wrt\n"
	    "            those of the 2nd.\n"
	    "  -m        Multiply the object's grey values.\n"
	    "  -s        Subtract the grey values of the 2nd object from those of the 1st.\n"
	    "  -n        Normalises the output object to the range of the input objects.\n"
	    "  -N        Normalises the output objects to the range [0-255].\n"
	    "  -h        Help, prints this usage message.\n"
	    "Computes an arithmetic binary (two objects) operation on two domain\n"
	    "objects. The default operator is add.\n"
	    "The input objects are read from stdin and values are written to stdout\n"
	    "unless the filenames are given.\n"
	    "Example:\n%s%s%s",
	    *argv,
	    WLZ_BO_ADD,
	    WLZ_BO_SUBTRACT,
	    WLZ_BO_MULTIPLY,
	    WLZ_BO_DIVIDE,
	    WLZ_BO_MODULUS,
	    WLZ_BO_EQ,
	    WLZ_BO_NE,
	    WLZ_BO_GT,
	    WLZ_BO_GE,
	    WLZ_BO_LT,
	    WLZ_BO_LE,
	    WLZ_BO_AND,
	    WLZ_BO_OR,
	    WLZ_BO_XOR,
	    WLZ_BO_MAX,
	    WLZ_BO_MIN,
	    WLZ_BO_MAGNITUDE,
	    "cat obj1.wlz | ",
	    *argv,
	    " -o obj3.wlz -a obj2.wlz\n"
	    "A new object 'obj3.wlz is formed by adding the grey values of obj1 and\n"
	    "obj2.wlz.\n");
  }
  return(!ok);
}
Example #5
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,
  		*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:
        sConv.type = WLZ_CONVOLVE_INT;
        break;
      case WLZ_GREY_FLOAT:
      case WLZ_GREY_DOUBLE:
        sConv.type = WLZ_CONVOLVE_FLOAT;
	break;
      case WLZ_GREY_RGBA: /* RGBA to be done RAB */
      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 = WlzConvolveObj(srcObj, &sConv, 1, &errNum);
    }
    if((errNum == WLZ_ERR_NONE) && vFlag)
    {
      sConv.cv = (sConv.type == WLZ_CONVOLVE_INT)?
      		 (int *)(&(sMaskVI[0])):
      		 (int *)(&(sMaskVD[0]));
      objV = WlzConvolveObj(srcObj, &sConv, 1, &errNum);
    }
    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;
      }
    }
    else
    {
      (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);
}
Example #6
0
/*!
* \return	Shade corrected object or NULL on error.
* \ingroup	WlzValueFilters
* \brief	Shade corrects the given domain object with grey
*               values.
*		\f[
		  p_i = n \frac{(o_i - d_i)}{(s_i - d_i}
		\f]
*               The shade corrected image P with values \f$p_i\f$ is
*		created by applying a correction factor to each image
*		value of the given image O with values \f$o_i\f$.
*		\f$s_i\f$ and \f$d_i\f$ are the bright and dark-field
*		shade image values respectively.
* \param	srcObj			Given object to be shade corrected.
* \param	shdObj			Given bright field object.
* \param	shdDFObj		Given dark field object (may be NULL).
* \param	nrmVal			Normalization value.
* \param	inPlace			Modify the grey values of the given
*					object in place if non-zero.
* \param	dstErr			Destination error pointer, may
*                                       be null.
*/
WlzObject	*WlzShadeCorrectBFDF(
  WlzObject 	*srcObj,
  WlzObject 	*shdObj,
  WlzObject 	*shdDFObj,
  double 	nrmVal,
  int 		inPlace,
  WlzErrorNum 	*dstErr)
{
  WlzObject	*rtnObj = NULL;
  WlzObject	*obj1, *obj2;
  WlzCompoundArray	*inCobj, *outCobj;
  WlzObject	**outArray;
  WlzValues	values;
  int		i;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if((srcObj == NULL) || (shdObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((srcObj->domain.core == NULL) || (shdObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((srcObj->values.core == NULL) || (shdObj->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(WlzGreyTableIsTiled(srcObj->values.core->type) ||
          WlzGreyTableIsTiled(shdObj->values.core->type))
  {
    errNum = WLZ_ERR_VALUES_TYPE;
  }
  else
  {
    switch(srcObj->type)
    {
    case WLZ_2D_DOMAINOBJ:
      if(shdObj->type != srcObj->type)
      {
	errNum = WLZ_ERR_OBJECT_TYPE;
      }
      else if( shdDFObj ){
	if( WlzGreyTypeFromObj(srcObj, &errNum) == WLZ_GREY_RGBA ){
	  obj1 = WlzRGBAImageArithmetic(srcObj, shdDFObj, WLZ_BO_SUBTRACT,
					0, &errNum);
	  obj2 = WlzRGBAImageArithmetic(shdObj, shdDFObj, WLZ_BO_SUBTRACT,
					0, &errNum);
	}
	else {
	  obj1 = WlzImageArithmetic(srcObj, shdDFObj, WLZ_BO_SUBTRACT,
				    0, &errNum);
	  obj2 = WlzImageArithmetic(shdObj, shdDFObj, WLZ_BO_SUBTRACT,
				    0, &errNum);
	}
	rtnObj = WlzShadeCorrect2D(obj1, obj2, nrmVal, inPlace, &errNum);
	WlzFreeObj(obj1);
	WlzFreeObj(obj2);;
      }
      else {
	rtnObj = WlzShadeCorrect2D(srcObj, shdObj, nrmVal, inPlace, &errNum);
      }
      break;

    case WLZ_COMPOUND_ARR_1:
    case WLZ_COMPOUND_ARR_2:
      inCobj = (WlzCompoundArray *) srcObj;
      if( inCobj->n > 0 ){
	if( (outArray = (WlzObject **)
	     AlcCalloc(inCobj->n, sizeof(WlzObject *))) == NULL){
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else {
	  for(i=0; (i < inCobj->n) && (errNum == WLZ_ERR_NONE); i++){
	    /* allow special behaviour of a non-compound shade image
	       to be used for each object in a compound but must align */
	    switch( shdObj->type ){
	    case WLZ_2D_DOMAINOBJ:
	    case WLZ_3D_DOMAINOBJ:
	      outArray[i] = WlzShadeCorrectBFDF(inCobj->o[i],
						shdObj, shdDFObj,
						nrmVal, inPlace, &errNum);
	      break;

	    case WLZ_COMPOUND_ARR_1:
	    case WLZ_COMPOUND_ARR_2:
	      outArray[i] =
		WlzShadeCorrectBFDF(inCobj->o[i],
				    ((WlzCompoundArray *) shdObj)->o[i],
				    shdDFObj?
				    ((WlzCompoundArray *) shdDFObj)->o[i]:NULL,
				    nrmVal, inPlace, &errNum);
	      break;
	    default:
	      errNum = WLZ_ERR_OBJECT_TYPE;
	      break;
	    }
	      
	  }
	  if( errNum == WLZ_ERR_NONE ){
	    outCobj = WlzMakeCompoundArray(srcObj->type, 3, inCobj->n,
					   outArray, outArray[0]->type,
					   &errNum);
	    rtnObj = (WlzObject *) outCobj;
	  }
	  else {
	    while( i >= 0 ){
	      WlzFreeObj(outArray[i--]);
	    }
	  }
	  AlcFree(outArray);
	}
      }
      else {
	errNum = WLZ_ERR_OBJECT_DATA;
      }
      break;

    case WLZ_3D_DOMAINOBJ:
      errNum = WLZ_ERR_UNIMPLEMENTED;
      break;

    case WLZ_TRANS_OBJ:
      if((rtnObj = WlzShadeCorrectBFDF(srcObj->values.obj,
                                       shdObj, shdDFObj, nrmVal,
				       inPlace, &errNum)) != NULL){
	values.obj = rtnObj;
	return WlzMakeMain(WLZ_TRANS_OBJ, srcObj->domain, values,
			   NULL, NULL, dstErr);
      }
      break;

    case WLZ_EMPTY_OBJ:
      return WlzMakeEmpty(dstErr);

    default:
      errNum = WLZ_ERR_OBJECT_TYPE;
      break;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rtnObj);
}