Converting DICOM images into nrrd images preserving pixel spacing - dicom

I am trying to convert a series of MRI DICOM images (.dcm) into .nnrd format. I found this guide for doing it in 3D slicer and I managed to do it. The problem is that the new nrrd image that is created has lost the pixel spacing of the original DICOM image.
In the additional settings, while converting the image, I also unticked the "Compress" box but the problem is still there. For instance, checking the two images (original .dcm and new .nrrd) in Imagej I get this:
The two images (nrrd on the left and dcm on the right) where I highlighted the old and the new pixel spacing
Anyone knows how to solve this? Any other alternative (that preserves the pixel spacing) is well accepted.
Thanks a lot in advance,
Tommaso

Your DICOM file is corrupted. Some mandatory tags are missing (e.g. 20,37, Image Orientation (Patient)). Therefore Slicer cannot properly compute the spacing. It even shows you in "Dicom Browser" window the following warning (after clicking Examine button): "Reference image in series does not contain geometry information. Please use caution".
If you cannot fix original images, you can apply manually all required spacing elements. Either do it in Slicer before exporting (Module Volumes -> Volume Information), or you can fix nrrd files themselves. Open them in your favorite text editor:
NRRD0004
# Complete NRRD file format specification at:
# http://teem.sourceforge.net/nrrd/format.html
type: short
dimension: 3
space: left-posterior-superior
sizes: 512 512 1
space directions: (1,0,0) (0,1,0) (0,0,1)
kinds: domain domain domain
endian: little
encoding: gzip
space origin: (0,0,0)
You have to update this line:
space directions: (0.507812,0,0) (0,0.507812,0) (0,0,4)
The true spacing are under tags 0028,0030 (X and Y) and 0018,0050 (Z).

Related

Automatic rotation and crop of images based on detetction reference marks

I have developed a framework in R to automatically measure vegetation structure variables from whiteboard photos taken on grasslands for ecological related studies. Until now we have preprocessed the images by hand, however now we need to automatise the rotation and cropping of the images.
The idea is the following: Use reference marks on the whiteboard, and detect these markings to rotate and crop the original photographs. I need help to detect the reference markings. After knowing the position of reference markings (centroids) we can calculate the coordinates/pixels where to crops the image. In the end, we want to get a picture like that.
We can use some special colour for the markings, but these can be obstructed by the vegetation. The bottom of the whiteboard is always obstructed, the cropped part (without the reference markings) should be 25×100 cm.
Possibly edge detection can be a solution. I'm familiar with only with R programming.

filter image with opencv

