Repository: scikit-image/scikit-image

Issue:
Seam carving is patented; remove from library
https://patents.google.com/patent/US8213745B2/en

Ref: #2808 #3082 #3643 

This code may be made available outside of scikit-image under the same license, but our policy is not to include algorithms covered under active patents.


Discussion:
The cited paper is from 2007. 

The priority date on the patent is from 2009.

I think you are safe @stefanv. 
Though it seems they cite a patent from the paper's authors, also from 2007. So :/
Yep, here's the actual patent:
https://patents.google.com/patent/US20080219587A1/en

Resolving patch:
diff --git a/doc/examples/transform/plot_seam_carving.py b/doc/examples/transform/plot_seam_carving.py
deleted file mode 100644
--- a/doc/examples/transform/plot_seam_carving.py
+++ /dev/null
@@ -1,85 +0,0 @@
-"""
-============
-Seam Carving
-============
-
-This example demonstrates how images can be resized using seam carving [1]_.
-Resizing to a new aspect ratio distorts image contents. Seam carving attempts
-to resize *without* distortion, by removing regions of an image which are less
-important. In this example we are using the Sobel filter to signify the
-importance of each pixel.
-
-.. [1] Shai Avidan and Ariel Shamir
-       "Seam Carving for Content-Aware Image Resizing"
-       http://www.cs.jhu.edu/~misha/ReadingSeminar/Papers/Avidan07.pdf
-
-"""
-from skimage import data, draw
-from skimage import transform, util
-import numpy as np
-from skimage import filters, color
-from matplotlib import pyplot as plt
-
-
-hl_color = np.array([0, 1, 0])
-
-img = data.rocket()
-img = util.img_as_float(img)
-eimg = filters.sobel(color.rgb2gray(img))
-
-plt.title('Original Image')
-plt.imshow(img)
-
-######################################################################
-
-resized = transform.resize(img, (img.shape[0], img.shape[1] - 200),
-                           mode='reflect')
-plt.figure()
-plt.title('Resized Image')
-plt.imshow(resized)
-
-######################################################################
-
-out = transform.seam_carve(img, eimg, 'vertical', 200)
-plt.figure()
-plt.title('Resized using Seam Carving')
-plt.imshow(out)
-
-######################################################################
-# Resizing distorts the rocket and surrounding objects, whereas seam carving
-# removes empty spaces and preserves object proportions.
-#
-# Object Removal
-# --------------
-#
-# Seam carving can also be used to remove artifacts from images. This
-# requires weighting the artifact with low values. Recall lower weights are
-# preferentially removed in seam carving. The following code masks the
-# rocket's region with low weights, indicating it should be removed.
-
-masked_img = img.copy()
-
-poly = [(404, 281), (404, 360), (359, 364), (338, 337), (145, 337), (120, 322),
-        (145, 304), (340, 306), (362, 284)]
-pr = np.array([p[0] for p in poly])
-pc = np.array([p[1] for p in poly])
-rr, cc = draw.polygon(pr, pc)
-
-masked_img[rr, cc, :] = masked_img[rr, cc, :]*0.5 + hl_color*.5
-plt.figure()
-plt.title('Object Marked')
-
-plt.imshow(masked_img)
-
-######################################################################
-
-eimg[rr, cc] -= 1000
-
-plt.figure()
-plt.title('Object Removed')
-out = transform.seam_carve(img, eimg, 'vertical', 90)
-resized = transform.resize(img, out.shape, mode='reflect')
-plt.imshow(out)
-plt.show()
-
-######################################################################
diff --git a/skimage/transform/seam_carving.py b/skimage/transform/seam_carving.py
--- a/skimage/transform/seam_carving.py
+++ b/skimage/transform/seam_carving.py
@@ -1,67 +1,16 @@
-from ._seam_carving import _seam_carve_v
-from .. import util
-from .._shared import utils
-import numpy as np
+def seam_carve(*args, **kwargs):
+    """Seam carving has been removed because it is a patented algorithm.
 
-
-def seam_carve(image, energy_map, mode, num, border=1, force_copy=True):
-    """ Carve vertical or horizontal seams off an image.
-
-    Carves out vertical/horizontal seams from an image while using the given
-    energy map to decide the importance of each pixel.
-
-    Parameters
-    ----------
-    image : (M, N) or (M, N, 3) ndarray
-        Input image whose seams are to be removed.
-    energy_map : (M, N) ndarray
-        The array to decide the importance of each pixel. The higher
-        the value corresponding to a pixel, the more the algorithm will try
-        to keep it in the image.
-    mode : str {'horizontal', 'vertical'}
-        Indicates whether seams are to be removed vertically or horizontally.
-        Removing seams horizontally will decrease the height whereas removing
-        vertically will decrease the width.
-    num : int
-        Number of seams are to be removed.
-    border : int, optional
-        The number of pixels in the right, left and bottom end of the image
-        to be excluded from being considered for a seam. This is important as
-        certain filters just ignore image boundaries and set them to `0`.
-        By default border is set to `1`.
-    force_copy : bool, optional
-        If set, the `image` and `energy_map` are copied before being used by
-        the method which modifies it in place. Set this to `False` if the
-        original image and the energy map are no longer needed after
-        this operation.
-
-    Returns
-    -------
-    out : ndarray
-        The cropped image with the seams removed.
-
-    References
-    ----------
-    .. [1] Shai Avidan and Ariel Shamir
-           "Seam Carving for Content-Aware Image Resizing"
-           https://www.cs.jhu.edu/~misha/ReadingSeminar/Papers/Avidan07.pdf
+    See https://github.com/scikit-image/scikit-image/issues/3646
     """
 
-    utils.assert_nD(image, (2, 3))
-    image = util.img_as_float(image, force_copy)
-    energy_map = util.img_as_float(energy_map, force_copy)
-
-    if image.ndim == 2:
-        image = image[..., np.newaxis]
+    message = (
+    """Seam carving has been removed because it is a patented algorithm.
 
