diff --git a/CHANGELOG.md b/CHANGELOG.md index 86f7271..19ec298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Version 0.1.35 - #374 Support pyzbar - #372 Support pydmtxlib - #371 Ugly error message when opening file with non-ascii characters in name +- #370 OpenCV Error when subsegmenting - #369 Keyboard shortcuts box too tall on some displays - #368 Ugly error message when creating a new inselect document on Mac OS X - #367 Reveal file doesn't work on Windows diff --git a/inselect/lib/segment.py b/inselect/lib/segment.py index 4f36fac..6423464 100644 --- a/inselect/lib/segment.py +++ b/inselect/lib/segment.py @@ -369,15 +369,19 @@ def segment_grabcut(image, window=None, seeds=[]): initial = np.zeros((h, w), np.uint8) initial[:] = cv2.GC_BGD initial[mag0 == 255] = cv2.GC_FGD - for i, rect in enumerate(rects): + for rect in rects: cv2.drawContours(initial, [rect[4]], -1, int(cv2.GC_FGD), -1) initial[display[:, :, 0] > 0] = cv2.GC_PR_FGD + if 0 not in initial: + # Crude solution to https://github.com/NaturalHistoryMuseum/inselect/issues/370 + # See also http://stackoverflow.com/a/7546787/1773758 + # Only ever seen in one image + initial[0, :] = 0 bgmodel = np.zeros((1, 65), np.float64) fgmodel = np.zeros((1, 65), np.float64) mask = initial - rect = None - cv2.grabCut(image, mask, rect, bgmodel, fgmodel, 1, cv2.GC_INIT_WITH_MASK) + cv2.grabCut(image, mask, None, bgmodel, fgmodel, 1, cv2.GC_INIT_WITH_MASK) mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8') contours, hierarchy = _find_contours(mask2.copy(), diff --git a/inselect/tests/gui/test_subsegment.py b/inselect/tests/gui/test_subsegment.py index d1610ed..605643a 100644 --- a/inselect/tests/gui/test_subsegment.py +++ b/inselect/tests/gui/test_subsegment.py @@ -4,11 +4,14 @@ from mock import patch from pathlib import Path +import cv2 + from PyQt5.QtCore import QPointF, QRect from PyQt5.QtWidgets import QMessageBox from inselect.gui.roles import MetadataRole, RectRole from inselect.gui.sort_document_items import SortDocumentItems +from inselect.lib.segment import segment_grabcut from .gui_test import GUITest @@ -95,5 +98,10 @@ def test_subsegment_no_seeds(self, mock_warning): self.assertTrue(expected in mock_warning.call_args[0]) + def test_subsegment_grabcut_fail(self): + "Subsegment image that has caused problems for cv2's grabcut function" + # https://github.com/NaturalHistoryMuseum/inselect/issues/370 + segment_grabcut(cv2.imread(str(TESTDATA / 'grabcut_problem.jpg'))) + if __name__ == '__main__': unittest.main() diff --git a/inselect/tests/test_data/grabcut_problem.jpg b/inselect/tests/test_data/grabcut_problem.jpg new file mode 100644 index 0000000..90f549d Binary files /dev/null and b/inselect/tests/test_data/grabcut_problem.jpg differ