feat: finished cluster selecting filtering and linking
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Lilian1024
2024-12-06 00:18:41 +01:00
parent e52b2de13f
commit d6fe3c4ee1
3 changed files with 379 additions and 58 deletions

View File

@ -1,3 +1,4 @@
#define _GNU_SOURCE
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
@ -26,6 +27,10 @@ int main(int argc, char *argv[])
SDL_Surface* img = IMG_Load(combine_path(application_directory, "image.png"));
/*image_to_black_white(img);
IMG_SavePNG(img, "/mnt/e/Programmation/C/OCRudoku/build/image.png");*/
/*int x = 4;
int y = 2;
int w = 1;
@ -41,9 +46,39 @@ int main(int argc, char *argv[])
}
}*/
SDL_Rect rect;
size_t nb_clusters;
get_clusters(img, rect);
pixel_cluster* clusters = get_clusters(img, &nb_clusters);
size_t nb_filtered;
pixel_cluster* filtered = filter_primary_clusters(clusters, nb_clusters, &nb_filtered);
size_t nb_linkages;
size_t* linkages_len;
pixel_cluster** linkages = get_clusters_linkages(filtered, nb_filtered, &nb_linkages, &linkages_len);
for (size_t i = 0; i < nb_linkages; i++)
{
printf("%li: %li\n", i, linkages_len[i]);
}
(void)linkages;
/*for (size_t i = 0; i < nb_filtered; i++)
{
SDL_Surface* surf = copy_cluster(img, filtered[i]);
char* path;
asprintf(&path, "/mnt/e/Programmation/C/OCRudoku/build/res/cluster_%li.png", i);
IMG_SavePNG(surf, path);
SDL_FreeSurface(surf);
}*/
//SDL Init
/*SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);

View File

@ -407,6 +407,16 @@ SDL_Surface* rotate_pixels(SDL_Surface* surface, double angle) {
return rotated_surface;
}
int get_bin_pixel(SDL_Surface* surface, int x, int y)
{
Uint8 r,g,b;
SDL_GetRGB(get_pixel_val(get_pixel_pt(surface, x, y), surface->format), surface->format, &r, &g, &b);
int bright = (r + g + b) / 3;
return bright < 127;
}
void get_cluster_size(SDL_Surface* surface, int* x, int* y, int* w, int* h, int currx, int curry, int visited[surface->w][surface->h])
{
visited[currx][curry] = 1;
@ -430,13 +440,8 @@ void get_cluster_size(SDL_Surface* surface, int* x, int* y, int* w, int* h, int
if (visited[currx + dx][curry + dy])
continue;
Uint8 r,g,b;
SDL_GetRGB(get_pixel_val(get_pixel_pt(surface, currx + dx, curry + dy), surface->format), surface->format, &r, &g, &b);
int bright = (r + g + b) / 3;
if (bright < 127)
if (get_bin_pixel(surface, currx + dx, curry + dy))
{
if (currx + dx < *x)
{
@ -458,9 +463,11 @@ void get_cluster_size(SDL_Surface* surface, int* x, int* y, int* w, int* h, int
}
}
void copy_cluster(SDL_Surface* surface, SDL_Surface* new_surface, int x, int y, int sx, int sy, int visited[surface->w][surface->h])
void copy_cluster_aux(SDL_Surface* surface, SDL_Surface* new_surface, int x, int y, int sx, int sy, int visited[])
{
visited[x][y] = 1;
visited[((y - sy) * new_surface->w) + (x - sx)] = 1;
set_pixel_val(get_pixel_pt(new_surface, x - sx, y - sy), new_surface->format, SDL_MapRGB(new_surface->format, 0, 0, 0));
for (int i = 0; i < 9; i++)
{
@ -470,36 +477,52 @@ void copy_cluster(SDL_Surface* surface, SDL_Surface* new_surface, int x, int y,
int dx = (i%3) - 1;
int dy = (i/3) - 1;
if (dx < 0 && x <= 0)
if (dx < 0 && x - sx <= 0)
continue;
if (dx > 0 && x >= surface->w - 1)
if (dx > 0 && x - sx >= new_surface->w - 1)
continue;
if (dy < 0 && y <= 0)
if (dy < 0 && y - sy <= 0)
continue;
if (dy > 0 && y >= surface->h - 1)
if (dy > 0 && y - sy >= new_surface->h - 1)
continue;
if (visited[x + dx][y + dy])
if (visited[(((y - sy) + dy) * new_surface->w) + (x - sx) + dx])
continue;
Uint8 r,g,b;
SDL_GetRGB(get_pixel_val(get_pixel_pt(surface, x + dx, y + dy), surface->format), surface->format, &r, &g, &b);
int bright = (r + g + b) / 3;
if (bright < 127)
if (get_bin_pixel(surface, x + dx, y + dy))
{
//Copy
set_pixel_val(get_pixel_pt(new_surface, x + dx - sx, y + dy - sy), new_surface->format, SDL_MapRGB(new_surface->format, r, g, b));
copy_cluster(surface, new_surface, x + dx, y + dy, sx, sy, visited);
copy_cluster_aux(surface, new_surface, x + dx, y + dy, sx, sy, visited);
}
}
}
cluster_split_result* get_clusters(SDL_Surface* surface, SDL_Rect rect)
SDL_Surface* copy_cluster(SDL_Surface* surface, pixel_cluster cluster_rect)
{
(void)rect;
int visited[cluster_rect.w * cluster_rect.h];
SDL_Surface* new_surface = SDL_CreateRGBSurface(0, cluster_rect.w, cluster_rect.h, 32, 0, 0, 0, 0);
if (new_surface == NULL)
errx(EXIT_FAILURE, "copy_cluster: failed to create surface!");
for (int i = 0; i < cluster_rect.w; i++)
{
for (int j = 0; j < cluster_rect.h; j++)
{
visited[(j * cluster_rect.w) + i] = 0;
set_pixel_val(get_pixel_pt(new_surface, i, j), new_surface->format, SDL_MapRGB(new_surface->format, 255, 255, 255));
}
}
copy_cluster_aux(surface, new_surface, cluster_rect.start_x, cluster_rect.start_y, cluster_rect.origin_x, cluster_rect.origin_y, visited);
return new_surface;
}
pixel_cluster* get_clusters(SDL_Surface* surface, size_t* cluster_nb)
{
*cluster_nb = 0;
int visited[surface->w][surface->h];
for (int y = 0; y < surface->h; y++)
@ -516,6 +539,9 @@ cluster_split_result* get_clusters(SDL_Surface* surface, SDL_Rect rect)
{
if (visited[x][y])
continue;
if (!get_bin_pixel(surface, x, y))
continue;
int nx = x;
int ny = y;
@ -524,33 +550,285 @@ cluster_split_result* get_clusters(SDL_Surface* surface, SDL_Rect rect)
get_cluster_size(surface, &nx, &ny, &w, &h, nx, ny, visited);
SDL_Surface* new_surface = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);
for (int i = 0; i < surface->h; i++)
{
for (int j = 0; j < surface->w; j++)
{
visited[j][j] = 0;
}
}
copy_cluster(surface, new_surface, nx, ny, nx, ny, visited);
char* path = calloc(400, sizeof(char));
memset(path, 0, 200);
strcpy(path, "/mnt/d/DataDocuments/Dev/C/OCRudoku/build/res/");
char* file_name;
asprintf(&file_name, "cluster_(%i,%i).png", x, y);
IMG_SavePNG(new_surface, strcpy(path, file_name));
(*cluster_nb)++;
}
}
return NULL;
for (int y = 0; y < surface->h; y++)
{
for (int x = 0; x < surface->w; x++)
{
visited[x][y] = 0;
}
}
pixel_cluster* result = calloc(*cluster_nb, sizeof(pixel_cluster));
size_t i = 0;
for (int y = 0; y < surface->h; y++)
{
for (int x = 0; x < surface->w; x++)
{
if (visited[x][y])
continue;
if (!get_bin_pixel(surface, x, y))
continue;
int nx = x;
int ny = y;
int w = 1;
int h = 1;
get_cluster_size(surface, &nx, &ny, &w, &h, nx, ny, visited);
result[i] = (pixel_cluster){
nx,
ny,
w,
h,
x,
y
};
i++;
}
}
return result;
}
pixel_cluster* filter_primary_clusters(pixel_cluster* clusters, size_t nb_clusters, size_t* filtered_nb)
{
*filtered_nb = 0;
for (size_t i = 0; i < nb_clusters; i++)
{
pixel_cluster curr = clusters[i];
int found = 0;
for (size_t j = 0; j < nb_clusters; j++)
{
if (i == j)
continue;
pixel_cluster target = clusters[j];
if (curr.origin_x <= target.origin_x && curr.origin_x + curr.w >= target.origin_x + target.w) //target contained in curr of x
{
if (curr.origin_y <= target.origin_y && curr.origin_y + curr.h >= target.origin_y + target.h) //target contained in curr of y
{
found = 1;
break;
}
}
}
if (found)
continue;
(*filtered_nb)++;
}
pixel_cluster* filtered = calloc(*filtered_nb, sizeof(pixel_cluster));
size_t filtered_count = 0;
for (size_t i = 0; i < nb_clusters; i++)
{
pixel_cluster curr = clusters[i];
int found = 0;
for (size_t j = 0; j < nb_clusters; j++)
{
if (i == j)
continue;
pixel_cluster target = clusters[j];
if (curr.origin_x <= target.origin_x && curr.origin_x + curr.w >= target.origin_x + target.w) //target contained in curr of x
{
if (curr.origin_y <= target.origin_y && curr.origin_y + curr.h >= target.origin_y + target.h) //target contained in curr of y
{
found = 1;
break;
}
}
}
if (found)
continue;
filtered[filtered_count] = curr;
filtered_count++;
}
return filtered;
}
void get_cluster_center(pixel_cluster cluster, int* x, int* y)
{
*x = cluster.origin_x + (cluster.w / 2);
*y = cluster.origin_y + (cluster.h / 2);
}
double distance_between(int x1, int y1, int x2, int y2)
{
int dx = x2 - x1;
int dy = y2 - y1;
return sqrt((double)(dx * dx) + (double)(dy * dy));
}
void get_cluster_linkage_count_aux(pixel_cluster* clusters, size_t start, size_t cluster_nb, size_t* linkage_nb, double distance, double margin, int visited[cluster_nb])
{
int center_x, center_y;
get_cluster_center(clusters[start], &center_x, &center_y);
for (size_t i = 0; i < cluster_nb; i++)
{
if (visited[i])
continue;
int other_x, other_y;
get_cluster_center(clusters[i], &other_x, &other_y);
double dist = distance_between(center_x, center_y, other_x, other_y);
if (dist > distance - (distance * margin) && dist < distance + (distance * margin))
{
visited[i] = 1;
(*linkage_nb)++;
get_cluster_linkage_count_aux(clusters, i, cluster_nb, linkage_nb, distance, margin, visited);
}
}
}
void get_cluster_linkage_aux(pixel_cluster* clusters, size_t start, size_t cluster_nb, size_t* current_linkage, pixel_cluster* arr, double distance, double margin, int visited[cluster_nb])
{
int center_x, center_y;
get_cluster_center(clusters[start], &center_x, &center_y);
for (size_t i = 0; i < cluster_nb; i++)
{
if (visited[i])
continue;
int other_x, other_y;
get_cluster_center(clusters[i], &other_x, &other_y);
double dist = distance_between(center_x, center_y, other_x, other_y);
if (dist > distance - (distance * margin) && dist < distance + (distance * margin))
{
visited[i] = 1;
arr[*current_linkage] = clusters[i];
(*current_linkage)++;
get_cluster_linkage_aux(clusters, i, cluster_nb, current_linkage, arr, distance, margin, visited);
}
}
}
pixel_cluster* get_cluster_linkage(pixel_cluster* clusters, size_t start, size_t cluster_nb, size_t* linkage_nb, int visited[cluster_nb])
{
double margin = 0.2;
int center_x, center_y;
get_cluster_center(clusters[start], &center_x, &center_y);
double min_distance = -1;
for (size_t i = 0; i < cluster_nb; i++)
{
if (i == start)
continue;
int other_x, other_y;
get_cluster_center(clusters[i], &other_x, &other_y);
double dist = distance_between(center_x, center_y, other_x, other_y);
if (min_distance < 0 || dist < min_distance)
{
min_distance = dist;
}
}
*linkage_nb = 1;
visited[start] = 1;
int visited_copy[cluster_nb];
for (size_t i = 0; i < cluster_nb; i++)
{
visited_copy[i] = visited[i];
}
get_cluster_linkage_count_aux(clusters, start, cluster_nb, linkage_nb, min_distance, margin, visited_copy);
pixel_cluster* linkage = calloc(*linkage_nb, sizeof(pixel_cluster));
linkage[0] = clusters[start];
size_t linkage_count = 1;
get_cluster_linkage_aux(clusters, start, cluster_nb, &linkage_count, linkage, min_distance, margin, visited);
return linkage;
}
pixel_cluster** get_clusters_linkages(pixel_cluster* clusters, size_t cluster_nb, size_t* nb_linkages, size_t** linkage_len)
{
int visited[cluster_nb];
for (size_t i = 0; i < cluster_nb; i++)
{
visited[i] = 0;
}
*nb_linkages = 0;
for (size_t i = 0; i < cluster_nb; i++)
{
if (visited[i])
continue;
size_t nb;
get_cluster_linkage(clusters, i, cluster_nb, &nb, visited);
(*nb_linkages)++;
}
for (size_t i = 0; i < cluster_nb; i++)
{
visited[i] = 0;
}
pixel_cluster** linkages = calloc(*nb_linkages, sizeof(pixel_cluster*));
*linkage_len = calloc(*nb_linkages, sizeof(size_t));
size_t current_pos = 0;
for (size_t i = 0; i < cluster_nb; i++)
{
if (visited[i])
continue;
linkages[current_pos] = get_cluster_linkage(clusters, i, cluster_nb, &((*linkage_len)[current_pos]), visited);
current_pos++;
}
return linkages;
}
// int testsupercool(void) {

View File

@ -9,12 +9,14 @@
#ifndef IMAGE_UTILS_H
#define IMAGE_UTILS_H
typedef struct clust_res{
size_t x;
size_t y;
SDL_Surface* surface;
struct clust_res* next;
}cluster_split_result;
typedef struct{
int origin_x;
int origin_y;
int w;
int h;
int start_x;
int start_y;
}pixel_cluster;
void render_image_file(const char* file, SDL_Renderer* renderer, const SDL_Rect* srcrect, const SDL_Rect* dstrect);
@ -40,7 +42,13 @@ SDL_Surface* create_sub_surface(SDL_Surface* surface, SDL_Rect rect);
SDL_Surface* rotate_pixels(SDL_Surface* surface, double angle);
cluster_split_result* get_clusters(SDL_Surface* surface, SDL_Rect rect);
SDL_Surface* copy_cluster(SDL_Surface* surface, pixel_cluster cluster_rect);
pixel_cluster* get_clusters(SDL_Surface* surface, size_t* cluster_nb);
pixel_cluster* filter_primary_clusters(pixel_cluster* clusters, size_t nb_clusters, size_t* filtered_nb);
pixel_cluster** get_clusters_linkages(pixel_cluster* clusters, size_t cluster_nb, size_t* nb_linkages, size_t** linkage_len);
int testsupercool(void);