I have an image which I would like to extract the number but in a dynamic way (I don't want to specify a roi because image may vary) so I have to filter it. I tried to detect the horizontal line(to crop the image) but it failed. I would like to detect high density zones in the binary image (the face and the top of the image)
ps:my problem isn't how to extract numbers but to specify the roi
and all the images have the same format
any help would be appreciated(even without code just the big lines)
thanks
the image
I would start form detecting frame of the whole document.
If you google: rectangle detection opencv, you will find lots of examples.
In second stage i would apply inRange to filter purple line and detect it with HoughLines.
This should be enough to calculate ROI.

Air in synthetic DICOM

I'm generating a synthetic DICOM image with the Insight Toolkit (using itk::GDCMImageIO) and I've found two problems:
VolView fails loading my DICOM (with the message: Sorry, the file cannot be read). ITK-Snap opens and shows it OK.
I'm trying to use this image in a Stryker surgical navigator. The problem is that the image is loaded ok, but then the padding pixels are shown in a certain gray level, showing a box (actually the bounding box) of the image. If I load non synthetic DICOMs this doesn't happen.
This is what gdcminfo is showing:
MediaStorage is 1.2.840.10008.5.1.4.1.1.7 [Secondary Capture Image Storage]
TransferSyntax is 1.2.840.10008.1.2.1 [Explicit VR Little Endian]
NumberOfDimensions: 2
Dimensions: (33,159,1)
Origin: (0,0,0)
Spacing: (1,1,1)
DirectionCosines: (1,0,0,0,1,0)
Rescale Intercept/Slope: (0,1)
SamplesPerPixel :1
BitsAllocated :16
BitsStored :16
HighBit :15
PixelRepresentation:0
ScalarType found :UINT16
PhotometricInterpretation: MONOCHROME2
PlanarConfiguration: 0
TransferSyntax: 1.2.840.10008.1.2.1
Orientation Label: AXIAL
I'm using unsigned short as pixel type in itk::Image object and I'm setting all the padding pixels to 0 (zero), as is suggested by the DICOM standard for unsigned scalar images. gdcminfo does not show it, but I'm also setting the Pixel Padding (0028,0120) field to zero.
I would really appreciate any hint about this problem.
Thanks in advance,
Federico
After a lot of experimentation, I'll answer my own question. I've found that some DICOM readers directly assume that you're using the Hounsfield scale if the type of the DICOM files is CT. In this case you have to use short as pixel type and use -1024 for air (less than -1000 is air in Hounsfield scale), and it will render the image ok. These readers I've been experimenting with don't use the Pixel Padding field nor the Rescale Intercept/Slope. But If you use ITK-Snap/VolView/3DSlicer you won't have any problem if you specify those fields.
Dicom is a VERY tricky file format. You will need to carefully read and understand the conventions for the visualization platform, the storage platform, and the type of medical image you are trying to synthesize.
This is very likely NOT an error with the toolkit, but an error with what is being defined in the file format itself.

Matlab Bwareaopen equivalent function in OpenCV

I'm trying to find similar or equivalent function of Matlabs "Bwareaopen" function in OpenCV?
In MatLab Bwareaopen(image,P) removes from a binary image all connected components (objects) that have fewer than P pixels.
In my 1 channel image I want to simply remove small regions that are not part of bigger ones? Is there any trivial way to solve this?
Take a look at the cvBlobsLib, it has functions to do what you want. In fact, the code example on the front page of that link does exactly what you want, I think.
Essentially, you can use CBlobResult to perform connected-component labeling on your binary image, and then call Filter to exclude blobs according to your criteria.
There is not such a function, but you can
1) find contours
2) Find contours area
3) filter all external contours with area less then threshhold
4) Create new black image
5) Draw left contours on it
6) Mask it with a original image
I had the same problem and came up with a function that uses connectedComponentsWithStats():
def bwareaopen(img, min_size, connectivity=8):
"""Remove small objects from binary image (approximation of
bwareaopen in Matlab for 2D images).
Args:
img: a binary image (dtype=uint8) to remove small objects from
min_size: minimum size (in pixels) for an object to remain in the image
connectivity: Pixel connectivity; either 4 (connected via edges) or 8 (connected via edges and corners).
Returns:
the binary image with small objects removed
"""
# Find all connected components (called here "labels")
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(
img, connectivity=connectivity)
# check size of all connected components (area in pixels)
for i in range(num_labels):
label_size = stats[i, cv2.CC_STAT_AREA]
# remove connected components smaller than min_size
if label_size < min_size:
img[labels == i] = 0
return img
For clarification regarding connectedComponentsWithStats(), see:
How to remove small connected objects using OpenCV
https://www.programcreek.com/python/example/89340/cv2.connectedComponentsWithStats
https://python.hotexamples.com/de/examples/cv2/-/connectedComponentsWithStats/python-connectedcomponentswithstats-function-examples.html
The closest OpenCV solution to your question is the morphological closing or opening.
Say you have white regions in your image that you need to remove. You can use morphological opening. Opening is erosion + dilation, in that order. Erosion is when the white regions in your image are shrunk. Dilation is (the opposite) where white regions in your image are enlarged. When you perform an opening operation, your small white region is eroded until it vanishes. Larger white features will not vanish but will be eroded from the boundary. The subsequent dilation step restores their original size. However, since the small element(s) vanished during the erosion step, they will not appear in the final image after dilation.
For example consider this image where we want to remove the small white regions but retain the 3 large white ellipses. Running the following code removes the white regions and displays the clean image
import cv2
im = cv2.imread('sample.png')
clean = cv2.morphologyEx(im, cv2.MORPH_OPEN, np.ones((10, 10)))
cv2.imshwo("Clean image", clean)
The clean image output would be like this.
The command above uses a square block of size 10 as the kernel. You can modify this to suit your requirement. You can even generate a more advanced kernel using the function getStructuringElement().
Note that if your image is inverted, i.e., with black noise on a white background, you simply need to use the morphological closing operation (cv2.MORPH_CLOSE method) instead of opening. This reverses the order of operation - first the image is eroded and then dilated.

how to ascribe (x,y) coordinates to text?

Greetings, Does anyone have a suggestion on how I can either, a) map text on a grid (what i imagine is a Cartesian system where each character has a (x,y) coordinate, or b) if a grid is not possible, somehow measure text for i)location of a character, difference (delta) between one text location and another x2-x1 horizontal or difference between one text location and another vertically y2-y1? I am on a PC and would require a suggested programming method or program suggestion (is there a PC based text program with this feature that anyone knows of)? Thanks so much in advance,
c~tea
In the absence of a defined programming language, I suggest PostScript.
PostScript is a page description language which has the feature you ask. It is understood by many printers directly and for the rest there are interpreters. It is also the basis of the PDF file format. On the wikipedia page is an example that demonstrates the use of the coordinate system:
%!PS
/Courier % name the desired font
20 selectfont % choose the size in points and establish
% the font as the current one
72 500 moveto % position the current point at
% coordinates 72, 500 (the origin is at the
% lower-left corner of the page)
(Hello world!) show % stroke the text in parentheses
showpage % print all on the page
The coordinate system has its origin in the lower left corner and is measured in points (1/72 inch)

Resources