diff --git a/cfast_slic.pxd b/cfast_slic.pxd index 284c8bd..ae9987e 100644 --- a/cfast_slic.pxd +++ b/cfast_slic.pxd @@ -59,6 +59,7 @@ cdef extern from "src/context.h" namespace "fslic": ContextRealDistL2(int H, int W, int K, const uint8_t* image, Cluster *clusters) except + cdef cppclass ContextRealDistNoQ(ContextRealDist): + bool float_color ContextRealDistNoQ(int H, int W, int K, const uint8_t* image, Cluster *clusters) except + cdef cppclass ContextBuilder: @@ -109,6 +110,7 @@ cdef class SlicModel: cdef public object preemptive cdef public float preemptive_thres cdef public object manhattan_spatial_dist + cdef public object float_color cdef public object last_timing_report cpdef void initialize(self, const uint8_t [:, :, ::1] image) diff --git a/cfast_slic.pyx b/cfast_slic.pyx index a2b0cb8..06a5c66 100644 --- a/cfast_slic.pyx +++ b/cfast_slic.pyx @@ -32,6 +32,7 @@ cdef class SlicModel: self.real_dist = real_dist self.real_dist_type = "standard" self.convert_to_lab = False + self.float_color = True self._c_clusters = malloc(sizeof(cfast_slic.Cluster) * num_components) memset(self._c_clusters, 0, sizeof(cfast_slic.Cluster) * num_components) @@ -161,6 +162,7 @@ cdef class SlicModel: cdef np.ndarray[np.uint16_t, ndim=2, mode='c'] assignments = np.zeros([H, W], dtype=np.uint16) cdef cfast_slic.Context *context cdef cfast_slic.ContextRealDist *context_real_dist + cdef cfast_slic.ContextRealDistNoQ *c_noq cdef ContextLSCBuilder lsc_builder lsc_builder.set_arch(self.arch_name) @@ -218,13 +220,15 @@ cdef class SlicModel: c_clusters, ) elif self.real_dist_type == 'noq': - context_real_dist = new cfast_slic.ContextRealDistNoQ( + c_noq = new cfast_slic.ContextRealDistNoQ( H, W, K, &image[0, 0, 0], c_clusters, ) + c_noq.float_color = self.float_color + context_real_dist = c_noq else: raise RuntimeError("No such real_dist_type " + repr(self.real_dist_type)) diff --git a/fast_slic/base_slic.py b/fast_slic/base_slic.py index ccf9639..5e8c13c 100644 --- a/fast_slic/base_slic.py +++ b/fast_slic/base_slic.py @@ -77,6 +77,11 @@ class SlicRealDistNoQ(SlicRealDist): arch_name = 'standard' real_dist_type = 'noq' + def __init__(self, *args, **kwargs): + float_color = kwargs.pop("float_color", True) + super(SlicRealDistNoQ, self).__init__(*args, **kwargs) + self._slic_model.float_color = float_color + class LSC(SlicRealDist): arch_name = 'standard' real_dist_type = 'lsc' diff --git a/src/context.cpp b/src/context.cpp index 8adf261..715ac1f 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -138,7 +138,7 @@ namespace fslic { } subsample_rem = 0; - subsample_stride = my_min(subsample_stride_config, (int)(2 * S + 1)); + subsample_stride = subsample_stride_config; { fstimer::Scope s("before_iteration"); before_iteration(); @@ -441,13 +441,15 @@ namespace fslic { } void ContextRealDistNoQ::before_iteration() { - lab_image.resize(3 * H * W, 0); - rgb_to_cielab_orig(image, &lab_image[0], lab_image.size()); - for (int k = 0; k < K; k++) { - int y = clusters[k].y, x = clusters[k].x; - clusters[k].r = lab_image[3 * (W * y + x)]; - clusters[k].g = lab_image[3 * (W * y + x) + 1]; - clusters[k].b = lab_image[3 * (W * y + x) + 2]; + if (float_color) { + lab_image.resize(3 * H * W, 0); + rgb_to_cielab_orig(image, &lab_image[0], lab_image.size()); + for (int k = 0; k < K; k++) { + int y = clusters[k].y, x = clusters[k].x; + clusters[k].r = lab_image[3 * (W * y + x)]; + clusters[k].g = lab_image[3 * (W * y + x) + 1]; + clusters[k].b = lab_image[3 * (W * y + x) + 2]; + } } } @@ -457,13 +459,19 @@ namespace fslic { void ContextRealDistNoQ::assign_clusters(const Cluster** target_clusters, int size) { if (manhattan_spatial_dist) { - assign_clusters_proto(target_clusters, size); + if (float_color) + assign_clusters_proto(target_clusters, size); + else + assign_clusters_proto(target_clusters, size); } else { - assign_clusters_proto(target_clusters, size); + if (float_color) + assign_clusters_proto(target_clusters, size); + else + assign_clusters_proto(target_clusters, size); } } - template + template void ContextRealDistNoQ::assign_clusters_proto(const Cluster** target_clusters, int size) { float coef = 1.0f / ((float)S / compactness); @@ -477,15 +485,21 @@ namespace fslic { uint16_t cluster_no = cluster->number; for (int i = y_lo; i < y_hi; i++) { if (!valid_subsample_row(i)) continue; - const float* __restrict image_row = &lab_image[3 * W * i]; + uint16_t* __restrict assignment_row = assignment.get_row(i); float* __restrict min_dist_row = min_dists.get_row(i); for (int j = x_lo; j < x_hi; j++) { - float dr = image_row[3 * j] - cluster_r, - dg = image_row[3 * j + 1] - cluster_g, - db = image_row[3 * j + 2] - cluster_b, - dy = coef * (i - cluster_y), - dx = coef * (j - cluster_x); + float dr, dg, db; + if (use_float_color) { + dr = lab_image[3 * W * i + 3 * j] - cluster_r; + dg = lab_image[3 * W * i + 3 * j + 1] - cluster_g; + db = lab_image[3 * W * i + 3 * j + 2] - cluster_b; + } else { + dr = quad_image.get(i, 4 * j) - cluster_r; + dg = quad_image.get(i, 4 * j + 1) - cluster_g; + db = quad_image.get(i, 4 * j + 2) - cluster_b; + } + float dy = coef * (i - cluster_y), dx = coef * (j - cluster_x); float distance; if (use_manhattan) { diff --git a/src/context.h b/src/context.h index a084d6d..b78d09d 100644 --- a/src/context.h +++ b/src/context.h @@ -106,13 +106,14 @@ namespace fslic { class ContextRealDistNoQ : public ContextRealDist { public: using ContextRealDist::ContextRealDist; + bool float_color = true; private: std::vector lab_image; protected: virtual void assign_clusters(const Cluster **target_clusters, int size); virtual bool centroid_quantization_enabled(); private: - template + template void assign_clusters_proto(const Cluster **target_clusters, int size); protected: virtual void before_iteration();