 
         d_img_labels_.create(d_img_.x, d_img_.y, d_img_.z, CV_32SC1);
 
-        grid_size_ = dim3((d_img_.x + BLOCK_X - 1) / BLOCK_X, (d_img_.y + BLOCK_Y - 1) / BLOCK_Y, (d_img_.z + BLOCK_Z - 1) / BLOCK_Z);
+        allocated_last_cude_fg_ = false;
+        if ((d_img_.x % 2 == 1) && (d_img_.y % 2 == 1) && (d_img_.z % 2 == 1)) {
+            if (d_img_.x > 1 && d_img_.y > 1) {
+                last_cube_fg_ = reinterpret_cast<unsigned char*>(d_img_labels_.data + (d_img_labels_.z - 1) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 2;
+            }
+            else if (d_img_.x > 1 && d_img_.z > 1) {
+                last_cube_fg_ = reinterpret_cast<unsigned char*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 1) * d_img_labels_.stepy) + d_img_labels_.x - 2;
+            }
+            else if (d_img_.y > 1 && d_img_.z > 1) {
+                last_cube_fg_ = reinterpret_cast<unsigned char*>(d_img_labels_.data + (d_img_labels_.z - 2) * d_img_labels_.stepz + (d_img_labels_.y - 2) * d_img_labels_.stepy) + d_img_labels_.x - 1;
+            }
+            else {
+                cudaMalloc(&last_cube_fg_, sizeof(unsigned char));
+                allocated_last_cude_fg_ = true;
+            }
+        }
+
+        grid_size_ = dim3(((d_img_.x + 1) / 2 + BLOCK_X - 1) / BLOCK_X, ((d_img_.y + 1) / 2 + BLOCK_Y - 1) / BLOCK_Y, ((d_img_.z + 1) / 2 + BLOCK_Z - 1) / BLOCK_Z);
         block_size_ = dim3(BLOCK_X, BLOCK_Y, BLOCK_Z);
 
         InitLabeling << <grid_size_, block_size_ >> > (d_img_labels_);


                if (img[img_index + img.stepy / img.elem_size]) {
                    P |= (P0 << 4);
                }

            }

        }
    }

    __global__ void Merge(const cuda::PtrStepSz3b img, cuda::PtrStepSz3i labels, unsigned char* last_cube_fg) {

        unsigned x = (blockIdx.x * BLOCK_X + threadIdx.x) * 2;
        unsigned y = (blockIdx.y * BLOCK_Y + threadIdx.y) * 2;
