Skip to content
Merged
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
146 changes: 0 additions & 146 deletions imgproc/segmentation.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,152 +251,6 @@ embeddip_status_t grayscaleKMeans(const Image *src, Image *dst, int k)
return EMBEDDIP_OK;
}

/**
* @brief Segments an HSI image using K-means clustering.
*
* @param[in] inImg Pointer to input HSI image.
* @param[out] outImg Pointer to output segmented HSI image.
* @param[in] k Number of clusters.
*/
embeddip_status_t colorKMeans_old(const Image *inImg, Image *outImg, int k)
{
// Input validation
if (!inImg || !outImg) {
return EMBEDDIP_ERROR_NULL_PTR;
}

if (!inImg->pixels || !outImg->pixels) {
return EMBEDDIP_ERROR_NULL_PTR;
}

if (k <= 0 || k > 255) {
return EMBEDDIP_ERROR_INVALID_ARG;
}

// Support RGB888, HSI, and YUV (all 3-channel formats)
if (inImg->format != IMAGE_FORMAT_RGB888 && inImg->format != IMAGE_FORMAT_HSI &&
inImg->format != IMAGE_FORMAT_YUV) {
return EMBEDDIP_ERROR_INVALID_FORMAT;
}

if (outImg->format != inImg->format) {
return EMBEDDIP_ERROR_INVALID_FORMAT;
}

if (inImg->width != outImg->width || inImg->height != outImg->height) {
return EMBEDDIP_ERROR_INVALID_SIZE;
}

int size = inImg->size;
const uint8_t *in = (const uint8_t *)inImg->pixels;
uint8_t *out = (uint8_t *)outImg->pixels;

typedef struct {
float c0, c1, c2; // Generic: R/H/Y, G/S/U, B/I/V
} color_t;

color_t *centers = (color_t *)memory_alloc(k * sizeof(color_t));
int *labels = (int *)memory_alloc(size * sizeof(int));
int *counts = (int *)memory_alloc(k * sizeof(int));
color_t *sums = (color_t *)memory_alloc(k * sizeof(color_t));

if (!centers || !labels || !counts || !sums) {
// Cleanup any successful allocations
if (centers)
memory_free(centers);
if (labels)
memory_free(labels);
if (counts)
memory_free(counts);
if (sums)
memory_free(sums);
return EMBEDDIP_ERROR_OUT_OF_MEMORY;
}

// Check if format is HSI (needs hue wraparound)
bool is_hsi = (inImg->format == IMAGE_FORMAT_HSI);

// Initialize cluster centers evenly spaced in third channel (I/B/V)
for (int i = 0; i < k; ++i) {
centers[i].c0 = (float)(rand() % 256);
centers[i].c1 = (float)(rand() % 256);
centers[i].c2 = (255.0f / (k - 1)) * i;
}

for (int iter = 0; iter < MAX_ITER; ++iter) {
// Reset sums and counts
for (int j = 0; j < k; ++j) {
counts[j] = 0;
sums[j].c0 = sums[j].c1 = sums[j].c2 = 0.0f;
}

// Assignment step
for (int i = 0; i < size; ++i) {
int idx = i * 3;
float ch0 = in[idx];
float ch1 = in[idx + 1];
float ch2 = in[idx + 2];

float minDist = 1e9f;
int best = 0;

for (int j = 0; j < k; ++j) {
float d0 = fabsf(ch0 - centers[j].c0);
// HSI format: wraparound hue distance for first channel
if (is_hsi && d0 > 128)
d0 = 256 - d0;

float d1 = ch1 - centers[j].c1;
float d2 = ch2 - centers[j].c2;

float dist = d0 * d0 + d1 * d1 + d2 * d2;

if (dist < minDist) {
minDist = dist;
best = j;
}
}

labels[i] = best;
sums[best].c0 += ch0;
sums[best].c1 += ch1;
sums[best].c2 += ch2;
counts[best]++;
}

// Update step
for (int j = 0; j < k; ++j) {
if (counts[j] > 0) {
centers[j].c0 = sums[j].c0 / counts[j];
centers[j].c1 = sums[j].c1 / counts[j];
centers[j].c2 = sums[j].c2 / counts[j];
} else {
// Reinitialize empty cluster randomly
centers[j].c0 = (float)(rand() % 256);
centers[j].c1 = (float)(rand() % 256);
centers[j].c2 = (float)(rand() % 256);
}
}
}

// Final assignment - replace each pixel with its cluster center
for (int i = 0; i < size; ++i) {
int idx = i * 3;
int c = CLAMP(labels[i], 0, k - 1);

out[idx + 0] = (uint8_t)centers[c].c0;
out[idx + 1] = (uint8_t)centers[c].c1;
out[idx + 2] = (uint8_t)centers[c].c2;
}

memory_free(centers);
memory_free(labels);
memory_free(counts);
memory_free(sums);

return EMBEDDIP_OK;
}

/**
* @brief Segments an image using K-means in its native color space.
*
Expand Down
9 changes: 0 additions & 9 deletions imgproc/segmentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,6 @@ extern "C" {
*/
embeddip_status_t grayscaleKMeans(const Image *src, Image *dst, int k);

/**
* @brief Segments an HSI image using K-means clustering.
*
* @param[in] inImg Pointer to input HSI image.
* @param[out] outImg Pointer to output segmented HSI image.
* @param[in] k Number of clusters.
*/
embeddip_status_t colorKMeans_old(const Image *inImg, Image *outImg, int k);

/**
* @brief Segments an image using K-means in its native color space.
*
Expand Down
Loading