Unnecessary system dependency
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 256
- Forks
- 75
- PR merge metrics
- No merged PRs in 30d
Description
Hello!
I noticed that the libGL system dependency is not strictly necessary as OpenCV's GUI functionalities (e.g. cv2.imshow) are not utilized. opencv-python-headless is a drop-in replacement for opencv-python which excludes the GUI library dependencies, and therefore may be used to remove rt-utils' dependency on libGL.
To ensure that switching to opencv-python-headless doesn't break existing behaviour, I drafted basic sanity tests for some relevant functions in image_helper.py, which I ran in a Docker container explicitly built without libGL. Please see the end of this message for reference. While these tests pass, I welcome any suggestions for further testing of this module (specifically get_slice_mask_from_slice_contour_data).
Will make a PR with these changes soon in the hopes that they may help someone else.
Thanks!
📁 requirements.txt
# requirements.txt
- opencv-python>=4.0.0
+ opencv-python-headless>=4.0.0
📁 Dockerfile
# Dockerfile
FROM ubuntu
WORKDIR /app
# Explicitly *not* installing LibGL (libgl1 && libglib2.0-0)
RUN apt-get update && \
apt-get install -y python3 python3-pip python3-venv && \
rm -rf /var/lib/apt/lists/*
COPY . .
ENV PATH="/opt/venv/bin:$PATH"
RUN python3 -m venv /opt/venv && \
pip3 install pytest && \
pip3 install --no-cache-dir -r requirements.txt
CMD ["pytest"]
📁 tests/test_image_helper.py
# tests/test_image_helper.py
import pytest
import numpy as np
from rt_utils.image_helper import (
load_sorted_image_series,
create_empty_series_mask,
find_mask_contours,
draw_line_upwards_from_point,
)
def create_full_series_mask(series_data):
ref_dicom_image = series_data[0]
mask_dims = (
int(ref_dicom_image.Columns),
int(ref_dicom_image.Rows),
len(series_data),
)
mask = np.ones(mask_dims).astype(bool)
return mask
def test_find_mask_contours_with_empty_mask(series_path):
series_data = load_sorted_image_series(series_path)
empty_mask = create_empty_series_mask(series_data)[:, :, 0]
# `hierarchy` is `None` in this case, thus `hierarchy = hierarchy[0]` fails
with pytest.raises(TypeError):
actual_contours, actual_hierarchy = find_mask_contours(empty_mask, True)
def test_find_mask_contours_with_full_mask(series_path):
series_data = load_sorted_image_series(series_path)
full_mask = create_full_series_mask(series_data)[:, :, 0]
# Entire mask is a single contour
expected_contours = [
[
[np.int32(0), np.int32(0)],
[np.int32(0), np.int32(511)],
[np.int32(511), np.int32(511)],
[np.int32(511), np.int32(0)],
]
]
expected_hierarchy = [[np.int32(-1), np.int32(-1), np.int32(-1), np.int32(-1)]]
actual_contours, actual_hierarchy = find_mask_contours(full_mask, True)
assert np.array_equal(expected_contours, actual_contours) == True
assert np.array_equal(expected_hierarchy, actual_hierarchy) == True
def test_draw_line_upwards_from_point_with_empty_mask(series_path):
series_data = load_sorted_image_series(series_path)
empty_mask = create_empty_series_mask(series_data)[:, :, 0]
start = (0, 0)
# Should fill (0,0) and one point in each direction
expected_binary_mask = empty_mask.copy()
expected_binary_mask[0][0] = True
expected_binary_mask[0][1] = True
expected_binary_mask[1][0] = True
actual_binary_mask = draw_line_upwards_from_point(empty_mask, start, 1)
assert np.array_equal(expected_binary_mask, actual_binary_mask) == True
def test_draw_line_upwards_from_point_with_full_mask(series_path):
series_data = load_sorted_image_series(series_path)
full_mask = create_full_series_mask(series_data)[:, :, 0]
start = (0, 0)
# Should remain unchanged
expected_binary_mask = full_mask.copy()
actual_binary_mask = draw_line_upwards_from_point(full_mask, start, 1)
assert np.array_equal(expected_binary_mask, actual_binary_mask) == True
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Review requirements.txt and image_helper.py, then inspect the proposed checks in tests/test_image_helper.py. Run the test suite in a Docker container without libGL after using the headless OpenCV dependency. Done means the relevant tests pass and the package no longer requires libGL.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- build-system, computer-vision, testing
- Issue type
- Refactor
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100