static void filterdensmap(real ****Densmap, int xslices, int yslices, int zslices, int tblocks, int ftsize) { real *kernel; real std, var; int i, j, n, order; order = ftsize/2; std = order/2.0; var = std*std; snew(kernel, ftsize); gausskernel(kernel, ftsize, var); for (n = 0; n < tblocks; n++) { for (i = 0; i < xslices; i++) { for (j = 0; j < yslices; j++) { periodic_convolution(zslices, Densmap[n][i][j], ftsize, kernel); } } } }
bool IODicom<T>::Read(PGCore::BaseDataObject *oDataObject, const IOParams &iParams, PGCore::BaseDataObject *oMetaDataObject/* = 0*/) { // read meta data first if (!oMetaDataObject) { LOG0("IO/IODicom::Read: metadata object null"); return false; } if (iParams.SourceType()!=kPgIOSourceTypeFile) { LOG0("IO/IODicom::Read: Expecting single file path."); return false; } if (!ReadMetaData(oMetaDataObject, iParams)) { LOG0("IO/IODicom::Read: ReadMetaData failed."); return false; } if (!oDataObject) { LOG0("IO/IODicom::Read: Invalid input image."); return false; } // cast to image type here PGCore::Image<T> *oImage = (static_cast<PGCore::Image < T > *>(oDataObject)); if (!oImage) { LOG0("IO/IODicom::Read: Invalid input image."); return false; } PGCore::MetaData<T> *oMetaData = (static_cast<PGCore::MetaData< T > *>(oMetaDataObject)); if (!oMetaData) { LOG0("IO/IOBase::Read: Invalid output container for metadata."); return false; } int frameCount = oMetaData->GetFrameCount(); int frameIndex = 0; if (frameCount>1) { frameIndex = iParams.GetActiveFrameIndex(); if (frameIndex<0 || frameIndex>(frameCount-1)) { LOG2("IO/IODicom::Read: Invalid frame index: %d/%d", frameIndex, frameCount); return false; } } //calculate the full size of the scalars const PGMath::Vector3D<int>& oSize = oMetaData->GetSize(); long ix=oSize.Y(), iy=oSize.X(); oImage->SetDimensions(ix, iy); T* oBuf = oImage->GetBuffer(); if (!oBuf) { LOG0("IO/IODicom::Read: Invalid image buffer."); return false; } bool needConversion = false; int nBitsPerPixel = oMetaData->GetNumberOfBits(); if (nBitsPerPixel!=8*sizeof(T)) { LOG2("IO/IODicom::Read:Warning: Pixel type mismatch. Need %d bits per pixel, but reporting %d.", nBitsPerPixel, 8*sizeof(T)); needConversion = true; //return false; } int oByteCount = (nBitsPerPixel/8) * ix * iy; long offset = frameIndex*ix*iy; unsigned char *iBuf=0; #ifdef _PG_GDDCM_ #else // read pixel data //DcmFileFormat fileformat; DcmDataset *dataset = m_fileformat.getDataset(); if (!dataset) { LOG0("IO/IODicom::Read: Cannot fetch pixel data"); return false; } switch (nBitsPerPixel) { case 8: dataset->findAndGetUint8Array(DCM_PixelData, (const Uint8 *&) iBuf); if (frameCount>1) { iBuf = (unsigned char *)((Uint8 *)iBuf + offset); } break; case 16: dataset->findAndGetUint16Array(DCM_PixelData, (const Uint16 *&) iBuf); if (frameCount>1) { iBuf = (unsigned char *)((Uint16 *)iBuf + offset); } break; default: LOG0("IO/IODicom::Read: failed to fetch image buffer."); return false; } #endif if (iBuf==0) { LOG0("IO/IODicom::Read: Invalid image buffer."); return false; } // we have to copy the data into the buffer already allocated if (!needConversion) { memcpy(oBuf, iBuf, oByteCount); } else { // first create a local image PGCore::Image<unsigned char> ucharImage; PGCore::Image<short> shortImage; unsigned char* localBuf = 0; switch (nBitsPerPixel) { case 8: ucharImage.SetDimensions(ix, iy); localBuf = (unsigned char *)ucharImage.GetBuffer(); break; case 16: shortImage.SetDimensions(ix, iy); localBuf = (unsigned char *)shortImage.GetBuffer(); break; default: break; } if (localBuf==0) { LOG0("IO/IODicom::Read: Invalid local image buffer."); return false; } // copy buffer locally memcpy(localBuf, iBuf, oByteCount); // now convert the pixels long i=0; while (i<ix*iy) { *(oBuf++) = T(*(localBuf++)); i++; } } if (GetSmoothFlag()) { PGCore::GaussianKernel<double, T> gausskernel(1.0f); PGCore::Image<T> sImage; gausskernel.Convolve(*oImage, sImage); *oImage = sImage; LOG0("\tIODicom::Smooth: Image DONE."); } //LOG0("IO/IODicom::Read: Image DONE."); //fclose(fptr); if (frameCount>1) { std::vector<PGMath::Vector3D<float>> orXVecs = oMetaData->GetImageOrientationsPatientX(); std::vector<PGMath::Vector3D<float>> orYVecs = oMetaData->GetImageOrientationsPatientY(); if (orXVecs.empty() || orYVecs.empty()) { LOG0("\tIODicom::Read: empty orientation vectors."); return false; } PGMath::Vector3D<float> orZVec = orXVecs[0] ^ orYVecs[0]; orZVec = orZVec*frameIndex; std::vector<PGMath::Vector3D<float>> posVecs; posVecs.push_back(orZVec); oMetaData->SetImagePositionsPatient(posVecs); } return true; }
bool IODicom<T>::Write(PGCore::BaseDataObject *iDataObject, const IOParams &iParams, PGCore::BaseDataObject *iMetaDataObject/* = 0*/) { // write meta data first /* if (!iMetaDataObject) { LOG0("IO/IODicom::Write: metadata object null"); return false; } */ if (!WriteMetaData(iMetaDataObject, iParams)) { LOG0("IO/IODicom::Write: failed to read metadata."); return false; } if (iParams.SourceType()!=kPgIOSourceTypeFile) { LOG0("IO/IODicom::Write: Expecting single file path."); return false; } const std::vector<std::string>& iPaths = iParams.Source(); if (iPaths.empty()) { LOG0("IO/IODicom::Read: Invalid input filename vector."); return false; } const std::string &oFileName = iPaths[0]; if (oFileName.empty()) { LOG0("IO/IODicom::Write: Invalid input filename."); return false; } if (!iDataObject) { LOG0("IO/IODicom::Write: Invalid input image."); return false; } // cast to image type here PGCore::Image<T> *iImage = (static_cast<PGCore::Image < T > *>(iDataObject)); if (!iImage) { LOG0("IO/IODicom::Write: Invalid input image."); return false; } long ioRows=0, ioCols=0; iImage->GetDimensions((long &)ioRows, (long &)ioCols); if (ioRows*ioCols <=0) { LOG0("IO/IODicom::Write: Invalid image dimensions."); return false; } PGCore::GaussianKernel<double, T> gausskernel(1.0f); if (GetSmoothFlag()) { PGCore::Image<T> sImage; gausskernel.Convolve(*iImage, sImage); *iImage = sImage; LOG1("IO/IODicom::Smooth Image [%s] DONE.", oFileName.c_str()); } LOG1("IO/IODicom::Write: Image [%s] DONE.", oFileName.c_str()); T* iBuf = iImage->GetBuffer(); if (!iBuf) { LOG0("IO/IODicom::Write: Invalid image buffer."); return false; } FILE *fptr = fopen (oFileName.c_str(), "wb"); if (!fptr) { LOG1("IO/IODicom::Write: failed to open file %s to write.", oFileName.c_str()); return false; } try { long rv = fwrite((const void *)iBuf, sizeof(T), ioRows*ioCols, fptr); if (rv!= ioRows*ioCols) { fclose(fptr); LOG1("IO/IODicom::Write: failed to write file %s. Possible overrun.", oFileName.c_str()); return false; } } catch (...) { fclose(fptr); LOG1("IO/IODicom::Write: failed to write file %s. Possible overrun.", oFileName.c_str()); return false; } fclose(fptr); return true; }
bool ImageEdgeDetectionBase<T, U>::detectEdges(float iSigma, /* Standard deviation of the gaussian kernel. */ float iTlow, /* Fraction of the high threshold in hysteresis. */ float iThigh, PGCore::Image<T> *iInImage, PGCore::Image<U> *oEdgeImage //must be allocated outside ) { if (!iInImage || !oEdgeImage) return false; //iOutImage = iInImage; //char composedfname[128]; /* Name of the output "direction" image */ T *image = (T *)iInImage->GetBuffer(); /* The input image */ U *edge = (U *)oEdgeImage->GetBuffer(); /* The output edge image */ //int rows , cols; /* The dimensions of the image. */ //float sigma, /* Standard deviation of the gaussian kernel. */ // tlow, /* Fraction of the high threshold in hysteresis. */ // thigh; /* High hysteresis threshold control. The actual threshold is the (100 * thigh) percentage point in the histogram of the magnitude of the gradient image that passes non-maximal suppression. */ /**************************************************************************** * Get the command line arguments. ****************************************************************************/ //infilename = argv[1]; //sigma = iSigma;//atof(argv[2]); //tlow = iTlow;//atof(argv[3]); //thigh = iThigh;//atof(argv[4]); long rows, cols; iInImage->GetDimensions(rows, cols); //rows = (int)lrows; //cols = (int)lcols; /**************************************************************************** * Perform the edge detection. All of the work takes place here. ****************************************************************************/ //void canny(unsigned char *image, int rows, int cols, float sigma, // float tlow, float thigh, unsigned char **edge, char *fname) //{ //FILE *fpdir=NULL; /* File to write the gradient image to. */ //U *nms; /* Points that are local maximal magnitude. */ T *smoothedim; /* The image after gaussian smoothing. */ T *delta_x, /* The first devivative image, x-direction. */ *delta_y, /* The first derivative image, y-direction. */ *magnitude; /* The magnitude of the gadient image. */ //int r, c, pos; //float *dir_radians=NULL; /* Gradient direction image. */ #ifdef _DEBUG PGAlgs::DumpImageAsPGM(*iInImage, std::string("C:\\Tmp\\Dump\\OriginalImage.pgm")); #endif /**************************************************************************** * Perform gaussian smoothing on the image using the input standard * deviation. ****************************************************************************/ //if(0) printf("Smoothing the image using a gaussian kernel.\n"); //gaussian_smooth(image, rows, cols, sigma, &smoothedim); PGCore::Image<T> smoothedImage(rows, cols); PGCore::GaussianKernel<T, T> gausskernel(iSigma, 3); gausskernel.Convolve(*iInImage, smoothedImage); smoothedim = (T *)smoothedImage.GetBuffer(); #ifdef _DEBUG PGAlgs::DumpImageAsPGM(smoothedImage, std::string("C:\\Tmp\\Dump\\SmoothImage.pgm")); #endif /**************************************************************************** * Compute the first derivative in the x and y directions. ****************************************************************************/ //if(0) printf("Computing the X and Y first derivatives.\n"); //derrivative_x_y(smoothedim, rows, cols, &delta_x, &delta_y); PGCore::DerivativeOfGaussianKernel<T, T> derivOfGaussian(iSigma); PGCore::DiffOfGaussianKernel<T, T> dogFilter(iSigma+0.1f, iSigma); PGCore::Image<T> oImageDerivG(rows, cols), oImageDerivGX(rows, cols), oImageDerivGY(rows, cols); // X gradient if (1) { //gausskernel.Convolve1D_Y(smoothedImage, oImageDerivG); //derivOfGaussian.Convolve1D_X(oImageDerivG, oImageDerivGX); dogFilter.Convolve1D_X(smoothedImage, oImageDerivGX); delta_x = (T *)oImageDerivGX.GetBuffer(); #ifdef _DEBUG PGAlgs::DumpImageAsPGM(oImageDerivGX, std::string("C:\\Tmp\\Dump\\GradientX.pgm")); #endif } // Y gradient if (1) { //gausskernel.Convolve1D_X(smoothedImage, oImageDerivG); //derivOfGaussian.Convolve1D_Y(oImageDerivG, oImageDerivGY); dogFilter.Convolve1D_Y(smoothedImage, oImageDerivGY); delta_y = (T *)oImageDerivGY.GetBuffer(); #ifdef _DEBUG PGAlgs::DumpImageAsPGM(oImageDerivGY, std::string("C:\\Tmp\\Dump\\GradientY.pgm")); #endif } /**************************************************************************** * Compute the magnitude of the gradient. ****************************************************************************/ //if(0) printf("Computing the magnitude of the gradient.\n"); //magnitude_x_y(delta_x, delta_y, rows, cols, &magnitude); PGCore::Image<T> gradientMagntudeImage(rows, cols); magnitude = (T *)gradientMagntudeImage.GetBuffer(); { long imgIter = 0; while (imgIter< rows*cols) { double inValX = *(delta_x+imgIter); double inValY = *(delta_y+imgIter); //double inVal = fabs(inValX) + fabs(inValY);//inValX>inValY ? inValX : inValY; double inVal = sqrt((inValX)*(inValX) + (inValY)*(inValY));//inValX>inValY ? inValX : inValY; T outVal = (T)((inVal + 0.5f)); *(magnitude+imgIter) = outVal; imgIter++; } } #ifdef _DEBUG PGAlgs::DumpImageAsPGM(gradientMagntudeImage, std::string("C:\\Tmp\\Dump\\GradientMagnitude.pgm")); #endif /**************************************************************************** * Perform non-maximal suppression. ****************************************************************************/ PGCore::Image<U> nonMaxSuppressedImage(rows, cols); U* nms = (U *)nonMaxSuppressedImage.GetBuffer(); if(!nms) { return false; } bool rv = nonMaximumSuppression(magnitude, delta_x, delta_y, rows, cols, nms); if (!rv) return false; #ifdef _DEBUG PGAlgs::DumpImageAsPGM(nonMaxSuppressedImage, std::string("C:\\Tmp\\Dump\\NonMaxSuppressed.pgm")); #endif /**************************************************************************** * Use hysteresis to mark the edge pixels. ****************************************************************************/ //if(0) printf("Doing hysteresis thresholding.\n"); /* if((*edge=(unsigned char *)calloc(rows*cols,sizeof(unsigned char))) ==NULL){ fprintf(stderr, "Error allocating the edge image.\n"); exit(1); }*/ //error in here somewhere rv = applyHysteresis(magnitude, nms, rows, cols, iTlow, iThigh, edge); if (!rv) { return false; } #ifdef _DEBUG PGAlgs::DumpImageAsPGM(*oEdgeImage, std::string("C:\\Tmp\\Dump\\Edges.pgm")); #endif /**************************************************************************** * Free all of the memory that we allocated except for the edge image that * is still being used to store out result. ****************************************************************************/ //free(smoothedim); //free(delta_x); //free(delta_y); //free(magnitude); //free(nms); return rv; }