-
-
Notifications
You must be signed in to change notification settings - Fork 471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide PixelData decompression (JPEG, RLE, MPEG, etc) #18
Comments
From darcymason@gmail.com on October 11, 2008 17:17:50 More info: Most important ones to add first will be the ones that have not been First, ultra-short first-line defaults list, then more details follow:
Full details
Summary: Provide PixelData decompression (JPEG, RLE, MPEG, etc) |
From darcymason@gmail.com on October 15, 2008 05:57:03 Tried to find JPEG libraries to decode pixel data (tried using PIL and libjpeg Status: WontFix |
From darcymason@gmail.com on May 24, 2009 19:26:28 Reopening this issue. Medical image format FAQ has good info on libraries available. http://www.dclunie.com/medical-image-faq/html/part7.html#SourceJPEG PVRG looks good (note link to PDF documentation in section linked to above, else is Status: New |
From darcymason@gmail.com on May 25, 2009 20:44:57 Found pure python Huffman encoding/decoding (part of JPEG process) at http://pypi.python.org/pypi/huffman%20encoder%20%26%20decoder/0.3 . Has detailed |
From darcymason@gmail.com on May 25, 2009 21:08:05 More research: code for DCT (also needed for JPEG I believe): http://projects.scipy.org/scipy/ticket/733 -- proposed code for DCT using numpy fft http://whiter4bbit.blogspot.com/2008/11/dct-python-implementation-warning-code.html -
|
From NikitaTh...@gmail.com on January 05, 2010 07:46:54 Just a suggestion -- libjpeg is widely installed in Unix/Linux land and is available The same goes for PNG/libpng. |
From darcymason@gmail.com on January 05, 2010 16:28:23
I'd be happy to use it if it would work. I did look at this a long time ago (see |
From mike...@gmail.com on September 12, 2010 19:02:59 For JPEG, how about the Jasper library? I believe that OsiriX (Mac OS X DICOM viewer) uses it, and it's licensed under the MIT license. http://www.ece.uvic.ca/~mdadams/jasper/ |
From mike...@gmail.com on September 12, 2010 19:25:07 OsiriX also uses OpenJPEG, which is BSD licensed. Not sure why the need for both. http://www.openjpeg.org/ |
From neuros...@gmail.com on March 06, 2014 14:54:27 Any updates on this? I'm currently using pydicom mixed with GDCM, looking to help incorporate a purely python way to decompress JPG images within DICOM. |
From darcymason@gmail.com on March 07, 2014 15:36:26 No sorry, no update. I wonder, though ... IIRC I looked at GDCM once (or was it dcmtk?) and i remember seeing that they handled compressed images by calling a command line routine to convert to non-compressed in a temporary file, and then load that. It would be fairly easy to add a "hook" in pydicom to call something like dcmtk to convert the file and then load it in. Would that be helpful? And ... I'd be interested to know which specific compressed files (transfer syntax) people are encountering in the real world. |
From ezaro...@gmail.com on March 07, 2014 15:39:56 I've used dcmtk in conjunction with pydicom. I frequently run into JPEG-LS and JPEG2000 variants. A downside to dmctk is that there is no free module for encoding/decoding JPEG2000. That being said, OsiriX ( https://github.com/pixmeo/osirix ) uses dcmtk and they have their own way of handling JPEG2000 which you can look at in the source. |
From darcymason@gmail.com on March 07, 2014 16:32:05 I'll try to have a look at OsiriX and see if there might be a way to build a C extension. If so, I could see that as a separate pydicom library (to keep the core pydicom pure python). Just by way of explanation for anyone stumbling on this thread...my take on this issue (as in issue 16 ) is that it seems like a large amount of work to try to add decompression into pydicom (or related package), which has always had the philosophy of being light and very easy to install. This is why I've avoided it and recommend people pre-process compressed files with dcmtk or others. To me, if the pydicom user has to go through the work of a complex installation with multiple dependencies, compiling C extensions, etc., then they might as well do so with one of the existing packages that already have that all worked out. If there were a way to provide decompression in pure python or with minimal C, then I think that would be more in the spirit of pydicom. My hope was to perhaps handle a few of the most common compression formats that way. I welcome anyone's thoughts on this subject. Having said all that, on a more positive note: the various comments in this issue do seem to be converging on OsiriX as a good source to model, if anyone had the ambition to try to take this on. Realistically, it's not something I can see getting around to anytime soon. |
From neuros...@gmail.com on March 09, 2014 07:48:53 Darcy, I'm using pydicom and GDCM for my prototype webservice dcmdb ( http://dcmdb.org ), so you can see I'm attempting to capture as many transfer syntaxes as possible ( http://dcmdb.org/main/transfer_syntax ). Using GDCM I have not have a transfer syntax issue as of yet. I really want a pure python way to get images out of DICOM files, I know Ruby DICOM ( http://dicom.rubyforge.org/ ) was able to accomplish that goal, so I'm going to start really investigating solutions to this problem ... if you have any documentation that would be helpful on this journey, please let me know. |
From mj...@nephosity.com on March 09, 2014 11:50:00 Eric, I'm a bit confused. you're already using GDCM. are you using its Python extension? if so, what is the reason for a "pure Python" implementation? in any case, OpenJPEG is really the best library out there, so you would need to do one of two things
HTH |
From darcymason@gmail.com on March 09, 2014 14:57:30 First, thank you to everyone for the discussion. It's good to get these ideas out there and see what we can come up with. @neurosnap: I found this comment on ruby dicom: https://groups.google.com/forum/#!topic/comp.protocols.dicom/NMdlfkzpaII in which the author says it relies on ImageMagick but it only handles a subset of the JPEG variants. That comment is almost a year old though, so perhaps it has changed? @mjpan: do you know any more about how the conversion to JS? It mentions using Emscripten, which I see is an LLVM to JS compiler. Is there a similar package to convert for python? And is there any hope of any of this working at an acceptable speed? To all: I've toyed with some ideas on pure python implementations, but if you start reading through libjpeg (libijg)code (which dcmtk's jpeg is based on) it is incredibly intertwined. It is so heavily optimized for speed (and memory use) that it is very difficult to follow or translate to another language. It has been around a long time, so it comes from an era where speed and memory were very important. Plus (IIRC) there were many workarounds for known poor implementations and such. It would be very hard to replicate this in other code; I think that is why no one (very few?) have succeeded in doing so. Everywhere I looked, I just saw the same libijg code copied and pasted and minimally modified. In terms of difficulty, Jpeg2000 may be a different situation; I haven't really looked into those codes. |
From neuros...@gmail.com on March 09, 2014 18:06:30 Thanks for the response, ideally I would like a better mechanism to deploy my server, something that would be easier to install besides GDCM, but I may be out of luck. I'll investigate openJPEG. |
From mj...@nephosity.com on March 10, 2014 13:48:20 Darcy, I'm sure that compiling OpenJPEG to pure Python can be done via LLVM, but I don't think anyone has had the motivation to do so, as it's possible to run C/C++ code in Python via an extension, as opposed to Javascript, which requires JS code to run in the browser. for anyone looking for Python -> OpenJPEG, I'd suggest checking out Glymur. https://glymur.readthedocs.org/en/latest/introduction.html although I can't imagine it being any easier than building the GDCM Python extension-- CMake really makes things easy, especially as you go across operation systems |
From martin.s...@gmail.com on March 17, 2014 17:40:30 I just had a go at using Glymur to try to get pixel data out of a 1.2.840.10008.1.2.4.91: JPEG 2000 Image Compression'. I suspect that I am going about the problems that I have encountered incorrectly. However I am posting this comment here in case anyone can point out my mistake, or it is of help to anyone else investigating Glymur. From the initial error messages it seemed that there was no header data. This seems consistent with, Part 5 of the DICOM standard section A.4.4 (p77) http://medical.nema.org/Dicom/2011/11_05pu.pdf staes: "The optional JP2 file format header shall NOT be included. " So far I have found Annex I of ISO15444-1 http://www.jpeg.org/public/15444-1annexi.pdf . Hoping DICOM pixel data contained a Contiguous Codestream, I attempted to create the relevant headings such that it could be simply read by the Glymur command for opening JPEG2000 files. import dicom f.write(struct.pack(">I4s4s", 12, "jP ", "\r\n\x87\n"))
|
From agrothberg on July 02, 2014 16:31:22 If the image is showing a TransferSyntaxUID=1.2.840.10008.1.2.4.50 ( http://www.dicomlibrary.com/dicom/transfer-syntax/ ) is there any way I can get access to the raw data and just hand it to PIL to decode? A naive call to: dicom.contrib.pydicom_PIL.show_PIL(dataset) did not work. |
Right now I am solving the problem by shelling out to def load_dicom(input_file, force_decode=False, no_decompress=False):
assert not (force_decode and no_decompress)
import dicom
data = dicom.read_file(input_file)
if no_decompress or (not force_decode
and data is not None
and data.file_meta.TransferSyntaxUID in dicom.dataset.NotCompressedPixelTransferSyntaxes):
return data
with tempfile.NamedTemporaryFile(suffix=".dcm") as f:
# +cl --conv-lossy convert YCbCr to RGB if lossy JPEG
# +cn --conv-never never convert color space
# +px --color-by-pixel always store color-by-pixel
subprocess.check_output(['dcmdjpeg', '+cl', '+px', input_file, f.name])
data = dicom.read_file(f.name)
return data |
If you have the python wrappers installed for GDCM, you can use On Wed Jan 14 2015 at 12:39:29 AM Alex Rothberg notifications@github.com
|
Here is some relevant discussion on what can and cannot be done from Python with |
I have a few comments on this. 2.) You could also use my dcm2niix (also on Github). This is written in C, but is much less complicated than dcmtk. This uses the following libraries: |
One other comment - in many cases you can decompress images by using the operating system APIs. This tends to be very efficient. However, at the moment these do not seem sufficient for medical imaging, for example OS X 10.10 (Yosemite) the command "imageRepsWithContentsOfFile" will open JPEG2000 images but they are ALWAYS down sampled to 8-bit precision. This is different from TIFF images where the precision is preserved. Therefore, we really need custom libraries. |
How about using Pillow? It seems to support the full list of formats? Or imageio wich also seems to support them all? |
I have not tried these libraries, but I assume they would need to be extended to support DICOM's very arcane lossless JPEG (again, not hard - this is the Huffman decoding without the DCT). Also, make sure they do not decode 16-bit precision to 8-bit. |
Unless something has changed, PIL (or pillow AFAIK) did not support 16-bit, which is what most dicom grayscale images would be. For imageio (http://imageio.readthedocs.org/en/latest/format_dicom.html#dicom):
|
The discussion here may help: python-pillow/Pillow#625 |
I think Pillow actually does support 16-bit currently: python-pillow/Pillow#730 (from @jrkerns link, thanks!). |
See #232! |
In a post[1] on the pydicom google group, cardioninja shared some concise code which can decompress 8-bit jpeg, if libjpeg-turbo and its cffi interface jpeg4py are installed. This was confirmed to work on files from Philips Echocardiography machines - iE33 & Affinity. Cardioninja also comments that it would be trivial to use PIL or Pillow instead, but libjpeg-turbo was much faster. Cardioninja's code is replicated below. As a side note, it also uses mmap, which is related to #139. I think it would be interesting to add "handlers" for various types of compressed images through a plug-in architecture -- in this case, if the code was registered as a handler for 8-bit jpeg, then anyone with the right libraries already installed could transparently read those images. Handlers should check for their dependencies and only register for transfer syntaxes they can decompress given the libraries installed. Perhaps a call function could also determine which additional libraries could give more functionality, so that pydicom could point to them in the NotImplemented exception message. (e.g. 'pydicom cannot handle this image, but if you installed Here is cardioninja's 8-bit jpeg code: import os
import sys
import mmap
import numpy as np
import jpeg4py
def jpeg_extract(file_fl):
frames = []
with open(file_fl, "r+b") as dicom_f:
with mmap.mmap(dicom_f.fileno(), 0) as dicom_m:
i = 0
while 1:
start = dicom_m.find(b"\xff\xd8\xff\xe0", i)
if start == -1:
break
i = start
end = dicom_m.find(b"\xff\xd9", i)
if end == -1:
break
try:
jpg_data = np.fromstring(dicom_m[start: end+2], dtype=np.uint8)
jpeg4py.JPEG.clear() #needed as if it ever fails, it won't decode another frame without a reset
image_data = jpeg4py.JPEG(jpg_data.copy()).decode()
frames.append(image_data)
except Exception as e:
print(e)
i = end
return np.array(frames) [1] https://groups.google.com/d/msg/pydicom/PJ9K37dsmBk/OXLJtprjCQAJ |
Thanks. Thats my code (cardioninja) - I only saw your reply and issue just now. Agree it would be nice to add to pydicom. Would you be happy including ctypes wrapper (jpeg4py) in the pydicom code; that way to utilise the helper the user would only have to drop in the dll/dylib/so downloaded from the website in the application directory? Sketching out the code - with the simplest boiler plate:
I guess you could have a init on the handler classes so that they can initialise and return success from the, and re-use the instance each time you need to decode a dicom file. May save a few ms. How does this sound? BW Matt |
I've mentioned in a couple of issues some old code I had tinkered with before, but I never tracked it down or explained it. I thought I'd do that here because I had discussed the concepts in an earlier comment in this issue. The config idea can be seen in https://github.com/pydicom/pydicom/blob/feaIture/image-handlers/pydicom/config.py#L63 image_handlers = ['standard_handler', 'gdcm_handler'] # jpgls_handler, pil_handler
"""Image handlers for converting pixel data. These are tried in order
until one can provide the pixel data. The code is in the 'handlers' subdir.
Change the order if needed to force using a specific handler, e.g. for speed.
Handlers may require installation of dependencies. If dependencies are not
installed, the handler will not attempt conversion, and the next handler
would be called. If none can convert, the handlers will provide messages
on what dependencies are needed.
""" Each handler should be split out into its own def process(ds):
"""Return a numpy array of pixel data for the given data.
Returns:
-------
pixel_array: None, or numpy array
If unable to process the pixel data, returns None.
message: str
If unable to process, a message explaining libraries to install,
or reason it cannot be processed. So each handler "answers" back with either the pixel data, or with None and a message. Note that even non-compressed images are handled this way -- so if someone wants, e.g. to use gdcm for all images, compressed or not, they can do so by changing the config order. I think I had started trying to refactor |
i try use python install model https://github.com/rii-mango/JPEGLosslessDecoderJS I try to export the dicom file as a jpeg or other picture。 |
@qile11, I don't understand your request. Have you been using pydicom, or are you looking for a way to use pydicom for converting dicom files to an image? |
I think this one has been implemented now by @darcymason and can be closed. @qile11 - please check the documentation, especially the parts about "Working with Pixel Data" and "Handling of compressed image data" for getting started. |
Thank you
try:
Traceback (most recent call last): print(dicom.PixelData ) is:
Is there a specific example file? |
From the Handling of Compressed Images page in the docs you need to install GDCM or possibly Pillow to handle that transfer syntax. If you want |
From darcymason@gmail.com on October 07, 2008 20:40:33
pydicom can read JPEG files, but the pixel data remains compressed. Should
investigate incorporating JPEG code to allow at least decompression of read
images.
Original issue: http://code.google.com/p/pydicom/issues/detail?id=16
The text was updated successfully, but these errors were encountered: