Skip to content
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

dicom_redact.py - added lossless compression #31

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions doc/dicom_redact.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,20 @@ overlays. This tool can do that job to fully clean a DICOM file.
## NOTE!

The utility has to decompress the image (if compressed), but it
does not (yet) recompress the image again afterwards, so the file size
may increase. Some other redaction tools have the ability to preserve
does not recompress the image again afterwards using the same
compression scheme so the file size may increase.
Some other redaction tools have the ability to preserve
most of a lossy-JPEG-compressed image except for the redacted blocks,
but those tools do not handle overlays at all. Compression, and lossy
compression support can of course be added to this tool later.
but those tools do not handle overlays at all. Lossless compression is
an option but the only scheme supported is JPEG2000Lossless.

## Usage:

```
-v, --verbose Verbose
--db DB database directory to read rectangles (needs --dicom)
--csv CSV CSV path to read rectangles (redacts all files in csv if --dicom not used)
--compress Compress the output using lossless JPEG2000
--dicom DICOM DICOM path to be redacted
-o OUTPUT, --output O Output DICOM dir or filename (created automatically if not specified)
--relative-path RELATIVE
Expand Down
23 changes: 23 additions & 0 deletions src/applications/dicom_redact.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import re
import pydicom
from pydicom.pixel_data_handlers.numpy_handler import pack_bits
from pydicom.uid import JPEGLSLossless, JPEG2000Lossless
from DicomPixelAnon.rect import Rect, DicomRect, DicomRectText, rect_exclusive_list
from DicomPixelAnon.nerengine import NER
from DicomPixelAnon.ocrenum import OCREnum
Expand Down Expand Up @@ -54,6 +55,10 @@
elem_OverlayNumFrames = 0x0015
elem_OverlayOrigin = 0x0050

# Choose compression scheme as 'JPEG-LS' or 'JPEG2000'
# (only the latter is supported on Python 3.6)
compression_scheme = 'JPEG2000'


# ---------------------------------------------------------------------

Expand All @@ -71,6 +76,21 @@ def mark_as_uncompressed(ds):
ds.file_meta.TransferSyntaxUID = pydicom.uid.ExplicitVRBigEndian


# ---------------------------------------------------------------------

def compress_dataset(ds):
""" Do lossless compression of the pydicom Dataset
"""
if compression_scheme == 'JPEG-LS':
ds.compress(JPEGLSLossless)
# ds.file_meta.TransferSyntaxUID = JPEGLSLossless # should already be done
elif compression_scheme == 'JPEG2000':
ds.compress(JPEG2000Lossless)
# ds.file_meta.TransferSyntaxUID = JPEG2000Lossless # should already be done
else:
logger.warning('unknown compression_scheme, will not compress')


# ---------------------------------------------------------------------

def overlay_tag_group_from_index(overlay):
Expand Down Expand Up @@ -647,6 +667,7 @@ def test_create_output_filename():
parser = argparse.ArgumentParser(description='Redact DICOM')
parser.add_argument('-v', '--verbose', action="store_true", help='Verbose')
parser.add_argument('--db', dest='db', action="store", help='database directory to read rectangles (needs --dicom)')
parser.add_argument('--compress', dest='compress', action="store_true", help='Use lossless compression (JPEG2000)')
parser.add_argument('--csv', dest='csv', action="store", help='CSV path to read rectangles (redacts all files in csv if --dicom not used)')
parser.add_argument('--dicom', dest='dicom', nargs='*', action="store", help='DICOM filename(s) to be redacted', default=None)
parser.add_argument('-o', '--output', dest='output', action="store", help='Output DICOM dir or filename (created automatically if not specified)', default=[])
Expand Down Expand Up @@ -724,4 +745,6 @@ def test_create_output_filename():
outfilename = create_output_filename(infilename, args.output, args.relative)
ds = pydicom.dcmread(infilename)
redact_DicomRect_rectangles(ds, rect_list)
if args.compress:
compress_dataset(ds)
ds.save_as(outfilename)
1 change: 1 addition & 0 deletions src/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pydicom
pylibjpeg
pylibjpeg_libjpeg
pylibjpeg_openjpeg
pydal
pymongo
Pillow
Expand Down