-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcrossing_number.py
83 lines (71 loc) · 2.52 KB
/
crossing_number.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import cv2 as cv
import numpy as np
def minutiae_at(pixels, i, j, kernel_size):
"""
Crossing number methods is a really simple way to detect ridge endings and ridge bifurcations.
Then the crossing number algorithm will look at 3x3 pixel blocks:
if middle pixel is black (represents ridge):
if pixel on boundary are crossed with the ridge once, then it is a possible ridge ending
if pixel on boundary are crossed with the ridge three times, then it is a ridge bifurcation
"""
# if middle pixel is black (represents ridge)
if pixels[i][j] == 1:
if kernel_size == 3:
cells = [
(-1, -1),
(-1, 0),
(-1, 1),
(0, 1),
(1, 1),
(1, 0),
(1, -1),
(0, -1),
(-1, -1),
]
else:
cells = [
(-2, -2),
(-2, -1),
(-2, 0),
(-2, 1),
(-2, 2),
(-1, 2),
(0, 2),
(1, 2),
(2, 2),
(2, 1),
(2, 0),
(2, -1),
(2, -2),
(1, -2),
(0, -2),
(-1, -2),
(-2, -2),
]
values = [pixels[i + l][j + k] for k, l in cells]
# count crossing how many times it goes from 0 to 1
crossings = 0
for k in range(0, len(values) - 1):
crossings += abs(values[k] - values[k + 1])
crossings //= 2
# if pixel on boundary are crossed with the ridge once, then it is a possible ridge ending
# if pixel on boundary are crossed with the ridge three times, then it is a ridge bifurcation
if crossings == 1:
return "ending"
if crossings == 3:
return "bifurcation"
return "none"
def calculate_minutiaes(im, kernel_size=3):
biniry_image = np.zeros_like(im)
biniry_image[im < 10] = 1.0
biniry_image = biniry_image.astype(np.int8)
(y, x) = im.shape
result = cv.cvtColor(im, cv.COLOR_GRAY2RGB)
colors = {"ending": (150, 0, 0), "bifurcation": (0, 150, 0)}
# iterate each pixel minutia
for i in range(1, x - kernel_size // 2):
for j in range(1, y - kernel_size // 2):
minutiae = minutiae_at(biniry_image, j, i, kernel_size)
if minutiae != "none":
cv.circle(result, (i, j), radius=2, color=colors[minutiae], thickness=2)
return result