CreateHistogram.cpp 3.37 KB
#include "GlobalValues.h"
#include <QImage>

struct HistogramStruct{
	unsigned int* hist2D;
	int nBins;

	float bounds[4];

	HistogramStruct(float minX, float minY, float maxX, float maxY, int bins){

		//allocate memory for the histogram
		hist2D = (unsigned int*)malloc(sizeof(unsigned int)*bins*bins);
		memset(hist2D, 0, sizeof(unsigned int)*bins*bins);

		bounds[0] = minX; 
		bounds[1] = maxX; 
		bounds[2] = minY; 
		bounds[3] = maxY;

		nBins = bins;
	}

	bool checkBounds(float x, float y){
		if(x < bounds[0] || x > bounds[1] || y < bounds[2] || y > bounds[3])
			return false;
		else return true;
	}

	void increment(float x, float y){
		//increment the counter at the appropriate histogram location

		//is the location within the bounds of the histogram
		if(checkBounds(x, y)){
			
			int binX = (x - bounds[0])/(bounds[1] - bounds[0]) * nBins;
			int binY = (y - bounds[2])/(bounds[3] - bounds[2]) * nBins;

			hist2D[binY * nBins + binX]++;
		}

	}

	void saveImage(string fileName){

		//create an output image
		QImage outImage(nBins, nBins, QImage::Format_RGB888);

		//find the maximum value in the histogram
		unsigned int histMax = 0;
		for(int i=0; i<nBins*nBins; i++)
			if(hist2D[i] > histMax)
				histMax = hist2D[i];
		cout<<"HistMax: "<<histMax;
		//convert all histogram values into colors and save
		int x, y;
		unsigned char intensity;
		QRgb color;
		for(x=0; x<nBins; x++)
			for(y=0; y<nBins; y++){
				intensity = log((double)hist2D[y*nBins + x]) / log((double)histMax) * 255;
				//cout<<(int)intensity<<endl;
				color = qRgb(intensity, intensity, intensity);
				outImage.setPixel(x, y, color);
			}

		//save the image file
		outImage.save(fileName.c_str());
	}





};

void CreateHistogram(int bins, float& minU, float& maxU, float& minV, float& maxV)
{
	VolumeData vol = VolumeList[0];
	int Sx = vol.Dim.x;
	int Sy = vol.Dim.y;
	int Sz = vol.Dim.z;
	int C = 3;
	
	//create the histogram
	HistogramStruct histogram(minU, minV, maxU, maxV, bins);


	//get the texture data from the GPU
	//allocate memory for the volume
	unsigned char* cpuVolume;
	int size = sizeof(unsigned char) * C * Sx * Sy * Sz;
	cpuVolume = (unsigned char*)malloc(size);
	memset(cpuVolume, 0, size);

	//copy the texture from the GPU
	vol.Texture.BeginTexture();
	glGetTexImage(GL_TEXTURE_3D, 0, GL_RGB, GL_UNSIGNED_BYTE, cpuVolume);

	int x, y, z, c;
	float maxVal = 0;
	float u, v;
	float xn, xp, yn, yp, zn, zp;
	float dx, dy, dz;
	minU = 99999;
	maxU = -99999;
	minV = 99999;
	maxV = -99999;
	for(x=1; x<Sx-1; x++)
		for(y=1; y<Sy-1; y++)
			for(z=1; z<Sz-1; z++)
				for(c=0; c<1; c++)
				{
					//compute the gradient magnitude
					u = cpuVolume[z*Sx*Sy*C + y*Sx*C + x*C + c];

					xn = cpuVolume[z*Sx*Sy*C + y*Sx*C + (x-1)*C + c];
					xp = cpuVolume[z*Sx*Sy*C + y*Sx*C + (x+1)*C + c];
					yn = cpuVolume[z*Sx*Sy*C + (y-1)*Sx*C + x*C + c];
					yp = cpuVolume[z*Sx*Sy*C + (y+1)*Sx*C + x*C + c];
					zn = cpuVolume[(z-1)*Sx*Sy*C + y*Sx*C + x*C + c];
					zp = cpuVolume[(z+1)*Sx*Sy*C + y*Sx*C + x*C + c];

					dx = (xp - xn)/2.0;
					dy = (yp - yn)/2.0;
					dz = (zp - zn)/2.0;

					v = sqrt(dx*dx + dy*dy + dz*dz);
					histogram.increment(u, v);

					if(v < minV)
						minV = v;
					if(v > maxV)
						maxV = v;
					if(u < minU)
						minU = u;
					if(u > maxU)
						maxU = u;


				}

	free(cpuVolume);
	cout<<"Data Value: "<<maxVal<<endl;

	//save the histogram image
	histogram.saveImage("testHistogram.bmp");


}