/*!
* - Function:   WlzEffWriteMeshTransform3DWithoutDisplacementVTK
* - Returns:    none 
* - Purpose:    output the orginal mesh.	
* - Parameters:	
*     -# *fp:               pointer pointing to a specific file.
*     -#  wmt3D:            mesh transform.
* - Author:       J. Rao, R. Baldock and B. Hill
*/
static void  OutPutSectionsForTest(
                  WlzObject   *WObjS, 
		  WlzObject   *WObj2D, 
		  /* FILE        *outFile;  */
		  char        *outFileStr, 
		  int          iloop,
		  WlzErrorNum *errNum){

  WlzGreyValueWSpace *gVWSp;
  WlzErrorNum       wErrN = WLZ_ERR_NONE;

  WlzGMModel         *gM;
  WlzGMShell         *cS, *fS;
  WlzGMLoopT         *cLT, *fLT;
  WlzGMEdgeT         *cET, *fET;
  WlzDVertex2        *v1,  *v2;
  WlzIBox2            bBoxT;
  WlzObject          *tObj;
  int ix, jy, kt, intensity;

 if( ( (WObjS->type) != WLZ_CONTOUR ) )
  {
      	wErrN = WLZ_ERR_DOMAIN_TYPE;
  }


  if( ( WObj2D->type != WLZ_2D_DOMAINOBJ )  )
  {
      	wErrN = WLZ_ERR_DOMAIN_TYPE;
  }

  if(  ( WObj2D->domain.core == NULL ) )
  {
	wErrN = WLZ_ERR_DOMAIN_NULL;
  }
  
  if(wErrN == WLZ_ERR_NONE)
  {
       /* copy it */
       tObj = WlzCopyObject(WObj2D, &wErrN);
       if( wErrN  != WLZ_ERR_NONE)
       {
          printf("Something wrong with when copy obj ");
          exit(1);
       }
   

       /* get the bounding box */
       bBoxT = WlzBoundingBox2I(tObj, &wErrN); 
       if( wErrN  != WLZ_ERR_NONE)
       {
          printf("Something wrong with getting bounding box of obj ");
          exit(1);
       }
       
       /* revise the grey value of it */   
       gVWSp        = WlzGreyValueMakeWSp(tObj, &wErrN);
       if( wErrN  != WLZ_ERR_NONE)
       {
          printf("Something wrong with when make warped obj Wsp");
          exit(1);
       }
       
       for(ix = bBoxT.xMin; ix <bBoxT.xMax; ix++)
       {
          kt = 0;
          for(jy= bBoxT.yMin; jy< bBoxT.yMax; jy++)
          {
	      /*  GetGreyValue(gVWSp, 0, jy, ix, &intensity, &errNum); */
	      intensity = 255;
	      FillGreyValue(gVWSp, 0, jy, ix, intensity, &wErrN);
	      
          } 
       }

   }

  /*  visualize the data: */
  if( wErrN == WLZ_ERR_NONE)
  {
    iloop = 1;

    kt = 0;
  
    gM = WObjS->domain.ctr->model;
    /* For each shell of the model. */
    cS = fS = (WlzGMShell *) gM->child;
    do
    {
       printf("Shell  %d   Shell index %d\n", kt, cS->idx);
      /* For each loop topology element of the model. */
       cLT = fLT = (WlzGMLoopT *) cS->child;
       kt++;
       do
       {
           printf("Loop index %d\n", cLT->idx);
           /* For each edge topology element of the model. */
	   cET = fET = cLT->edgeT;
	   do
	   {
              if(cET == cET->edge->edgeT) /* Print edge end points */
	      {
	         v1 = (WlzDVertex2 *) cET->vertexT->diskT->vertex->geo.vg2D;
	         v2 = (WlzDVertex2 *) cET->opp->vertexT->diskT->vertex->geo.vg2D;
		 /*
		 printf("%lg    %lg\n",cET->vertexT->diskT->vertex->geo.vg2D->vtx.vtX, \
		                       cET->vertexT->diskT->vertex->geo.vg2D->vtx.vtY );
		 printf("%lg    %lg\n",cET->opp->vertexT->diskT->vertex->geo.vg2D->vtx.vtX, \
		                       cET->opp->vertexT->diskT->vertex->geo.vg2D->vtx.vtY );
				       */
		/* if(kt%3 == iloop) */
		{
		 ix = (int) cET->vertexT->diskT->vertex->geo.vg2D->vtx.vtX;
		 jy = (int) cET->vertexT->diskT->vertex->geo.vg2D->vtx.vtY;
		 printf("idx %d ix  %d  iy  %d\n", cET->vertexT->diskT->vertex->idx, ix, jy);
	 	 intensity = kt * 40;
	         FillGreyValue(gVWSp, 0, jy, ix, intensity, &wErrN);
		 ix = (int) cET->opp->vertexT->diskT->vertex->geo.vg2D->vtx.vtX;
		 jy = (int) cET->opp->vertexT->diskT->vertex->geo.vg2D->vtx.vtY;
                 printf("idx %d ix  %d  iy  %d\n", cET->opp->vertexT->diskT->vertex->idx, ix, jy);
                 FillGreyValue(gVWSp, 0, jy, ix, intensity, &wErrN);
		} 
              }
	      cET = cET->next;
	   } while (cET != fET);
           cLT = cLT->next;


       } while(cLT != fLT);
       cS = cS->next;
   }  while(cS != fS );
  }

 
    if((outFile = fopen(outFileStr, "w")) == NULL )
    {
      printf("cannot open the output woolz file.\n");
      exit(1);
    }

    if( ( wErrN = WlzWriteObj(outFile, tObj) ) != WLZ_ERR_NONE )
    {
       printf("output Woolz Object Error.\n");
       fclose(outFile); 
       exit(1);
    }
    
    fclose(outFile); 
    outFile = NULL;

    WlzGreyValueFreeWSp(gVWSp);


}
Example #2
0
/*!
* \return	Affine transform which brings the two objects into register.
* \ingroup	WlzRegistration
* \brief	Registers the two given 2D domain objects using a
*               frequency domain cross correlation.  An affine transform
*               is computed, which when applied to the source object
*               takes it into register with the target object.
*               A resolution pyramid is built from the given objects
*               and used to register the objects, progressing from
*               a low resolution towards the full resolution objects.
* \param	tObj			The target object. Must have
*                                       been assigned.
* \param	sObj			The source object to be
*                                       registered with target object.
* \param	initTr			Initial affine transform
*                                       to be applied to the source
*                                       object prior to registration.
*                                       Only translations in x and y
*                                       and rotation about the z axis
*                                       are used. May be NULL which is
*                                       equivalent to an identity transform.
* \param	trType			Required transform type.
* \param	maxTran			Maximum translation.
* \param	maxRot			Maximum rotation.
* \param	maxItr			Maximum number of iterations,
*                                       if \f$leq\f$ 0 then infinite iterations
*                                       are allowed.
* \param	winFn			Window function.
* \param	noise			Use Gaussian noise if non-zero.
* \param	dstConv			Destination ptr for the
*                                       convergence flag (non zero
*                                       on convergence), may be NULL.
* \param	dstCCor			Destination ptr for the cross
*                                       correlation value, may be NULL.
* \param	dstErr			Destination error pointer,
*                                       may be NULL.
*/
static WlzAffineTransform *WlzRegCCorObjs2D(WlzObject *tObj, WlzObject *sObj,
					    WlzAffineTransform *initTr,
					    WlzTransformType trType,
					    WlzDVertex2 maxTran, double maxRot,
					    int maxItr,
					    WlzWindowFnType winFn, int noise,
					    int *dstConv, double *dstCCor,
					    WlzErrorNum *dstErr)
{
  int		tI1,
		samIdx,
  		nSam,
		conv;
  double	cCor,
  		rot0,
		rot1,
		sMaxRot;
  WlzPixelV	gV[4];
  WlzIVertex2	tIV0,
  		tIV1;
  WlzIVertex3	samFacV;
  WlzDVertex2	tran0,
  		tran1,
		sMaxTran;
  WlzIBox2	sBox,
  		tBox;
  int		*samFac = NULL;
  WlzObject	**sTObj = NULL,
  		**sSObj = NULL;
  WlzAffineTransform *samRegTr0 = NULL,
  		*samRegTr1 = NULL,
		*regTr = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzAffineTransformPrim trPrim;
  WlzPixelV	zeroBgd;
  const int	samFacStep = 4,
  		maxSam = 16,
  		minSamSz = 100;

  zeroBgd.type = WLZ_GREY_INT;
  zeroBgd.v.inv = 0;
  gV[0].type = gV[1].type = gV[2].type = gV[3].type = WLZ_GREY_DOUBLE;
  /* Compute the number of x4 subsampling operations to use. */
  sBox = WlzBoundingBox2I(sObj, &errNum);
  if(errNum == WLZ_ERR_NONE)
  {
    tBox = WlzBoundingBox2I(tObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    tIV0.vtX = sBox.xMax - sBox.xMin + 1;
    tIV0.vtY = sBox.yMax - sBox.yMin + 1;
    tIV1.vtX = tBox.xMax - tBox.xMin + 1;
    tIV1.vtY = tBox.yMax - tBox.yMin + 1;
    tIV0.vtX = WLZ_MIN(tIV0.vtX, tIV1.vtX);
    tIV0.vtY = WLZ_MIN(tIV0.vtY, tIV1.vtY);
    nSam = 1;
    tI1 = WLZ_MIN(tIV0.vtX, tIV0.vtY);
    while((nSam < maxSam) && (tI1 > minSamSz))
    {
      ++nSam;
      tI1 /= samFacStep;
    }
  }
  /* Allocate space for subsampled objects. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(((samFac = (int *)AlcMalloc(nSam * sizeof(int))) == NULL) ||
       ((sTObj = (WlzObject **)AlcCalloc(nSam,
    				         sizeof(WlzObject *))) == NULL) ||
       ((sSObj = (WlzObject **)AlcCalloc(nSam,
       					 sizeof(WlzObject *))) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute subsampled objects and make sure the background value is zero. */
  if(errNum == WLZ_ERR_NONE)
  {
    samIdx = 0;
    *samFac = 1;
    samFacV.vtX = samFacV.vtY = samFacStep;
    *(sTObj + 0) = WlzAssignObject(tObj, NULL);
    *(sSObj + 0) = WlzAssignObject(sObj, NULL);
    while((errNum == WLZ_ERR_NONE) && (++samIdx < nSam))
    {
      *(samFac + samIdx) = *(samFac + samIdx - 1) * samFacStep;
      *(sTObj + samIdx) = WlzAssignObject(
      			  WlzSampleObj(*(sTObj + samIdx - 1), samFacV,
      				       WLZ_SAMPLEFN_GAUSS, &errNum), NULL);
      if(errNum == WLZ_ERR_NONE)
      {
	(void )WlzSetBackground(*(sTObj + samIdx), zeroBgd);
        *(sSObj + samIdx) = WlzAssignObject(
			    WlzSampleObj(*(sSObj + samIdx - 1), samFacV,
			       	         WLZ_SAMPLEFN_GAUSS, &errNum), NULL);
      }
      if(errNum == WLZ_ERR_NONE)
      {
        (void )WlzSetBackground(*(sSObj + samIdx), zeroBgd);
      }
    }
  }
  /* Register the subsampled objects starting with the lowest resolution
   * (highest subsampling) and progressing to the unsampled objects. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(initTr == NULL)
    {
      rot0 = 0.0;
      tran0.vtX = 0.0;
      tran0.vtY = 0.0;
    }
    else
    {
      errNum = WlzAffineTransformPrimGet(initTr, &trPrim);
      rot0 = trPrim.theta;
      tran0.vtX = trPrim.tx;
      tran0.vtY = trPrim.ty;
    }
    conv = 1;
    samIdx = nSam - 1;
    sMaxRot = maxRot;
    sMaxTran.vtX =  maxTran.vtX / *(samFac + nSam - 1);
    sMaxTran.vtY =  maxTran.vtY / *(samFac + nSam - 1);
    while((errNum == WLZ_ERR_NONE) && conv && (samIdx >= 0))
    {
      /* Compute initial transform. */
      rot1 = rot0;
      tran1.vtX = tran0.vtX / *(samFac + samIdx);
      tran1.vtY = tran0.vtY / *(samFac + samIdx);
      samRegTr0 = WlzAffineTransformFromPrimVal(WLZ_TRANSFORM_2D_AFFINE,
      					        tran1.vtX, tran1.vtY, 0.0, 1.0, 
						rot1, 0.0, 0.0, 0.0, 0.0, 0,
						&errNum);
      /* Compute registration transform. */
      if(errNum == WLZ_ERR_NONE)
      {
	samRegTr1 = WlzRegCCorObjs2D1(*(sTObj + samIdx), *(sSObj + samIdx),
				      samRegTr0,
				      trType, sMaxTran, sMaxRot, maxItr,
				      winFn, noise,
				      &conv, &cCor, &errNum);
        
      }
      if(samRegTr0)
      {
        (void )WlzFreeAffineTransform(samRegTr0);
	samRegTr0 = NULL;
      }
      if(samRegTr1)
      {
        samRegTr0 = samRegTr1;
	samRegTr1 = NULL;
      }
      if(errNum == WLZ_ERR_NONE)
      {
        errNum = WlzAffineTransformPrimGet(samRegTr0, &trPrim);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	rot0 = trPrim.theta;
	tran0.vtX = trPrim.tx * *(samFac + samIdx);
	tran0.vtY = trPrim.ty * *(samFac + samIdx);
      }
      /* Set registration limits. */
      sMaxRot = WLZ_M_PI / 24.0;
      sMaxTran.vtX = samFacStep * 3;
      sMaxTran.vtY = samFacStep * 3;
      --samIdx;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(dstConv)
    {
      *dstConv = conv;
    }
    if(dstCCor)
    {
      *dstCCor = cCor;
    }
    regTr = samRegTr0;
  }
  AlcFree(samFac);
  /* Free subsampled objects. */
  if(sTObj)
  {
    for(samIdx = 0; samIdx < nSam; ++samIdx)
    {
      (void )WlzFreeObj(*(sTObj + samIdx));
    }
    AlcFree(sTObj);
  }
  if(sSObj)
  {
    for(samIdx = 0; samIdx < nSam; ++samIdx)
    {
      (void )WlzFreeObj(*(sSObj + samIdx));
    }
    AlcFree(sSObj);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(regTr);
}
Example #3
0
/*!
* \return	Translation.
* \ingroup	WlzRegistration
* \brief	Registers the given 2D domain objects using a
*               frequency domain cross correlation, to find
*               the translation which has the highest cross
*               correlation value.
* \param	tObj			The target object. Must have
*                                       been assigned.
* \param	sObj			The source object to be
*                                       registered with target object.
*                                       Must have been assigned.
* \param	initTr			Initial affine transform
*                                       to be applied to the source
*                                       object prior to registration.
* \param        maxTran    		Maximum translation.
* \param	maxTran			Maximum translation.
* \param	winFn			Window function.
* \param	noise			Use Gaussian noise if non-zero.
* \param	dstCCor			Destination ptr for the cross
*                                       correlation value, may be NULL.
* \param	dstErr			Destination error pointer,
*                                       may be NULL.
*/
static WlzDVertex2 WlzRegCCorObjs2DTran(WlzObject *tObj, WlzObject *sObj,
					WlzAffineTransform *initTr,
					WlzDVertex2 maxTran,
					WlzWindowFnType winFn, int noise,
					double *dstCCor, WlzErrorNum *dstErr)
{
  int		oIdx;
  double	cCor = 0.0;
  double	sSq[2];
  double	**oAr[2];
  WlzIBox2	aBox;
  WlzIBox2	oBox[2],
  		pBox[2];
  WlzIVertex2	aSz,
  		aOrg,
		centre,
		radius,
		tran;
  WlzDVertex2	dstTran;
  WlzObject	*oObj[2],
  		*pObj[2];
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  dstTran.vtX = 0.0;
  dstTran.vtY = 0.0;
  oAr[0] = oAr[1] = NULL;
  oObj[0] = oObj[1] = NULL;
  pObj[0] = pObj[1] = NULL;
  oObj[0] = WlzAssignObject(tObj, NULL);
  /* Transform source object. */
  if((initTr == NULL) || WlzAffineTransformIsIdentity(initTr, NULL))
  {
    oObj[1] = WlzAssignObject(sObj, NULL);
  }
  else
  {
    oObj[1] = WlzAssignObject(
              WlzAffineTransformObj(sObj, initTr, WLZ_INTERPOLATION_NEAREST,
				    &errNum), NULL);
  }
  /* Preprocess the objects. */
  if(errNum == WLZ_ERR_NONE)
  {
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      oBox[oIdx] = WlzBoundingBox2I(oObj[oIdx], &errNum);
      ++oIdx;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      centre.vtX = (oBox[oIdx].xMin + oBox[oIdx].xMax) / 2;
      centre.vtY = (oBox[oIdx].yMin + oBox[oIdx].yMax) / 2;
      radius.vtX = (oBox[oIdx].xMax - oBox[oIdx].xMin) / 2;
      radius.vtY = (oBox[oIdx].yMax - oBox[oIdx].yMin) / 2;
      pObj[oIdx] = WlzAssignObject(
                   WlzRegCCorPProcessObj2D(oObj[oIdx], winFn, centre, radius,
      					   &errNum), NULL);
      ++oIdx;
    }
  }
  /* Create double arrays. */
  if(errNum == WLZ_ERR_NONE)
  {
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      pBox[oIdx] = WlzBoundingBox2I(pObj[oIdx], &errNum);
      ++oIdx;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    aBox.xMin = WLZ_MIN(pBox[0].xMin, pBox[1].xMin) - (int )(maxTran.vtX) + 1;
    aBox.yMin = WLZ_MIN(pBox[0].yMin, pBox[1].yMin) - (int )(maxTran.vtY) + 1;
    aBox.xMax = WLZ_MAX(pBox[0].xMax, pBox[1].xMax) + (int )(maxTran.vtX) + 1;
    aBox.yMax = WLZ_MAX(pBox[0].yMax, pBox[1].yMax) + (int )(maxTran.vtY) + 1;
    aOrg.vtX = aBox.xMin;
    aOrg.vtY = aBox.yMin;
    aSz.vtX = aBox.xMax - aBox.xMin + 1;
    aSz.vtY = aBox.yMax - aBox.yMin + 1;
    (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtX), aSz.vtX);
    (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtY), aSz.vtY);
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      errNum = WlzToArray2D((void ***)&(oAr[oIdx]), pObj[oIdx], aSz, aOrg,
      			    noise, WLZ_GREY_DOUBLE);
      ++oIdx;
    }
  }
  if((dstCCor != NULL) && (errNum == WLZ_ERR_NONE))
  {
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      WlzArrayStats2D((void **)(oAr[oIdx]), aSz, WLZ_GREY_DOUBLE, NULL, NULL,
		      NULL, &(sSq[oIdx]), NULL, NULL);
      ++oIdx;
    }
  }
#ifdef WLZ_REGCCOR_DEBUG
  if(errNum == WLZ_ERR_NONE)
  {
    FILE	*fP = NULL;
    WlzObject	*cCObjT = NULL;
    
    cCObjT = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg,
			    WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE,
			    0.0, 1.0, 0, 0, &errNum);
    if(cCObjT)
    {
      if((fP = fopen("oObjT0.wlz", "w")) != NULL)
      {
	(void )WlzWriteObj(fP, cCObjT);
	(void )fclose(fP);
      }
      (void )WlzFreeObj(cCObjT);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    FILE	*fP = NULL;
    WlzObject	*cCObjT = NULL;
    
    cCObjT = WlzFromArray2D((void **)(oAr[1]), aSz, aOrg,
			    WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE,
			    0.0, 1.0, 0, 0, &errNum);
    if(cCObjT)
    {
      if((fP = fopen("oObjT1.wlz", "w")) != NULL)
      {
	(void )WlzWriteObj(fP, cCObjT);
	(void )fclose(fP);
      }
      (void )WlzFreeObj(cCObjT);
    }
  }
#endif /* WLZ_REGCCOR_DEBUG */
  /* Cross correlate. */
  if(errNum == WLZ_ERR_NONE)
  {
    (void )AlgCrossCorrelate2D(oAr[0], oAr[1], aSz.vtX, aSz.vtY);
    AlgCrossCorrPeakXY(&(tran.vtX), &(tran.vtY), &cCor, oAr[0],
		       aSz.vtX, aSz.vtY, maxTran.vtX, maxTran.vtY);
  }
#ifdef WLZ_REGCCOR_DEBUG
  if(errNum == WLZ_ERR_NONE)
  {
    FILE	*fP = NULL;
    WlzObject	*cCObjT = NULL;
    
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      (void )WlzGreyStats(pObj[oIdx], NULL, NULL, NULL, NULL, &(sSq[oIdx]),
			  NULL, NULL, &errNum);
      ++oIdx;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      cCObjT = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg,
			      WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE,
			      0.0,
			      255.0 / (1.0 + (sqrt(sSq[0] * sSq[1]) *
			      		      aSz.vtX * aSz.vtY)),
			      0, 0, &errNum);
    }
    if(cCObjT)
    {
      if((fP = fopen("cCObjT.wlz", "w")) != NULL)
      {
	(void )WlzWriteObj(fP, cCObjT);
	(void )fclose(fP);
      }
      (void )WlzFreeObj(cCObjT);
    }
  }
#endif /* WLZ_REGCCOR_DEBUG */
  for(oIdx = 0; oIdx < 2; ++oIdx)
  {
    (void )WlzFreeObj(oObj[oIdx]);
    (void )WlzFreeObj(pObj[oIdx]);
    AlcDouble2Free(oAr[oIdx]);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    dstTran.vtX = tran.vtX;
    dstTran.vtY = tran.vtY;
    if(dstCCor)
    {
      cCor = cCor / (1.0 + (sqrt(sSq[0] * sSq[1]) * aSz.vtX * aSz.vtY));
      *dstCCor = cCor;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstTran);
}
Example #4
0
/*!
* \return	Angle of roatation.
* \ingroup	WlzRegistration
* \brief	Polar samples then registers the given 2D domain objects
*               using a frequency domain cross correlation, to find
*               the angle of rotation about the given centre of rotation
*               which has the highest cross correlation value.
*		The rotation is always about the objects cente of mass.
* \param	tObj			The target object. Must have
*                                       been assigned.
* \param	sObj			The source object to be
*                                       registered with target object.
*                                       Must have been assigned.
* \param	initTr			Initial affine transform
*                                       to be applied to the source
*                                       object prior to registration.
* \param	maxRot			Maximum rotation.
* \param	winFn			Window function.
* \param	noise			Use Gaussian noise if non-zero.
* \param	dstErr			Destination error pointer,
*                                       may be NULL.
*/
static double	WlzRegCCorObjs2DRot(WlzObject *tObj, WlzObject *sObj,
				    WlzAffineTransform *initTr, double maxRot,
				    WlzWindowFnType winFn, int noise,
				    WlzErrorNum *dstErr)
{
  int		oIdx,
  		angCnt;
  double	angInc,
  		dstRot = 0.0;
  WlzIBox2	aBox;
  WlzIBox2	oBox[2];
  WlzIVertex2	rot,
  		aSz,
  		aOrg,
		winRad,
		winOrg,
		rotPad,
		rotCentreI;
  double	**oAr[2];
  WlzObject	*oObj[2],
  		*pObj[2],
		*wObj[2];
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	rotCnt = 500;
  const double	distInc = 1.0;

  /* Assign the target and transform source objects. */
  oAr[0] = oAr[1] = NULL;
  oAr[0] = oAr[1] = NULL;
  oObj[0] = oObj[1] = NULL;
  pObj[0] = pObj[1] = NULL;
  wObj[0] = wObj[1] = NULL;
  oObj[0] = WlzAssignObject(tObj, NULL);
  if((initTr == NULL) || WlzAffineTransformIsIdentity(initTr, NULL))
  {
    oObj[1] = WlzAssignObject(sObj, NULL);
  }
  else
  {
    oObj[1] = WlzAssignObject(
    	      WlzAffineTransformObj(sObj, initTr, WLZ_INTERPOLATION_NEAREST,
				   &errNum), NULL);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      tObj = WlzAutoCor(oObj[oIdx], &errNum);
      (void )WlzFreeObj(oObj[oIdx]);
      oObj[oIdx] = WlzAssignObject(tObj, NULL);
      ++oIdx;
    }
  }
  /* Compute rectangular to polar transformation. */
  if(errNum == WLZ_ERR_NONE)
  {
    angInc = (2.0 * (maxRot + WLZ_M_PI)) / rotCnt;
    angCnt = (2.0 * WLZ_M_PI) / angInc;
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      rotCentreI.vtX = 0;
      rotCentreI.vtY = 0;
      if(errNum == WLZ_ERR_NONE)
      {
	pObj[oIdx] = WlzAssignObject(
		     WlzPolarSample(oObj[oIdx], rotCentreI, angInc, distInc,
				    angCnt, 0, &errNum), NULL);
      }
      ++oIdx;
    }
  }
  /* Preproccess the objects using windows or noise. */
  if(errNum == WLZ_ERR_NONE)
  {
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      oBox[oIdx] = WlzBoundingBox2I(pObj[oIdx], &errNum);
      if(errNum == WLZ_ERR_NONE)
      {
	winOrg.vtX = (oBox[oIdx].xMax + oBox[oIdx].xMin) / 2;
	winOrg.vtY = (oBox[oIdx].yMax + oBox[oIdx].yMin) / 2;
	winRad.vtX = (oBox[oIdx].xMax - oBox[oIdx].xMin) / 2;
	winRad.vtY = (oBox[oIdx].yMax - oBox[oIdx].yMin) / 2;
	wObj[oIdx] = WlzAssignObject(
		     WlzRegCCorPProcessObj2D(pObj[oIdx], winFn,
					     winOrg, winRad, 
					     &errNum), NULL);
      }
      ++oIdx;
    }
  }
  /* Create 2D double arrays from the polar sampled objects. */
  if(errNum == WLZ_ERR_NONE)
  {
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      oBox[oIdx] = WlzBoundingBox2I(wObj[oIdx], &errNum);
      ++oIdx;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    aBox.xMin = WLZ_MIN(oBox[0].xMin, oBox[1].xMin);
    aBox.yMin = WLZ_MIN(oBox[0].yMin, oBox[1].yMin);
    aBox.xMax = WLZ_MAX(oBox[0].xMax, oBox[1].xMax);
    aBox.yMax = WLZ_MAX(oBox[0].yMax, oBox[1].yMax);
    rotPad.vtX = (aBox.xMax - aBox.xMin) / 2;
    rotPad.vtY = 1 + WLZ_NINT(maxRot / angInc);
    aBox.yMin -= rotPad.vtY;
    aBox.yMax += rotPad.vtY;
    aOrg.vtX = aBox.xMin;
    aOrg.vtY = aBox.yMin;
    aSz.vtX = aBox.xMax - aBox.xMin + 1;
    aSz.vtY = aBox.yMax - aBox.yMin + 1;
    (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtX), aSz.vtX);
    (void )AlgBitNextPowerOfTwo((unsigned int *)&(aSz.vtY), aSz.vtY);
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      errNum = WlzToArray2D((void ***)&(oAr[oIdx]), wObj[oIdx], aSz, aOrg,
      			    noise, WLZ_GREY_DOUBLE);
      ++oIdx;
    }
  }
