Dicom Toolkit (DCMTK) - How to get Window Centre and Width - c++

I am currently using DCMTK in C++. I am quite new to this toolkit but, as I understand it, I should be able to read the window centre and width for normalisation purposes.
I have a DicomImage DCM_image object with my Dicom data.
I read the values to an opencv Mat object. However, I now would like to normalise them.
The following shows how I am reading and transferring the Data to an opencv Mat.
DicomImage DCM_image("test.dcm");
uchar *pixelData = (uchar *)(DCM_image.getOutputData(8));
cv::Mat image(int(DCM_image.getHeight()), int(DCM_image.getWidth()), CV_8U, pixelData);
Any help is appreciated. Thanks

Reading window center and width is not difficult, however you need to use a different constructor and pass a DcmDataset to the image.
DcmFileFormat file;
file.loadFile("test.dcm");
DcmDataset* dataset = file.getDataset()
DicomImage image(dataset);
double windowCenter, windowWidth;
dataset->findAndGetFloat64(DcmTagKey(0x0010, 0x1050), windowCenter);
dataset->findAndGetFloat64(DcmTagKey(0x0010, 0x1051), windowWidth);
But actually I do not think it is a good idea to apply the windowing to the image upon loading. Windowing is something which should be adjustable by the user. The attributes Window Center and Window Width allow multiple values which can be applied to adjust the window to the grayscale range of interest ("VOI", Values of Interest).
If you really just want to create a windowed image, you can use your code to construct the image from the file contents and use one of the createXXXImage methods that the DicomImage provides.
HTH

Related

How to use CImg functions with pixel data?

I am using Visual Studio and looking to find a useful image processing library that will take care of basic image processing functions such as rotation so that I don't have to keep coding them manually. I came across CImg and it supports this, as well as many other useful functions, along with interpolation.
However, all the examples I've seen show CImg being used by loading and using full images. I want to work with pixel data. So my loops are the typical:
for (x=0;x<width; x++)
for (y=0;y<height; y++)
I want to perform bilinear or bicubic rotation in this instance and I see CImg supports this. It provides a rotate() and get_rotate function, among others.
I can't find any examples online that show how to use this with pixel data. Ideally, I could simply pass it the pixel color, x, y, and interpolation method, and have it return the result.
Could anyone provide any helpful suggestions? If CImg is not the right library for this type of this, could anyone recommend a simple, light-weight, easy-to-use one?
Thank you!
You can copy pixel data to CImg class using iterators, and copy it back when you are done.
std::vector<uint8_t> pixels_src, pixels_dst;
size_t width, height, n_colors;
// Copy from pixel data
cimg_library::CImg<uint8_t> image(width, height, 1, n_colors);
std::copy(pixels_src.begin(), pixels_src.end(), image.begin());
// Do image processing
// Copy to pixel data
pixels_dst.resize(width * height * n_colors);
std::copy(image.begin(), image.end(), pixels_dst.begin());

EasyAR access Camera Frames as OpenCV Mat

I'm using EasyAR to develop an app on android using C++ & I'm trying to use opencv with it, what I'm trying to achieve is: get the easyAR frames that it got from the camera as Mat and do some processing using opencv then return the frames to view.
Why do all that? simply I'm only after the EasyAR camera frame crossplatform access (I think it's really fast, I just built the sample HelloAR)
in the Sample HelloAR, there is a line
auto frame = streamer->peek();
is there is a way to convert this to be used in openCV ?
is there is an alternative way to access camera frames from c++ in both IOS & Android (Min API 16)?
your help is appreciated, thank you.
here is the samples link, I'm using HelloAR
http://s3-us-west-2.amazonaws.com/easyar/sdk/EasyAR_SDK_2.0.0_Basic_Samples_Android_2017-05-29.tar.xz
Okay, I managed to get a solution for this
so simply frame (class Frame in EasyAR) contains a vector of images (probably different images for the same frame), accessing that vector returns an Image object with a method called data (a byte array) and that can be used to initialize a Mat in opencv
here is the code to clarify for anyone searching for the same
unsigned char* imageBuffer = static_cast<unsigned char*>(frame->images().at(0)->data());
int height = frame->images()[0]->height(); // height of the image
int width = frame->images()[0]->width(); // width of image
// Obtained Frame is YUV21 by default, so convert that to RGBA
cv::Mat _yuv(height+height/2, width, CV_8UC1, imageBuffer);
cv::cvtColor(_yuv, _yuv, CV_YUV2RGBA_NV21);

