-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpyQuickshift.pyx
173 lines (132 loc) · 4.56 KB
/
pyQuickshift.pyx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
'''
Cython wrapper by Colin Lea
June 2012
Quickshift algorithm is part of vlfeat: http://www.vlfeat.org/
Copyright (C) 2007-12, Andrea Vedaldi and Brian Fulkerson
All rights reserved.
--Requirements--
Python 2.x (tested with 2.7)
Numpy 1.x (tested with 1.7)
Cython
VlFeat (tested with 0.9.14)
--Optional requirement--
Image module
--Compilation--
Run the following in the pyQuickshift folder:
python setup.py build_ext --inplace
--Example Usage--
import Image
import numpy as np
import pyQuickShift as qs
imgRaw = Image.open('/Users/colin/libs/vlfeat/data/a.jpg')
imgRGB = np.array(imgRaw, dtype=uint8)
img = np.ascontiguousarray(imgRaw, dtype=np.double)
if 0: # 3 channel
labels, dists, density = qs.quickshift_3D(img*.5, 2, 20) # Image, kernel size, maxDistance
else: # 1 channel
im2D = np.ascontiguousarray(img[:,:,2], dtype=double)
labels, dists, density = qs.quickshift_2D(im2D*.5, 2, 20) # Image, kernel size, maxDistance
print "There are", len(unique(labels)), "superpixels"
#Paint the superpixels with their average color
if len(unique(labels)) < 10000:
imgColor = np.empty_like(imgRGB)
for l in unique(labels):
imgColor[labels==l] = imgRGB[labels==l].mean(0)
imshow(imgColor)
'''
import numpy as np
cimport numpy as np
np.import_array()
from libcpp cimport bool
ctypedef double vl_qs_type
cdef extern from "math.h":
cdef int floor(double)
cdef extern from "../quickshift.h":
cdef struct VlQS
cdef VlQS* vl_quickshift_new (vl_qs_type*, int, int, int)
cdef void vl_quickshift_process (VlQS *q)
cdef void vl_quickshift_set_kernel_size (VlQS*, vl_qs_type)
cdef void vl_quickshift_set_max_dist (VlQS*, vl_qs_type)
cdef vl_quickshift_set_medoid (VlQS*, vl_bool)
cdef void vl_quickshift_delete(VlQS*)
cdef int* vl_quickshift_get_parents(VlQS*)
cdef vl_qs_type* vl_quickshift_get_dists(VlQS*)
cdef vl_qs_type* vl_quickshift_get_density(VlQS*)
cdef vl_qs_type vl_quickshift_get_max_dist(VlQS*)
cdef vl_qs_type vl_quickshift_get_kernel_size(VlQS*)
def quickshift_2D(np.ndarray[np.double_t, ndim=2] im, double kernelSize=2, double maxDist=-1):#, bool medoid=False):
cdef int height = im.shape[0]
cdef int width = im.shape[1]
cdef int channels = 1
cdef int old, new
cdef VlQS* obj
cdef int* parents
cdef vl_qs_type* distances
cdef vl_qs_type* density_
obj = vl_quickshift_new(<double*>im.data, height, width, channels)
# Set kernel size, max distance
vl_quickshift_set_kernel_size (obj, kernelSize)
if maxDist > 0:
vl_quickshift_set_max_dist(obj, maxDist)
# Process
vl_quickshift_process(obj)
# Get data
parents = vl_quickshift_get_parents(obj)
distances = vl_quickshift_get_dists(obj)
density_ = vl_quickshift_get_density(obj)
# For each pixel we must follow the trail to get to the topmost node Get base label
for i in range(height*width):
while 1:
old = parents[i]
new = parents[old]
# If at uppermost node, break
if new == old:
break
else:
parents[i] = new
cdef np.npy_intp shape[2]
shape[0] = height
shape[1] = width
npLabels = np.PyArray_SimpleNewFromData(2, shape, np.NPY_INT32, <void*>parents)
dists = np.PyArray_SimpleNewFromData(2, shape, np.NPY_DOUBLE, <void*>distances)
density = np.PyArray_SimpleNewFromData(2, shape, np.NPY_DOUBLE, <void*>density_)
# vl_quickshift_delete (obj)
return npLabels, dists, density
def quickshift_3D(np.ndarray[np.double_t, ndim=3] im, double kernelSize=2, double maxDist=-1):#, bool medoid=False):
cdef int height = im.shape[0]
cdef int width = im.shape[1]
cdef int channels = 3
cdef int old, new
cdef VlQS* obj
cdef int* parents
cdef vl_qs_type* distances
cdef vl_qs_type* density_
obj = vl_quickshift_new(<double*>im.data, height, width, channels)
# Set kernel size, max distance
vl_quickshift_set_kernel_size (obj, kernelSize)
if maxDist > 0:
vl_quickshift_set_max_dist(obj, maxDist)
# Process
vl_quickshift_process(obj)
# Get data
parents = vl_quickshift_get_parents(obj)
distances = vl_quickshift_get_dists(obj)
density_ = vl_quickshift_get_density(obj)
# For each pixel we must follow the trail to get to the topmost node Get base label
for i in range(height*width):
while 1:
old = parents[i]
new = parents[old]
# If at uppermost node, break
if new == old:
break
else:
parents[i] = new
cdef np.npy_intp shape[2]
shape[0] = height
shape[1] = width
npLabels = np.PyArray_SimpleNewFromData(2, shape, np.NPY_INT32, <void*>parents)
dists = np.PyArray_SimpleNewFromData(2, shape, np.NPY_DOUBLE, <void*>distances)
density = np.PyArray_SimpleNewFromData(2, shape, np.NPY_DOUBLE, <void*>density_)
# vl_quickshift_delete (obj)
return npLabels, dists, density