#ifdef WLZ_REGCCOR_DEBUG
  if(errNum == WLZ_ERR_NONE)
  {
    FILE	*fP = NULL;
    WlzObject	*aObj = NULL;

    aObj = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg,
    			  WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0,
			  0, 0, &errNum);
    if((fP = fopen("cObjR0.wlz", "w")) != NULL) 
    {
      (void )WlzWriteObj(fP, aObj); 
      (void )fclose(fP);
    }
    WlzFreeObj(aObj);
    aObj = WlzFromArray2D((void **)(oAr[1]), aSz, aOrg,
    			  WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0,
			  0, 0, &errNum);
    if((fP = fopen("cObjR1.wlz", "w")) != NULL)
    {
      (void )WlzWriteObj(fP, aObj);
      (void )fclose(fP);
    }
    WlzFreeObj(aObj);
  }
#endif /* WLZ_REGCCOR_DEBUG */
  /* Cross correlate. */
  if(errNum == WLZ_ERR_NONE)
  {
    (void )AlgCrossCorrelate2D(oAr[0], oAr[1], aSz.vtX, aSz.vtY);
    AlgCrossCorrPeakXY(&(rot.vtX), &(rot.vtY), NULL, oAr[0],
		       aSz.vtX, aSz.vtY, rotPad.vtX, rotPad.vtY);
    dstRot = rot.vtY * angInc;
    /* dstRot = -(rot.vtY) * angInc; */
  }
#ifdef WLZ_REGCCOR_DEBUG
  if(errNum == WLZ_ERR_NONE)
  {
    double	sSq[2];
    FILE	*fP = NULL;
    WlzObject	*cCObjR = NULL;
    
    oIdx = 0;
    while((errNum == WLZ_ERR_NONE) && (oIdx < 2))
    {
      (void )WlzGreyStats(wObj[oIdx], NULL, NULL, NULL, NULL, &(sSq[oIdx]),
			  NULL, NULL, &errNum);
      ++oIdx;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      cCObjR = WlzFromArray2D((void **)(oAr[0]), aSz, aOrg,
			      WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE,
			      0.0,
			      255.0 / (1.0 + (sqrt(sSq[0] * sSq[1]) *
			      		      aSz.vtX * aSz.vtY)),
			      0, 0, &errNum);
    }
    if(cCObjR)
    {
      if((fP = fopen("cCObjR.wlz", "w")) != NULL)
      {
	(void )WlzWriteObj(fP, cCObjR);
	(void )fclose(fP);
      }
      (void )WlzFreeObj(cCObjR);
    }
  }
#endif /* WLZ_REGCCOR_DEBUG */
  for(oIdx = 0; oIdx < 2; ++oIdx)
  {
    (void )WlzFreeObj(oObj[oIdx]);
    (void )WlzFreeObj(pObj[oIdx]);
    (void )WlzFreeObj(wObj[oIdx]);
    AlcDouble2Free(oAr[oIdx]);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(dstRot);
}
Example #5
0
/*!
* \return	Autocorrelated object or NULL on error.
* \ingroup	WlzRegistration
* \brief	Computes the autocorrelation of the given 2D object, see
*		WlzAutoCor().
* \param	gObj			Given object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzObject *WlzAutoCor2D(WlzObject *gObj, WlzErrorNum *dstErr)
{
  WlzIVertex2	aSz,
		wSz,
		aOrg,
  		wOrg;
  WlzIBox2	box;
  double	**wAr = NULL,
  		**aAr = NULL;
  WlzObject     *aObj = NULL;
  WlzErrorNum   errNum = WLZ_ERR_NONE;

  if(gObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(gObj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(gObj->values.core == NULL)
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    box = WlzBoundingBox2I(gObj, &errNum);
    aSz.vtX = box.xMax - box.xMin + 1;
    aSz.vtY = box.yMax - box.yMin + 1;
    /* Make sure aSz is even in x and y. */
    if((aSz.vtX & 1) != 0)
    {
      aSz.vtX += 1;
    }
    if((aSz.vtY & 1) != 0)
    {
      aSz.vtY += 1;
    }
    wOrg.vtX = box.xMin - (aSz.vtX / 2);
    wOrg.vtY = box.yMin - (aSz.vtY / 2);
    wSz.vtX = aSz.vtX * 2;
    wSz.vtY = aSz.vtY * 2;
    (void )AlgBitNextPowerOfTwo((unsigned int *)&(wSz.vtX), wSz.vtX);
    (void )AlgBitNextPowerOfTwo((unsigned int *)&(wSz.vtY), wSz.vtY);
    errNum = WlzToArray2D((void ***)&wAr, gObj, wSz, wOrg, 0, WLZ_GREY_DOUBLE);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    (void )AlgAutoCorrelate2D(wAr, wSz.vtX, wSz.vtY);
    if(AlcDouble2Malloc(&aAr, aSz.vtY, aSz.vtX) != ALC_ER_NONE)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    WlzAutoCorRearrange2D(aAr, aSz, wAr, wSz);
    aOrg.vtX = -(aSz.vtX / 2);
    aOrg.vtY = -(aSz.vtY / 2);
    aObj = WlzFromArray2D((void **)aAr, aSz, aOrg,
                          WLZ_GREY_DOUBLE, WLZ_GREY_DOUBLE, 0.0, 1.0,
			  0, 0, &errNum);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(aObj != NULL)
    {
      (void )WlzFreeObj(aObj);
    }
  }
  (void )Alc2Free((void **)wAr);
  (void )Alc2Free((void **)aAr);
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(aObj);
}
Example #6
0
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Splits the reference object into component objects cliped
*		from the reference object, with the bounding box of each
*		of the component objects determined using the pre-processed
*		object. The component objects are returned in size order.
* \param	refObj			Reference object.
* \param	ppObj			Pre-processed object which is
*					normalised to values in the range
*					0 - 255 as WlzUByte greys.
* \param	bWidth			Border width.
* \param	bgdFrac			Minimum fraction of values which are
* 					background values, with range
*					[0.0+ - 1.0-].
* \param	sigma			Histogram smoothing parameter used
*					by WlzHistogramCnvGauss().
* \param	compThrMethod		Method for computing threshold, used
*					in call to WlzCompThresholdVT().
* \param	nReqComp		Number of required components.
* \param	dstNComp		Destination pointer for the number of
*					components extracted, must not be NULL.
* \param	dstComp			Destination pointer for the extracted
*					components, must not be NULL.
*/
WlzErrorNum	WlzSplitObj(WlzObject *refObj, WlzObject *ppObj,
			      int bWidth, double bgdFrac, double sigma,
			      WlzCompThreshType compThrMethod,
			      int nReqComp, int *dstNComp,
			      WlzObject ***dstComp)
{
  int		dim,
  		idC;
  WlzObject	*hObj = NULL,
  		*tObj = NULL;
  WlzObject 	**comp = NULL;
  WlzBox	box;
  WlzPixelV	tV;
  WlzSplitObjData split;
  WlzThresholdType tType;
  WlzConnectType lCon;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const int	maxComp = 1024;

  split.nLComp = 0;
  split.compI = NULL;
  split.lCompSz = NULL;
  split.lComp = NULL;
  if((refObj == NULL) || (ppObj == NULL))
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((refObj->domain.core == NULL) || (ppObj->domain.core == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((refObj->values.core == NULL) || (ppObj->values.core == NULL))
  {
    errNum = WLZ_ERR_VALUES_NULL;
  }
  else if(refObj->type != ppObj->type)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if((dstNComp == NULL) || (dstComp == NULL))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else if((bgdFrac < DBL_EPSILON) || (bgdFrac > (1.0 - DBL_EPSILON)))
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(refObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	dim = 2;
        lCon = WLZ_8_CONNECTED;
	break;
      case WLZ_3D_DOMAINOBJ:
	dim = 3;
        lCon = WLZ_26_CONNECTED;
	break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  /* Compute threshold value and type from histogram. */
  if(errNum == WLZ_ERR_NONE)
  {
    hObj = WlzAssignObject(
    	   WlzHistogramObj(ppObj, 256, 0.0, 1.0, &errNum), NULL);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzHistogramCnvGauss(hObj, sigma, 0);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzCompThresholdVT(hObj, compThrMethod, bgdFrac, 0.0,
    			        0.0, &tV, &tType);
  }
  (void )WlzFreeObj(hObj); hObj = NULL;
  /* Threshold object. */
  if(errNum == WLZ_ERR_NONE)
  {
    tObj = WlzAssignObject(
     	   WlzThreshold(ppObj, tV, tType, &errNum), NULL);
  }
  /* Label to get connected components. */
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzLabel(tObj, &(split.nLComp), &(split.lComp), maxComp, 0, lCon);
  }
  /* Sort connected components by size. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(split.nLComp < nReqComp)
    {
      nReqComp = split.nLComp;
    }
    if(((split.compI = (int *)AlcMalloc(sizeof(int) *
                                        split.nLComp)) == NULL) ||
       ((split.lCompSz = (int *)AlcMalloc(sizeof(int) *
                                          split.nLComp)) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    idC = 0; 
    while((errNum == WLZ_ERR_NONE) && (idC < split.nLComp))
    {
      split.compI[idC] = idC;
      split.lCompSz[idC] = (dim == 2)? WlzArea(split.lComp[idC], &errNum):
      				       WlzVolume(split.lComp[idC], &errNum);
      ++idC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Sort component indices by component size. */
    AlgQSort(split.compI, split.nLComp, sizeof(int), &split,
    	     WlzSplitObjSortSzFn);
    /* Allocate array for cliped component objects. */
    if((comp = (WlzObject **)AlcCalloc(sizeof(WlzObject *),
    				       split.nLComp)) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute bounding box and clip objects from the reference object. */
  if(errNum == WLZ_ERR_NONE)
  {
    idC = 0;
    while((errNum == WLZ_ERR_NONE) && (idC < nReqComp))
    {
      if(dim == 2)
      {
        box.i2 = WlzBoundingBox2I(split.lComp[split.compI[idC]], &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  box.i2.xMin -= bWidth;
	  box.i2.yMin -= bWidth;
	  box.i2.xMax += bWidth;
	  box.i2.yMax += bWidth;
	  comp[idC] = WlzClipObjToBox2D(refObj, box.i2, &errNum);
	}
      }
      else /* dim == 3 */
      {
        box.i3 = WlzBoundingBox3I(split.lComp[split.compI[idC]], &errNum);
	if(errNum == WLZ_ERR_NONE)
	{
	  box.i3.xMin -= bWidth;
	  box.i3.yMin -= bWidth;
	  box.i3.zMin -= bWidth;
	  box.i3.xMax += bWidth;
	  box.i3.yMax += bWidth;
	  box.i3.zMax += bWidth;
	  comp[idC] = WlzClipObjToBox3D(refObj, box.i3, &errNum);
	}
      }
      ++idC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    *dstNComp = nReqComp;
    *dstComp = comp;
  }
  /* Free temporary storage. */
  if(split.lComp)
  {
    for(idC = 0; idC < split.nLComp; ++idC)
    {
      (void )WlzFreeObj(split.lComp[idC]);
    }
    AlcFree(split.lComp);
  }
  AlcFree(split.compI);
  AlcFree(split.lCompSz);
  (void )WlzFreeObj(tObj);
  return(errNum);
}
Example #7
0
/*!
* \return	Woolz error code.
* \ingroup	WlzBinaryOps
* \brief	Splits the given montage object into component objects
*		clipped from the montage object.  The montage object
*		must be composed of component images embedded in a
*		background, with little variation in the background
*		values.
* \param	mObj			Montage object, which must be either
*					a WLZ_2D_DOMAINOBJ or a
*					WLZ_3D_DOMAINOBJ with values.
* \param	gapV			Value for the uniform background.
*					Must be either WLZ_GREY_INT or
*					WLZ_GREY_RGBA.
* \param	tol			Tolerance (fraction) for the
*					variation in background values.
* \param	bWidth			Additional boundary width added
*					to detected images before they are
*					clipped.
* \param	minArea			Minimum area for a valid component
*					image, must be greater than zero.
* \param	maxComp			Maximum number of components.
* \param	dstNComp		Destination pointer for the number of
*					components extracted, must not be NULL.
* \param	dstComp			Destination pointer for the extracted
*					components, must not be NULL.
*/
WlzErrorNum 	WlzSplitMontageObj(WlzObject *mObj, WlzPixelV gapV,
				      double tol, int bWidth, int minArea,
				      int maxComp,
				      int *dstNComp, WlzObject ***dstComp)
{
  int		id0,
  		id1,
		area,
		nLComp = 0;
  WlzObject	*gObj = NULL,
  		*tObj = NULL;
  WlzObject	**lComp;
  WlzGreyType	objG;
  WlzBox	box;
  WlzPixelV	gapLV,
  		gapHV;
  WlzConnectType lCon;
  int		tI[8];
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  tol = WLZ_CLAMP(tol, 0.0, 1.0);
  if(mObj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(minArea < 1)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else
  {
    switch(mObj->type)
    {
      case WLZ_2D_DOMAINOBJ:
	lCon = WLZ_4_CONNECTED;
        break;
      case WLZ_3D_DOMAINOBJ:
	lCon = WLZ_6_CONNECTED;
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    objG = WlzGreyTypeFromObj(mObj, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(gapV.type)
    {
      case WLZ_GREY_INT: /* FALLTHROUGH */
      case WLZ_GREY_RGBA:
        break;
      default:
	errNum = WLZ_ERR_GREY_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(objG == WLZ_GREY_RGBA)
    {
      if(gapV.type != WLZ_GREY_RGBA)
      {
        (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_RGBA);
      }
    }
    else
    {
      if(gapV.type != WLZ_GREY_INT)
      {
        (void )WlzValueConvertPixel(&gapV, gapV, WLZ_GREY_INT);
      }
    }
    gapLV.type = gapHV.type = gapV.type;
    if(gapV.type == WLZ_GREY_INT)
    {
      tI[0] = gapV.v.inv * tol;
      gapLV.v.inv = gapV.v.inv - tI[0];
      gapHV.v.inv = gapV.v.inv + tI[0];
      tObj = WlzThreshold(mObj, gapLV, WLZ_THRESH_HIGH, &errNum);
      if((errNum == WLZ_ERR_NONE) && (tObj != NULL))
      {
	gObj = WlzThreshold(tObj, gapHV, WLZ_THRESH_LOW, &errNum);
      }
      (void )WlzFreeObj(tObj);
      tObj = NULL;
    }
    else /* gapV.type == WLZ_GREY_RGBA */
    {
	tI[0] = WLZ_RGBA_RED_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[2] = tI[0] - tI[1];
	tI[5] = tI[0] + tI[1];
	tI[0] = WLZ_RGBA_GREEN_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[3] = tI[0] - tI[1];
	tI[6] = tI[0] + tI[1];
	tI[0] = WLZ_RGBA_BLUE_GET(gapV.v.rgbv);
	tI[1] = (int )floor((double )(tI[0]) * tol);
	tI[4] = tI[0] - tI[1];
	tI[7] = tI[0] + tI[1];
	tI[2] = WLZ_CLAMP(tI[2], 0, 255);
	tI[3] = WLZ_CLAMP(tI[3], 0, 255);
	tI[4] = WLZ_CLAMP(tI[4], 0, 255);
	WLZ_RGBA_RGBA_SET(gapLV.v.rgbv, tI[2], tI[3], tI[4], 255);
	tI[5] = WLZ_CLAMP(tI[5], 0, 255);
	tI[6] = WLZ_CLAMP(tI[6], 0, 255);
	tI[7] = WLZ_CLAMP(tI[7], 0, 255);
	WLZ_RGBA_RGBA_SET(gapHV.v.rgbv, tI[5], tI[6], tI[7], 255);
        gObj = WlzRGBABoxThreshold(mObj, gapLV, gapHV, &errNum);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    tObj = WlzDiffDomain(mObj, gObj, &errNum);
  }
  (void )WlzFreeObj(gObj);
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzLabel(tObj, &nLComp, &lComp, maxComp, 0, lCon);
  }
  (void )WlzFreeObj(tObj);
  if(errNum == WLZ_ERR_NONE)
  {
    /* Get rid of small objects using minArea as the threshold. */
    id0 = 0;
    id1 = 0;
    while(id0 < nLComp)
    {
      switch((*(lComp + id0))->type)
      {
        case WLZ_2D_DOMAINOBJ:
	  area = WlzArea(*(lComp + id0), NULL);
	  break;
        case WLZ_3D_DOMAINOBJ:
	  area = WlzVolume(*(lComp + id0), NULL);
	  break;
        default:
          area = 0;
	  break;
      }
      if(area >= minArea)
      {
        *(lComp + id1) = *(lComp + id0);
        ++id1;
      }
      else
      {
        (void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = NULL;
      }
      ++id0;
    }
    nLComp = id1;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Clip rectangular objects from the montage object. */
    id0 = 0;
    while((errNum == WLZ_ERR_NONE) && (id0 < nLComp))
    {
      if(tObj->type == WLZ_2D_DOMAINOBJ)
      {
        box.i2 = WlzBoundingBox2I(*(lComp + id0), &errNum);
	box.i2.xMin -= bWidth;
	box.i2.yMin -= bWidth;
	box.i2.xMax += bWidth;
	box.i2.yMax += bWidth;
	(void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = WlzClipObjToBox2D(mObj, box.i2, &errNum);
      }
      else /* tObj->type == WLZ_3D_DOMAINOBJ */
      {
        box.i3 = WlzBoundingBox3I(*(lComp + id0), &errNum);
	box.i3.xMin -= bWidth;
	box.i3.yMin -= bWidth;
	box.i3.zMin -= bWidth;
	box.i3.xMax += bWidth;
	box.i3.yMax += bWidth;
	box.i3.zMax += bWidth;
	(void )WlzFreeObj(*(lComp + id0));
	*(lComp + id0) = WlzClipObjToBox3D(mObj, box.i3, &errNum);
      }
      ++id0;
    }
  }
  *dstNComp = nLComp;
  *dstComp = lComp;
  return(errNum);
}
Example #8
0
/*!
* \return	New filtered object with new values or NULL on error.
* \ingroup	WlzValuesFilters
* \brief	Applies a seperable filter along the y axis (lines)
* 		to the given object using the given convolution kernel.
* \param	inObj			Input 2 or 3D spatial domain object
* 					to be filtered which must have scalar
* 					values.
* \param	dim			Object's dimension.
* \param	maxThr			Maximum number of threads to use.
* \param	iBuf			Working buffers large enough for any
* 				        column in the image with one for each
* 				        thread.
* \param	rBuf			Buffers as for iBuf. 			
* \param	cBufSz			Convolution kernel size.
* \param	cBuf			Convolution kernel buffer.
* \param	pad			Type of padding.
* \param	padVal			Padding value.
* \param	dstErr			Destination error pointer may be NULL.
*/
static WlzObject		*WlzSepFilterY(WlzObject *inObj,
				  int dim,
				  int maxThr,
				  double **iBuf,
				  double **rBuf,
				  int cBufSz,
				  double *cBuf,
				  AlgPadType pad,
				  double padVal,
				  WlzErrorNum *dstErr)
{
  int		idp,
		poff,
  		nPln;
  WlzObjectType	rGTT;
  WlzDomain	*domains;
  WlzValues	*iVal,
  		*rVal;
  WlzPixelV	zV;
  WlzObject	*rnObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  		
  zV.v.dbv = 0.0;
  zV.type = WLZ_GREY_DOUBLE;
  rGTT = WlzGreyTableType(WLZ_GREY_TAB_RAGR, WLZ_GREY_DOUBLE, NULL);
  if(dim == 3)
  {
    WlzPlaneDomain *pDom;
    WlzVoxelValues *vVal;

    pDom = inObj->domain.p;
    vVal = inObj->values.vox;
    nPln = pDom->lastpl - pDom->plane1 + 1;
    domains = pDom->domains;
    iVal = vVal->values;
    poff = pDom->plane1 - vVal->plane1;
    rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      rVal = rnObj->values.vox->values;
    }
  }
  else
  {
    nPln = 1;
    poff = 0;
    domains = &(inObj->domain);
    iVal = &(inObj->values);
    rnObj = WlzNewObjectValues(inObj, rGTT, zV, 1, zV, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      rVal = &(rnObj->values);
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
#ifdef _OPENMP
#pragma omp parallel for num_threads(maxThr)
#endif
    for(idp = 0; idp < nPln; ++idp)
    {
      if(errNum == WLZ_ERR_NONE)
      {
	if(domains[idp].core != NULL)
	{
	  int		thrId = 0;
	  WlzIBox2	bBox;
	  WlzObject	*iObj = NULL,
			*rObj = NULL;
	  WlzGreyValueWSpace *iVWSp = NULL,
			     *rVWSp = NULL;
          WlzErrorNum	errNum2 = WLZ_ERR_NONE;

#ifdef _OPENMP
          thrId = omp_get_thread_num();
#endif
	  iObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], iVal[idp + poff],
			     NULL, NULL, &errNum);
	  if(errNum == WLZ_ERR_NONE)
	  {
	    rObj = WlzMakeMain(WLZ_2D_DOMAINOBJ, domains[idp], rVal[idp],
			       NULL, NULL, &errNum);
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    bBox = WlzBoundingBox2I(iObj, &errNum);
	  }
	  if((errNum == WLZ_ERR_NONE) &&
	     ((iVWSp = WlzGreyValueMakeWSp(iObj, &errNum)) != NULL) &&
	     ((rVWSp = WlzGreyValueMakeWSp(rObj, &errNum)) != NULL))
	  {
	    int		idx;

	    for(idx = bBox.xMin; idx <= bBox.xMax; ++idx)
	    {
	      int		y0,
			  y1,
			  idy;
	      WlzUByte	in = 0;

	      for(idy = bBox.yMin; idy <= bBox.yMax + 1; ++idy)
	      {
		WlzGreyValueGet(iVWSp, 0, idy, idx);
		if(iVWSp->bkdFlag == 0)
		{
		 double	*ibp;

		 if(in == 0)
		 {
		   y0 = idy;
		   in = 1;
		 }
		 y1 = idy;
		 ibp = iBuf[thrId] + (y1  - y0);
		 switch(iVWSp->gType)
		 {
		   case WLZ_GREY_INT:
		     *ibp = iVWSp->gVal[0].inv;
		     break;
		   case WLZ_GREY_SHORT:
		     *ibp = iVWSp->gVal[0].shv;
		     break;
		   case WLZ_GREY_UBYTE:
		     *ibp = iVWSp->gVal[0].ubv;
		     break;
		   case WLZ_GREY_FLOAT:
		     *ibp = iVWSp->gVal[0].flv;
		     break;
		   case WLZ_GREY_DOUBLE:
		     *ibp = iVWSp->gVal[0].dbv;
		     break;
		   default:
		     break;
		 }
		}
		else if(in)
		{
		  int 	idr,
			len;

		  len = y1 - y0 + 1;
		  AlgConvolveD(len, rBuf[thrId], cBufSz * 2 + 1, cBuf,
		               len, iBuf[thrId], pad, padVal);
		  for(idr = y0; idr <= y1; ++idr)
		  {
		    WlzGreyValueGet(rVWSp, 0, idr, idx);
		    *(rVWSp->gPtr[0].dbp) = rBuf[thrId][idr - y0];
		  }
		}
	      }
	    }
	  }
	  WlzGreyValueFreeWSp(iVWSp);
	  WlzGreyValueFreeWSp(rVWSp);
	  (void )WlzFreeObj(iObj);
	  (void )WlzFreeObj(rObj);
	  if(errNum2 != WLZ_ERR_NONE)
	  {
#ifdef _OPENMP
#pragma omp critical
	    {
#endif
	      if(errNum == WLZ_ERR_NONE)
	      {
	        errNum = errNum2;
	      }
#ifdef _OPENMP
	    }
#endif
	  }
	}
      }
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzFreeObj(rnObj);
    rnObj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(rnObj);
}