-    if mode == 'horizontal':
-        image = np.swapaxes(image, 0, 1)
-        energy_map = np.swapaxes(energy_map, 0, 1)
+    See https://github.com/scikit-image/scikit-image/issues/3646
 
-    image = np.ascontiguousarray(image)
-    out = _seam_carve_v(image, energy_map, num, border)
-
-    if mode == 'horizontal':
-        out = np.swapaxes(out, 0, 1)
+    This message will be removed completely in scikit-image version 0.16.
+    """
+    )
 
-    return np.squeeze(out)
+    raise NotImplementedError(message)
diff --git a/skimage/transform/setup.py b/skimage/transform/setup.py
--- a/skimage/transform/setup.py
+++ b/skimage/transform/setup.py
@@ -15,8 +15,7 @@ def configuration(parent_package='', top_path=None):
 
     cython(['_hough_transform.pyx',
             '_warps_cy.pyx',
-            '_radon_transform.pyx',
-            '_seam_carving.pyx'], working_path=base_path)
+            '_radon_transform.pyx'], working_path=base_path)
 
     config.add_extension('_hough_transform', sources=['_hough_transform.c'],
                          include_dirs=[get_numpy_include_dirs()])
@@ -28,8 +27,6 @@ def configuration(parent_package='', top_path=None):
                          sources=['_radon_transform.c'],
                          include_dirs=[get_numpy_include_dirs()])
 
-    config.add_extension('_seam_carving', sources=['_seam_carving.c'],
-                         include_dirs=[get_numpy_include_dirs()])
     return config
 
 if __name__ == '__main__':


Test patch:
diff --git a/skimage/transform/tests/test_seam_carving.py b/skimage/transform/tests/test_seam_carving.py
--- a/skimage/transform/tests/test_seam_carving.py
+++ b/skimage/transform/tests/test_seam_carving.py
@@ -1,31 +1,10 @@
 from skimage import transform
-import numpy as np
-from numpy import testing
+import pytest
 
 
 def test_seam_carving():
-    img = np.array([[0, 0, 1, 0, 0],
-                    [0, 0, 1, 0, 0],
-                    [0, 0, 1, 0, 0],
-                    [0, 1, 0, 0, 1],
-                    [1, 0, 0, 1, 0]], dtype=np.float)
-
-    expected = np.array([[0, 0, 0, 0],
-                        [0, 0, 0, 0],
-                        [0, 0, 0, 0],
-                        [0, 0, 0, 1],
-                        [0, 0, 1, 0]], dtype=np.float)
-
-    energy = 1 - img
-
-    out = transform.seam_carve(img, energy, 'vertical', 1, border=0)
-    testing.assert_equal(out, expected)
-
-    img = img.T
-    energy = energy.T
-
-    out = transform.seam_carve(img, energy, 'horizontal', 1, border=0)
-    testing.assert_equal(out, expected.T)
+    with pytest.raises(NotImplementedError):
+        transform.seam_carve()
 
 
 if __name__ == '__main__':