How to obtain the Hu value of DICOM in ITK in C++ programming

I can get the pixel value by converteing DICOM to mat through OpenCVImageBridge, but I would have some trouble when adjusting the window width and window center. I don’t know whether you have a method that we can obtain the Hu value of the DICOM file in ITK directly.Thank you!

ReaderType::Pointer reader = ReaderType::New();
FilterType::Pointer filter = FilterType::New();
InputImageType::Pointer image = reader->GetOutput();
image->Update();
filter->SetWindowMinimum(50);
filter->SetWindowMaximum(100);
filter->SetOutputMinimum(255);
filter->SetOutputMaximum(0);
filter->SetInput(image);
filter->Update();
m_img = itk::OpenCVImageBridge::ITKImageToCVMat< OutputImageType >(filter->GetOutput());

If you read the CT image or DICOM series the normal way, ITK image’s pixels directly represent Hounsfield Units. Something like this: firstPixelHU = image->GetPixel({0,0,0});. Once you apply some intensity transform (such as W/L), the pixel intensities will have some other units.

1 Like

Thanks for replying. we need to adjust the window width and window center to display DICOM within the specified Hu value range, but what I got with GetPixel() is still pixel value, and the result is the same as the result obtained by OpencvImageBridge.What we need to do is achieving Window width and center adjustment based on Hu value , should we only use the formula(U = m*SV + b) that maps pixel values to Hu values? The slope m and intercept b can be obtained in a certain way, such as the following code, and in general, the slope is 1, the intercept is -1024, Is the Hu value in this way accurate?

ImageIOType::Pointer gdcmIO = ImageIOType::New();
double intercept =	gdcmIO->GetRescaleIntercept();
double slope = gdcmIO->GetRescaleSlope();
Mat m1 = Mat_<quint16>(512, 512);
for (int i = 0; i < 512; i++)
{
	pixelIndex[0] = i;
	for (int j = 0; j < 512; j++)
	{
		pixelIndex[1] = j;
		InputImageType::PixelType pixelValue = reader->GetOutput()->GetPixel(pixelIndex);
		m1.at<quint16>(i, j) = pixelValue;
	}
}
char filename[] = "D://raw.mat";
std::ofstream fout(filename);
if (!fout) {

	return;
}

for (int i = 0; i < m1.rows; i++)
{
	for (int j = 0; j < m1.cols; j++)
	{
		fout << m1.at<quint16>(i, j) << "\t";
	}
	fout << std::endl;
}
fout.close();

Thank you for your answer. I know what my problem is. The Hu value obtained by GetPixel is indeed the Hu value. Since I set the image type to unsigned short, many of the data values obtained by traversing DICOM are abnormally large, like 64512. Thus, I thought that what I got was still the pixel value, but when I set the DICOM type to signed short, the value became -1024, and the Hu-based window width and window center can be adjusted by using the filter. Thanks again for your reply.

typedef signed short InputPixelType;
2 Likes