⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cu_extractdirs.cpp

📁 Edge detection in microscopy images using curvelets
💻 CPP
字号:
/* *  extractdirs.cpp * *  Created by Tobias Gebaeck on 12.9.2007. *  Copyright 2007 ETH Zurich. All rights reserved. * */#include "CurveletUtils.h"#include "numvec.hpp"#include <algorithm>using namespace std;using namespace fdct_wrapping_ns;using namespace fdct3d_ns;namespace CurveletUtils {const double PI = 3.141592653589793;// compute the direction of the curvelet (the direction along the valleys/ridges)// in the form of cosine and sine of anglevoid ComputeAngle(int idx, int nangles, double &cosa, double &sina){  int nangpquad = nangles/4;  double tana = 1.0 - (1.0 + 2.0*(idx % nangpquad)) / nangpquad;  double scf = sqrt(1 + tana*tana);	  switch (idx / (nangpquad)) { 		case 0:		case 2:			cosa = 1.0 / scf;			sina = tana / scf;			break;	    case 1:    case 3:      cosa = tana / scf;			sina = -1.0 / scf;       break;  }}	// Compute the direction of a 3D curvelet (normal to its plane), based on its index// Angles are spherical coordinates (theta, phi)	void ComputeAngle3D(int idx, int totangles, int angperdir, double &theta, double &phi)	{		int angperface = angperdir*angperdir;		int face = idx / angperface;		int k1 = idx % angperdir;		int k2 = (idx % angperface) / angperdir;		double alpha = (k1 - angperdir/2 + 0.5) / (angperdir/2.0);		double beta = (k2 - angperdir/2 + 0.5) / (angperdir/2.0); 				switch (face) {			case 0:				theta = PI/2.0 - atan(alpha); phi = PI/2.0 - atan(beta); break;			case 1:				theta = PI/2.0 - atan(beta); phi = atan(alpha); break;			case 2:				theta = atan(sqrt(alpha*alpha + beta*beta)); phi = atan2(beta, alpha); break;			case 3:				theta = PI/2.0 + atan(alpha); phi = -PI/2.0 - atan(beta); break;			case 4:				theta = PI/2.0 + atan(beta); phi = PI + atan(alpha); break;			case 5:				theta = PI - atan(sqrt(alpha*alpha + beta*beta)); phi = PI + atan2(beta,alpha); break;		}				if (phi > PI) phi -= 2.0*PI;		if (phi <= -PI) phi += 2.0*PI;	}// Map coordinates (ix,iy) with max dimensions (m,n) to level given by levmat// return indices on this level in (levx,levy)void MapCoordToLevel(const CpxNumMat &levmat, int ix, int iy, int m, int n, int& levx, int& levy){  levx = (int) (ix / double(m) * double(levmat.m()) + 0.5) % levmat.m();  levy = (int) (iy / double(n) * double(levmat.n()) + 0.5) % levmat.n();}	void MapCoordToLevel3D(const CpxNumTns &levtns, int ix, int iy, int iz, int m, int n, int p, int &levx, int &levy, int &levz)	{		levx = (int) (ix / double(m) * double(levtns.m()) + 0.5) % levtns.m();		levy = (int) (iy / double(n) * double(levtns.n()) + 0.5) % levtns.n();		levz = (int) (iz / double(p) * double(levtns.p()) + 0.5) % levtns.p();	}	// Map coordinates (ix,iy) with max dimensions (m,n) to level of actual size (mp,np)// return indices on this level in (levx,levy)void MapCoordToLevelME(int mp, int np, int ix, int iy, int m, int n, int& levx, int& levy){	levx = (int) (ix / double(m) * double(mp) + 0.5);	levy = (int) (iy / double(n) * double(np) + 0.5);	if (levx >= mp) levx = mp-1;	if (levy >= np) levy = np-1;}		// Find maximum number of angles on selected levels, and the stepsize in angles for other levels// i.e. each angle on level levels(lx) maps to angfact(lx) levels on finest selected levelvoid GetAngleFactors(const CurveletData &cdata, const IntNumVec &levels, IntNumVec &angfact, int &maxang){	maxang = 0;  angfact.resize(levels.m());  for (int levx=0; levx<levels.m(); levx++) {    int lev = levels(levx);    if (cdata[lev].size() > maxang)      maxang = cdata[lev].size();  }  for (int levx=0; levx<levels.m(); levx++)    angfact(levx) = maxang / cdata[levels(levx)].size();	}	// datastructure for sorting, keeping original indicesstruct CoSortEntry {	int idx;	double val;};// order function, passed to std::sortbool cosortgt(const CoSortEntry &a, const CoSortEntry &b) {	return (a.val>b.val);}	// perform a running, periodic sum of first len entries// in vec, going sumofs steps in each directionvoid circularsum(DblNumVec &vec, int len, int sumofs) {	DblNumVec tmpvec(vec);	clear(vec);	for (int k=0; k<len; k++) {		for (int m=k-sumofs; m<=k+sumofs; m++) {			vec(k) += tmpvec((m+len) % len);		}	}}		// returns true if vec(idx) is a local maximum, regarding// first len entries of vec as a periodic vectorbool islocalmax(DblNumVec &vec, int len, int idx){	int lidx = (idx - 1 + len) % len;	int uidx = (idx + 1) % len;	return (vec(idx) >= vec(lidx) && vec(idx) >= vec(uidx));}// computes distance between indices idx1 and idx2,// if they are indices into a periodic array of size periodint periodicdistance(int idx1, int idx2, int period){	return min(abs(idx1-idx2), abs(abs(idx1 - idx2) - period));}	/*	ExtractMultipleDirFields()  Extracts major direcional fields from the levels (0-based indices) of curvelet data cdata. Extracts nrfields fields, each of size (m,n), into dirfields[0..nrfields-1][0..1](0..m-1,0..n-1) (the second index is x- and y-direction)  The function sums magnitudes of curvelet coefficients on selected levels, and at each point picks the direction with largest coefficient (and second, third,... largest if nrfields > 1)  Options: DirFieldOptions.CurveletSize				determines the number of grid points (on its own grid) away																		that a curvelet influences DirFieldOptions.CircSumOffset      determines number of directions away in both directions that 																		are included in a running sum over the directions DirFieldOptions.LocMaxGap					the required minimal distance in direction numbers between																		successive maxima saved in fields */	CurvUtilError ExtractMultipleDirFields(int m, int n, const CurveletData &cdata, const IntNumVec &levels, int nrfields, std::vector< std::vector<DblNumMat> > &dirfields, DirFieldOptions *a_opts){ 	// Check inputs	if (nrfields <= 0 || m<=0 || n<=0)		return CUError_BadParams;	for (int k=0; k<levels.m(); k++) {		if (levels(k) >= cdata.size())			return CUError_BadParams;	}			// Get parameters (or defaults)	DirFieldOptions *opts;	if (a_opts == NULL) {		opts = new DirFieldOptions;		opts->CircSumOffset = 1;		opts->CurveletSize = 1;		opts->LocMaxGap = 3;		opts->FilterType = CF_Abs;	}	else {		opts = a_opts;		if (opts->CurveletSize < 0 || opts->CircSumOffset < 0 || opts->LocMaxGap < 0)			return CUError_BadParams;	}		// initialize selected number of fields	dirfields.resize(nrfields);   	for (int k=0; k<nrfields; k++) {		dirfields[k].resize(2); 		dirfields[k][0].resize(m,n); 		dirfields[k][1].resize(m,n);	}		// find maximum number of angles, and the number of angles for each fine angle at each level  int maxang;	IntNumVec angfact;	GetAngleFactors(cdata, levels, angfact, maxang);	int mangd2 = max(maxang/2, 1); 		// At each pixel, add coefficient magnitudes and pick maximum	DblNumVec csum(maxang);  for (int xi=0; xi<m; xi++) {    for (int yi=0; yi<n; yi++) {      clear(csum);      for (int levx=0; levx<levels.m(); levx++) {        int lev = levels(levx);        int nang = max((int) cdata[lev].size()/2, 1);  // loop over half the angles, since other half has same magnitudes (assuming real-valued image)        for (int angx=0; angx<nang; angx++) {          int lx, ly;          MapCoordToLevel(cdata[lev][angx], xi, yi, m, n, lx, ly);          // Add neighboring curvelets          double cf = 0.0;					const CpxNumMat *mat = &(cdata[lev][angx]);					int lox = max(lx-opts->CurveletSize, 0);					int hix = min(lx+opts->CurveletSize, cdata[lev][angx].m()-1);					int loy = max(ly-opts->CurveletSize, 0);					int hiy = min(ly+opts->CurveletSize, cdata[lev][angx].n()-1);										switch (opts->FilterType) {						case CF_Abs:							for (int lxi=lox; lxi <= hix; lxi++)								for (int lyi=loy; lyi <= hiy; lyi++)									cf += abs((*mat)(lxi,lyi));							break;						case CF_Real:							for (int lxi=lox; lxi <= hix; lxi++)								for (int lyi=loy; lyi <= hiy; lyi++)									cf += abs(real((*mat)(lxi,lyi)));														break;						case CF_Imag:							for (int lxi=lox; lxi <= hix; lxi++)								for (int lyi=loy; lyi <= hiy; lyi++)									cf += abs(imag((*mat)(lxi,lyi)));														break;					  case CF_Sum:							for (int lxi=lox; lxi <= hix; lxi++)								for (int lyi=loy; lyi <= hiy; lyi++)									cf += abs(real((*mat)(lxi,lyi))) + abs(imag((*mat)(lxi,lyi)));														break;					}										// Add to all relevant (sub-)angles          for (int idx=angx*angfact(levx); idx<(angx+1)*angfact(levx); idx++)            csum(idx) += cf;        }      }			      // running (circular) sum, and find maximal directions			circularsum(csum, mangd2, min(opts->CircSumOffset, mangd2));			std::vector<CoSortEntry> svec;			svec.resize(mangd2);      for (int idx=0; idx<mangd2; idx++) {				svec[idx].val = csum(idx);				svec[idx].idx = idx;      }			sort(svec.begin(), svec.end(), cosortgt);      			// compute angles and field for maximal directions	    double cosa, sina;			int diridx = 0;			for (int idx=0; idx<nrfields; idx++) {				while (diridx < svec.size() && !islocalmax(csum, mangd2, svec[diridx].idx) ) {					// only accept second direction if far from previously selected directions and is local maximum					bool ok = false;					for (int fi=0; fi<idx && !ok; fi++) {						if (periodicdistance(svec[diridx].idx, svec[fi].idx, svec.size()) > opts->LocMaxGap)							ok = true;					}					if (ok) break;										diridx++;				}				if (diridx == svec.size())					break;								//compute angles and field for next largest direction				ComputeAngle(svec[diridx].idx, maxang, cosa, sina);				dirfields[idx][0](xi,yi) = svec[diridx].val * cosa;				dirfields[idx][1](xi,yi) = svec[diridx].val * sina;								diridx++;			}			    }  }  		if (a_opts == NULL) 		delete opts;	  return CUError_NoError;}		/* Sums the curvelet coefficient magnitudes on specified levels, over all directions, onto a grid of size (m,n) */CurvUtilError GetMagnitude(int m, int n, const CurveletData &cdata, const IntNumVec &levels, DblNumMat &mag, int crvlt_size){	// Check inputs	if (m<=0 || n<=0)		return CUError_BadParams;	for (int k=0; k<levels.m(); k++) {		if (levels(k) >= cdata.size())			return CUError_BadParams;	}	if (crvlt_size < 0)		return CUError_BadParams;		mag.resize(m,n);	// At each pixel, add coefficient magnitudes and pick maximum	double magsum;  for (int xi=0; xi<m; xi++) {    for (int yi=0; yi<n; yi++) {      magsum = 0.0;      for (int levx=0; levx<levels.m(); levx++) {        int lev = levels(levx);        int nang = max((int) cdata[lev].size()/2, 1);  // loop over half the angles, since other half has same magnitudes (assuming real-valued image)        for (int angx=0; angx<nang; angx++) {          int lx, ly;          MapCoordToLevel(cdata[lev][angx], xi, yi, m, n, lx, ly);          					// Add neighboring curvelets, to compute average          double avg = 0.0;					const CpxNumMat *mat = &(cdata[lev][angx]);					int nel = (1 + 2*crvlt_size) * (1 + 2*crvlt_size);					int nely = 1 + 2*crvlt_size;          for (int lxi=lx-crvlt_size; lxi <= lx+crvlt_size; lxi++) {						if (lxi < 0)							nel -= nely;						else if	(lxi >= cdata[lev][angx].m()) 							nel -=nely;						else {							for (int lyi=ly-crvlt_size; lyi <= ly+crvlt_size; lyi++) {								if (lyi < 0)									nel -= 1;								else if (lyi >= cdata[lev][angx].n())									nel -= 1;								else									avg += abs((*mat)(lxi,lyi));          							}						}					}					magsum += avg / nel;        }      }						mag(xi,yi) = 2.0 * magsum;		}	}  return CUError_NoError;}			/*	 Sums the _mirror-extended_ curvelet coefficient magnitudes on specified levels, over all directions, onto a grid of size (m,n)	 */	CurvUtilError GetMagnitudeME(int m, int n, const CurveletData &cdata, const IntNumVec &levels, DblNumMat &mag, int crvlt_size)	{		// Check inputs		if (m<=0 || n<=0)			return CUError_BadParams;		for (int k=0; k<levels.m(); k++) {			if (levels(k) >= cdata.size())				return CUError_BadParams;		}		if (crvlt_size < 0)			return CUError_BadParams;				mag.resize(m,n);				// At each pixel, add coefficient magnitudes and pick maximum		double magsum;		for (int xi=0; xi<m; xi++) {			for (int yi=0; yi<n; yi++) {				magsum = 0.0;				for (int levx=0; levx<levels.m(); levx++) {					int lev = levels(levx);					int nang = cdata[lev].size();					for (int angx=0; angx<nang; angx++) {						int lx, ly;						int mp = (int)(cdata[lev][angx].m() / 2) + 1; // actual sizes for mirror-extended levels						int np = (int)(cdata[lev][angx].n() / 2) + 1;						MapCoordToLevelME(mp, np, xi, yi, m, n, lx, ly);												// Add neighboring curvelets, to compute average						double avg = 0.0;						const CpxNumMat *mat = &(cdata[lev][angx]);						int nel = (1 + 2*crvlt_size) * (1 + 2*crvlt_size);						int nely = 1 + 2*crvlt_size;						for (int lxi=lx-crvlt_size; lxi <= lx+crvlt_size; lxi++) {							if (lxi < 0)								nel -= nely;							else if	(lxi >= mp) 								nel -=nely;							else {								for (int lyi=ly-crvlt_size; lyi <= ly+crvlt_size; lyi++) {									if (lyi < 0)										nel -= 1;									else if (lyi >= np)										nel -= 1;									else {										avg += abs((*mat)(lxi,lyi));          										avg += abs((*mat)(lxi, ((*mat).n() - lyi) % (*mat).n()));  // add direction pi - theta									}								}							}						}						magsum += avg / nel;					}				}								mag(xi,yi) = 2.0 * magsum;			}		}				return CUError_NoError;	}														 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -