Skip to content

Commit e09b98a

Browse files
committed
Add morphology operations + feature extraction
1 parent 029feb2 commit e09b98a

File tree

5 files changed

+212
-0
lines changed

5 files changed

+212
-0
lines changed

include/morphology.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef MORPHOLOGY_H
2+
#define MORPHOLOGY_H
3+
4+
#include "matrix.h"
5+
#include <stddef.h>
6+
7+
Matrix structuring_element(size_t m, size_t n);
8+
9+
void smooth(Matrix *image, Matrix kernel);
10+
void dilate(Matrix *image, Matrix kernel);
11+
void erode(Matrix *image, Matrix kernel);
12+
void opening(Matrix *image, Matrix kernel);
13+
void closing(Matrix *image, Matrix kernel);
14+
void difference(Matrix *image1, Matrix image2);
15+
16+
#endif // MORPHOLOGY_H

include/segmentation.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ifndef SEGMENTATION_H
2+
#define SEGMENTATION_H
3+
4+
#include "matrix.h"
5+
6+
void segment(Matrix image);
7+
void feature_extraction(Matrix *image);
8+
9+
#endif // SEGMENTATION_H

src/main.c

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "error.h"
33
#include "image.h"
44
#include "matrix.h"
5+
#include "segmentation.h"
56
#include <stdio.h>
67

78
int main(int argc, char *argv[]) {
@@ -15,8 +16,12 @@ int main(int argc, char *argv[]) {
1516
try
1617
(bitmap_load(argv[1], &image));
1718

19+
feature_extraction(&image);
20+
1821
try
1922
(bitmap_save("out.bmp", &image));
2023

24+
matrix_free(&image);
25+
2126
return 0;
2227
}

src/morphology.c

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#include "morphology.h"
2+
#include "matrix.h"
3+
#include <assert.h>
4+
#include <float.h>
5+
6+
float smooth_pixel(size_t y, size_t x, Matrix *image, Matrix kernel);
7+
float dilate_pixel(size_t y, size_t x, Matrix *image, Matrix kernel);
8+
float erode_pixel(size_t y, size_t x, Matrix *image, Matrix kernel);
9+
10+
Matrix structuring_element(size_t m, size_t n) {
11+
size_t i, j;
12+
assert(m > 0 && n > 0 && m % 2 == 1 && n % 2 == 1);
13+
14+
Matrix se = matrix_new(m, n);
15+
for (i = 0; i < m; i++) {
16+
for (j = 0; j < n; j++) {
17+
se.val[i][j] = 1.f;
18+
}
19+
}
20+
21+
return se;
22+
}
23+
24+
void smooth(Matrix *image, Matrix kernel) {
25+
size_t i, j;
26+
27+
Matrix smoothed = matrix_new(image->h, image->w);
28+
for (i = 0; i < image->h; i++) {
29+
for (j = 0; j < image->w; j++) {
30+
smoothed.val[i][j] = smooth_pixel(i, j, image, kernel);
31+
}
32+
}
33+
34+
matrix_free(image);
35+
*image = smoothed;
36+
}
37+
38+
float smooth_pixel(size_t y, size_t x, Matrix *image, Matrix kernel) {
39+
size_t i, j;
40+
float pixel;
41+
42+
pixel = 0;
43+
for (i = 0; i < kernel.h; i++) {
44+
for (j = 0; j < kernel.w; j++) {
45+
if (y + i >= kernel.h / 2 && x + j >= kernel.w / 2
46+
&& y + i < image->h + kernel.h / 2
47+
&& x + j < image->w + kernel.w / 2) {
48+
pixel += image->val[y + i - kernel.h / 2][x + j - kernel.w / 2]
49+
* kernel.val[i][j];
50+
}
51+
}
52+
}
53+
54+
return pixel / (kernel.h * kernel.w);
55+
}
56+
57+
void dilate(Matrix *image, Matrix kernel) {
58+
size_t i, j;
59+
60+
Matrix dilated = matrix_new(image->h, image->w);
61+
for (i = 0; i < image->h; i++) {
62+
for (j = 0; j < image->w; j++) {
63+
dilated.val[i][j] = dilate_pixel(i, j, image, kernel);
64+
}
65+
}
66+
67+
matrix_free(image);
68+
*image = dilated;
69+
}
70+
71+
float dilate_pixel(size_t y, size_t x, Matrix *image, Matrix kernel) {
72+
size_t i, j;
73+
float max, v;
74+
75+
max = FLT_MIN;
76+
for (i = 0; i < kernel.h; i++) {
77+
for (j = 0; j < kernel.w; j++) {
78+
if (y + i >= kernel.h / 2 && x + j >= kernel.w / 2
79+
&& y + i < image->h + kernel.h / 2
80+
&& x + j < image->w + kernel.w / 2) {
81+
v = image->val[y + i - kernel.h / 2][x + j - kernel.w / 2]
82+
* kernel.val[i][j];
83+
if (v > max) {
84+
max = v;
85+
}
86+
}
87+
}
88+
}
89+
90+
return max;
91+
}
92+
93+
void erode(Matrix *image, Matrix kernel) {
94+
size_t i, j;
95+
96+
Matrix eroded = matrix_new(image->h, image->w);
97+
for (i = 0; i < image->h; i++) {
98+
for (j = 0; j < image->w; j++) {
99+
eroded.val[i][j] = erode_pixel(i, j, image, kernel);
100+
}
101+
}
102+
103+
matrix_free(image);
104+
*image = eroded;
105+
}
106+
107+
float erode_pixel(size_t y, size_t x, Matrix *image, Matrix kernel) {
108+
size_t i, j;
109+
float min, v;
110+
111+
min = FLT_MAX;
112+
for (i = 0; i < kernel.h; i++) {
113+
for (j = 0; j < kernel.w; j++) {
114+
if (y + i >= kernel.h / 2 && x + j >= kernel.w / 2
115+
&& y + i < image->h + kernel.h / 2
116+
&& x + j < image->w + kernel.w / 2) {
117+
v = image->val[y + i - kernel.h / 2][x + j - kernel.w / 2]
118+
* kernel.val[i][j];
119+
if (v < min) {
120+
min = v;
121+
}
122+
}
123+
}
124+
}
125+
126+
return min;
127+
}
128+
129+
void opening(Matrix *image, Matrix kernel) {
130+
dilate(image, kernel);
131+
erode(image, kernel);
132+
}
133+
134+
void closing(Matrix *image, Matrix kernel) {
135+
erode(image, kernel);
136+
dilate(image, kernel);
137+
}
138+
139+
void difference(Matrix *image1, Matrix image2) {
140+
size_t i, j;
141+
float d;
142+
assert(image1->h == image2.h && image1->w == image2.w);
143+
144+
for (i = 0; i < image1->h; i++) {
145+
for (j = 0; j < image1->w; j++) {
146+
d = image1->val[i][j] - image2.val[i][j];
147+
image1->val[i][j] = d < 0 ? -d : d;
148+
}
149+
}
150+
}

src/segmentation.c

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include "segmentation.h"
2+
#include "image.h"
3+
#include "matrix.h"
4+
#include "morphology.h"
5+
6+
/*
7+
* Morphology based feature extraction method
8+
* Proposed by Wu, Hsieh and Chen:
9+
* https://www.cin.ufpe.br/~if751/projetos/artigos/Morphology-based%20text%20line%20extraction.pdf
10+
*/
11+
void feature_extraction(Matrix *image) {
12+
Matrix kernel, closed;
13+
14+
kernel = structuring_element(3, 3);
15+
smooth(image, kernel);
16+
matrix_free(&kernel);
17+
18+
kernel = structuring_element(1, 21);
19+
closed = matrix_copy(*image);
20+
closing(&closed, kernel);
21+
opening(image, kernel);
22+
matrix_free(&kernel);
23+
24+
difference(image, closed);
25+
matrix_free(&closed);
26+
27+
kernel = structuring_element(5, 5);
28+
closing(image, kernel);
29+
matrix_free(&kernel);
30+
31+
image_threshold(10.f, 255.f, image);
32+
}

0 commit comments

Comments
 (0)