Correct display of DICOM images ITK-VTK (images too dark)

I read dicom images with ITK using itk::ImageSeriesReader and itk::GDCMImageIO after reading i flip the images with itk::FlipImageFilter (to get right orientation of the images) and convert the itkImageData to vtkImageData using itk::ImageToVTKImageFilter. I visualization images with VTK using vtkResliceImageViewer in QVTKWidget2.
I set:
(vtkResliceImageViewer)m_imageViewer[i]->SetColorWindow(windowWidthTAGvalue[0028|1051]);
(vtkResliceImageViewer)m_imageViewer[i]->SetColorLevel(windowCenterTAGvalue[0028|1050]);
and i set following blac&white LookUpTable:
vtkLookupTable* lutbw = vtkLookupTable::New();
lutbw->SetTableRange(0,1000);
lutbw->SetSaturationRange(0,0);
lutbw->SetHueRange(0,0);
lutbw->SetValueRange(0,1);
lutbw->Build();
And images shown into my software compared with the same images shown into other software are much darker, i can not get the same effect as other DICOM viewers
My software images are right other software image is left also when i use some other LookUpTable in this example Flow i can not get the same effect (2nd row images) my image on right is much darker then other.
What i am missing why my images are darker what can i do? i was research a lot into dicom and ikt/vtk can not find good solution any help is appreciate.
Please check the values for Rescale Slope (0028,1053) and Rescale Intercept(0028,1052) and apply the Modality LUT transformation before applying the Window level.
Your dataset may have VOI LUT Function (0028,1056) attribute value of "SIGMOID" instead of "LINEAR".
I extracted the image data from one of your DICOM file (brain_009.dcm) and looked at the histogram of the image data. It looks like, the minimum value stored in the image is 0 and maximum value is 960 regardless of interpreting the data is signed or unsigned. Also, the Window Width (0028:1051) has an invalid value of “0” and you cannot use that for displaying the image.
So your default display could set the Window Width to 960 and Window Center to half the window width plus the minimum value.

Taking a screenshot of a particular area

Looking for a way for taking a screenshot of a particular area on the screen in C++. (So not the whole screen) Then it should save it as .png .jpg whatever to use it with another function afterwards.
Also, I am going to use it, somehow, with openCV. Thought i'd mention that, maybe it's a helpful detail.
OpenCV cannot take screenshots from your computer directly. You will need a different framework/method to do this. #Ben is correct, this link would be worth investigating.
Once you have read this image in, you will need to store it into a cv:Mat so that you are able to perform OpenCV operations on it.
In order to crop an image in OpenCV the following code snippet would help.
CVMat * imagesource;
// Transform it into the C++ cv::Mat format
cv::Mat image(imagesource);
// Setup a rectangle to define your region of interest
cv::Rect myROI(10, 10, 100, 100);
// Crop the full image to that image contained by the rectangle myROI
// Note that this doesn't copy the data
cv::Mat croppedImage = image(myROI);

converting images between opencv and wxwidgets

I have got a big problem. After searching through the internet, I didn't find a good solution. I read in images from files via opencv (2.3) and manipulate them. Afterwards I want to present the result in my application written in wxwidgets (2.9.3). The main problem is, that my images are grayscale and so I just have got a single data pointer, but wxwidgets just use RGB. just a small example:
cv::imread(filename,CV_LOAD_IMAGE_GRAYSCALE).convertTo(pictureMatrix,CV_32F,(float)(1/2.0f),0);
// here are some more floating point calculations
cv::Mat output;
pictureMatrix.convertTo(output,CV_8U);
wxImage test(output.rows, output.cols, output.data, true);
wxInitAllImageHandlers();
// saving the picture is just for testing, if it works
test.SaveFile("test.png", wxBITMAP_TYPE_PNG);
All you need to to do is to convert from grayscale to RGB (actually, to BGR, if you're on Windows).
cv::Mat grayOutput, rgbOutput;
pictureMatrix.convertTo(grayOutput,CV_8U);
cvtColor(grayOutput, rgbOutput, CV_GRAY2BGR); // note the BGR here.
//If on Linux, set as RGB
wxImage test(rgbOutput.cols, rgbOutput.rows, rgbOutput.data, true);
...
You can always set R=G=B=<your grayscale value> for every pixel. If the format of the image pixels doesn't match up, you can allocate a new array in the format expected by wxImage and fill it with those RGB values.
You can also take a look at this link. It looks similar to what you need to do.