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

Expose Slic #26

Open
wants to merge 8 commits into
base: master
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
1 change: 1 addition & 0 deletions conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ test:
- coverage

imports:
- cyvlfeat.slic.slic
- cyvlfeat.sift.sift
- cyvlfeat.sift.dsift
- cyvlfeat.fisher.fisher
Expand Down
18 changes: 18 additions & 0 deletions cyvlfeat/_vl/slic.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
# All rights reserved.
#
# This file is part of the VLFeat library and is made available under
# the terms of the BSD license (see the COPYING file).

from cyvlfeat._vl.host cimport vl_size
from cyvlfeat._vl.host cimport vl_uint32

cdef extern from "vl/slic.h":
void vl_slic_segment(vl_uint32 * segmentation,
float * image,
vl_size width,
vl_size height,
vl_size numChannels,
vl_size regionSize,
float regularization,
vl_size minRegionSize)
47 changes: 47 additions & 0 deletions cyvlfeat/slic/cyslic.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
# All rights reserved.
#
# This file is part of the VLFeat library and is made available under
# the terms of the BSD license (see the COPYING file).


import numpy as np
cimport numpy as np
import ctypes
cimport cython
import cython
from libc.stdio cimport printf

# Import the header files
from cyvlfeat._vl.slic cimport *
from cyvlfeat._vl.host cimport *

@cython.boundscheck(False)
cpdef cy_slic(np.ndarray[float, ndim=2, mode='c'] image, int region_size,
float regularizer, bint verbose):

cdef:
vl_size width = image.shape[1]
vl_size height = image.shape[0]
vl_size n_channels = 1
# vl_size n_channels = image.shape[2]
int min_region_size = -1
np.ndarray[unsigned int, ndim=2, mode='c'] segmentation

if min_region_size < 0:
min_region_size = region_size * region_size/36
# printf("min_reigon_size cannot be less than 0. Assigning min_reigon_size = %d\n", min_region_size)

if verbose:
print('vl_slic: image: [{} x {} X {}]\n'
'vl_slic: region size: {}\n'
'vl_slic: regularizer: {}\n'
'vl_slic: min region size: {}'. format(
width, height, n_channels, region_size, regularizer, min_region_size ))

segmentation = np.zeros((height, width), dtype=np.uint32, order='C')

vl_slic_segment(&segmentation[0,0], &image[0, 0], height, width, n_channels,
region_size, regularizer, min_region_size)

return np.asarray(segmentation)
65 changes: 65 additions & 0 deletions cyvlfeat/slic/slic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import numpy as np
from cyvlfeat.slic.cyslic import cy_slic


def slic(image, region_size, regularizer, verbose=False):
r"""
Extracts the SLIC superpixels from the image.

Parameters
----------
image : [H, W] `float32` `ndarray`
A `float32` numpy array (ndarray)
representing the image to calculate superpixels for.
region_size : `int`
Starting size of the superpixels
regularizer : `float`
The trades-off appearance for spatial regularity
when clustering (a larger value results in more
spatial regularization)
verbose: `bool`, optional
If ``True``, be verbose.

Returns
-------
segments: `float32` `ndarray`
contains the superpixel identifier for each image pixel.

Examples
--------
>>> from cyvlfeat.slic.slic import slic
>>> import numpy as np
>>> from cyvlfeat.test_util import lena
>>> img = lena().astype(np.float32)
>>> segment = slic(img, region_size=10, regularizer=10)
"""

# Check for none
if image is None or region_size is None or regularizer is None:
raise ValueError('A required input is None')

# Remove last channel
if image.ndim == 3 and image.shape[-1] == 1:
image = image[..., 0]

# Validate image size
if image.ndim != 2:
raise ValueError('Only 2D arrays are supported')

# if image.ndim != 3:
# raise ValueError('Image should be a 3D array')

image = np.require(image, dtype=np.float32, requirements='C')

if region_size < 1:
raise ValueError('region_size cannot be less than 1')

if regularizer < 0:
raise ValueError('regularizer cannot be less than 0')

result = cy_slic(image, region_size, regularizer, verbose)

return result



Empty file added cyvlfeat/slic/tests/__init__.py
Empty file.
25 changes: 25 additions & 0 deletions cyvlfeat/slic/tests/slic_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from cyvlfeat.slic.slic import slic
import numpy as np
from numpy.testing import assert_allclose
from cyvlfeat.test_util import lena

img = lena().astype(np.float32)


def test_slic_dimension():
segment = slic(img, region_size=10, regularizer=10)
assert segment.shape[0] == img.shape[0]
assert segment.shape[1] == img.shape[1]


def test_slic_segment():
segment = slic(img, region_size=10, regularizer=10)
assert_allclose(segment[-4:-1, -1], [2702, 2703, 2703],
rtol=1e-3)
assert_allclose(segment[0:3, -1], [51, 51, 51],
rtol=1e-3)
assert_allclose(segment[0:3, 1], [0, 0, 0],
rtol=1e-3)
assert_allclose(segment[-4:-1, 1], [2600, 2600, 2600],
rtol=1e-3)

2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def gen_extension(path_name, sources):
LIBRARY_DIRS.append(conda_bin_dir)

vl_extensions = [
gen_extension('cyvlfeat.slic.cyslic',
[op.join('cyvlfeat', 'slic', 'cyslic.pyx')]),
gen_extension('cyvlfeat.sift.cysift',
[op.join('cyvlfeat', 'sift', 'cysift.pyx')]),
gen_extension('cyvlfeat.fisher.cyfisher',
Expand Down