diff --git a/doc/examples/plot_seam_carving.py b/doc/examples/plot_seam_carving.py index 1c2dcfc9..0583cd5d 100644 --- a/doc/examples/plot_seam_carving.py +++ b/doc/examples/plot_seam_carving.py @@ -1,19 +1,38 @@ +""" +============ +Seam Carving +============ + +This example demonstrates how images can be resized using seam carving [1]_. +Resizing often distorts contents in the image. Seam carving tries to resize +images while trying to keep important content intact. 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 io, data from skimage import transform from skimage import color, filters from matplotlib import pyplot as plt -def custom_sobel(img): - if img.ndim == 3: - img = color.rgb2gray(img) - - return filters.sobel(img) img = data.coins() -out = transform.seam_carve(img, 'vertical', 80, energy_func = custom_sobel) -out = transform.seam_carve(out, 'horizontal', 70, energy_func = custom_sobel) +out = transform.seam_carve(img, 'vertical', 80, energy_func = filters.sobel) +out = transform.seam_carve(out, 'horizontal', 70, energy_func = filters.sobel) +resized = transform.resize(img, out.shape) + +plt.title('Original Image') +io.imshow(img, plugin='matplotlib') -io.imshow(out) plt.figure() -io.imshow(img) +plt.title('Resized Image Image') +io.imshow(resized, plugin='matplotlib') + +plt.figure() +plt.title('Resized Image Image') +io.imshow(out, plugin='matplotlib') + io.show() diff --git a/skimage/transform/_seam_carving.pyx b/skimage/transform/_seam_carving.pyx index 3d07beb5..188c8dcb 100644 --- a/skimage/transform/_seam_carving.pyx +++ b/skimage/transform/_seam_carving.pyx @@ -84,7 +84,7 @@ cdef find_seam_v(cnp.double_t[:, ::1] energy_img, cnp.int8_t[:, ::1] track_img, return seam -cdef remove_seam_h_2d(cnp.double_t[:, ::1] img, Py_ssize_t[::1] seam, +cdef remove_seam_v_2d(cnp.double_t[:, ::1] img, Py_ssize_t[::1] seam, Py_ssize_t cols): cdef Py_ssize_t rows, row, col, idx rows = img.shape[0] @@ -105,14 +105,14 @@ cdef remove_seam_h_2d(cnp.double_t[:, ::1] img, Py_ssize_t[::1] seam, ----- `seam` is passed as an argument so that we don't have to reallocate it for each iteration in `_seam_carve_v`. - """" + """ for row in range(rows): for idx in range(seam[row], cols - 1): img[row, idx] = img[row, idx + 1] -cdef remove_seam_h_3d(cnp.double_t[:, :, ::1] img, Py_ssize_t[::1] seam, +cdef remove_seam_v_3d(cnp.double_t[:, :, ::1] img, Py_ssize_t[::1] seam, Py_ssize_t cols): """ Removes one horizontal seam from the image. @@ -131,7 +131,7 @@ cdef remove_seam_h_3d(cnp.double_t[:, :, ::1] img, Py_ssize_t[::1] seam, ----- `seam` is passed as an argument so that we don't have to reallocate it for each iteration in `_seam_carve_v`. - """" + """ cdef Py_ssize_t rows, row, col, idx rows = img.shape[0] @@ -201,9 +201,9 @@ def _seam_carve_v(img, iters, energy_func, extra_args , extra_kwargs, border): cols) if ndim == 2: - remove_seam_h_2d(img, seam, cols) + remove_seam_v_2d(img, seam, cols) elif ndim == 3: - remove_seam_h_3d(img, seam, cols) + remove_seam_v_3d(img, seam, cols) cols -= 1 diff --git a/skimage/transform/seam_carving.py b/skimage/transform/seam_carving.py index c716c0d1..e9c700b0 100644 --- a/skimage/transform/seam_carving.py +++ b/skimage/transform/seam_carving.py @@ -1,4 +1,4 @@ -from _seam_carving import _seam_carve_h +from _seam_carving import _seam_carve_v from ..import filters from .. import util from .._shared import utils @@ -47,6 +47,12 @@ def seam_carve(img, mode, num, energy_func, extra_args = [], ------- out : ndarray The cropped image with the seams removed. + + References + ---------- + .. [1] Shai Avidan and Ariel Shamir + "Seam Carving for Content-Aware Image Resizing" + http://www.cs.jhu.edu/~misha/ReadingSeminar/Papers/Avidan07.pdf """ utils.assert_nD(img, (2,3)) @@ -55,7 +61,7 @@ def seam_carve(img, mode, num, energy_func, extra_args = [], if mode == 'horizontal': img = np.ascontiguousarray(img) - return _seam_carve_h(img, num, energy_func, extra_args ,extra_kwargs, + return _seam_carve_v(img, num, energy_func, extra_args ,extra_kwargs, border) elif mode == 'vertical' : if img.ndim == 3: @@ -64,7 +70,7 @@ def seam_carve(img, mode, num, energy_func, extra_args = [], img = img.T img = np.ascontiguousarray(img) - out = _seam_carve_h(img, num, energy_func, extra_args , extra_kwargs, + out = _seam_carve_v(img, num, energy_func, extra_args , extra_kwargs, border) if img.ndim == 3: diff --git a/skimage/transform/tests/test_seam_carving.py b/skimage/transform/tests/test_seam_carving.py new file mode 100644 index 00000000..0c476b2d --- /dev/null +++ b/skimage/transform/tests/test_seam_carving.py @@ -0,0 +1,33 @@ +from skimage import transform +import numpy as np +from numpy import testing + +def energy(img): + if(img.ndim == 3): + return np.ascontiguousarray(img[:, :, 0]) + return (1 - img) + +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, 0], + [1, 0 , 0, 0, 0]], dtype = np.float ) + + out = transform.seam_carve(img, 'horizontal', 1, energy, border=0) + testing.assert_allclose(out, 0) + + img = img.T + out = transform.seam_carve(img, 'vertical', 1, energy, border=0) + testing.assert_allclose(out, 0) + + img = img.T + + img3 = np.dstack([img, img, img]) + + out = transform.seam_carve(img3, 'horizontal', 1, energy, border=0) + testing.assert_allclose(out, 0) + + + out = transform.seam_carve(img3, 'vertical', 1, energy, border=0) + testing.assert_allclose(out, 0)