a b/segmentation/singleprobjump.py
1
"""
2
Created by: Rishav Raj and Qie Shang Pua, University of New South Wales
3
This program performs image processing to obtain multiple segments of a patient's spine.
4
Input: Ultrasound scans of the patient's back (in png format)
5
Output: 1. Processed Spine Images
6
        2. A csv file that will be fed into registration.py
7
"""
8
9
# Import Packages
10
import os
11
import cv2
12
import glob
13
import math
14
import pandas as pd
15
import cv2
16
import numpy as np
17
import scipy.ndimage
18
import statistics
19
from skimage import data, color
20
import matplotlib.pyplot as plt
21
from skimage.color import rgb2gray
22
from skimage.transform import rescale, resize, downscale_local_mean
23
from timeit import default_timer as timer
24
import sys
25
from skimage.io import imread
26
27
28
# Python Migration of "find_best_path_jumping.m" of MATLAB
29
# Applies Dynamic Programming to calculate the path of least cost.
30
def find_best_path_jumping(curr):
31
    x = 151  # these are hardcoded - should be determined instead.
32
    y = 289
33
34
    # if at end
35
    if curr[1] == y:
36
        curr_cost = 0
37
        cost[int(curr[0]), int(curr[1])] = curr_cost  # Casted into int to access array index
38
        nexts[int(curr[0]), int(curr[1])] = 0
39
        return
40
41
    max_jump = 50
42
    no_cells = max_jump * 2 + 1
43
44
    min_next = [0, 0]
45
    min_cost = math.inf  # inf gives the largest num in float
46
    # print(curr)
47
    # print(int(curr[0]))
48
49
    # calc costs
50
    for i in range(no_cells):
51
52
        # cell no
53
        next = [0, 0]
54
        next[0] = curr[0] + i - max_jump - 1
55
        next[1] = curr[1] + 1
56
        # print(next)
57
58
        # out of bounds
59
        if next[0] < 1 or next[0] > x:
60
            next_cost = math.inf
61
62
        # already calculated
63
        elif cost[int(next[0]), int(next[1])] != math.inf:
64
            next_cost = cost[int(next[0]), int(next[1])]
65
66
        # need to recursively calculate
67
        else:
68
            next_cost = find_best_path_jumping(next)
69
70
        # print(next_cost)
71
        # add penalty if needed
72
        if abs(curr[0] - next[0]) > 2:
73
            if next_cost == None:
74
                next_cost = 0
75
            next_cost = next_cost + 0.2
76
77
        # calculate running min
78
        if next_cost != None and next_cost < min_cost:
79
            min_cost = next_cost
80
            min_next = next[0]
81
82
    # set results
83
84
    # print([int(curr[0]), int(curr[1])])
85
    curr_cost = inv_prob[int(curr[0]), int(curr[1])] + min_cost
86
    cost[int(curr[0]), int(curr[1])] = curr_cost
87
    nexts[int(curr[0]), int(curr[1])] = min_next
88
89
    return curr_cost
90
91
# Python Migration of "get_prob_map.m" of MATLAB
92
# Produces processed image in black and white
93
def get_prob_map(grayscale):
94
95
    # Start prob map as simple intensity
96
    intensity_map = rescale(grayscale, .5, anti_aliasing=False)
97
    intensity_map = np.asarray(intensity_map)
98
    prob_map = intensity_map * 0.5
99
    # print(np.shape(prob_map))
100
101
    # Create probablity map from intensity after gaussian filtering
102
    gausian = cv2.GaussianBlur(prob_map, (5, 5), 5)
103
    gausian = np.asarray(gausian)
104
    # print(np.shape(gausian))
105
106
    num = np.multiply(gausian, prob_map)
107
    den = num + np.multiply((1 - gausian), (1 - prob_map))
108
    prob_map = np.divide(num, den)
109
110
    kernel1 = np.ones((3, 3), np.float32) / 9
111
    kernel1[1][1] = 0.8888889
112
113
    y = 1
114
    x = 1
115
    shadow = np.ones((y, x)) * 0.2
116
    overall_mean = np.mean(np.mean(intensity_map))
117
118
    for i in range(1, x):
119
        j = y
120
        while (j > 0 and (
121
                gausian[j, i] < overall_mean * 1.5 or np.mean(gausian[j - 10:j - 1, i]) < overall_mean * 1.5)):
122
            shadow[j, i] = 0.1
123
            j = j - 1
124
        while (j > 0 and (gausian[j, i] > overall_mean * 1.5) or j > 5 and np.mean(
125
                gausian[j - 5:j - 1, i]) > overall_mean * 1.5):
126
            shadow[j, i] = intensity_map(j, i)
127
            j = j - 1
128
    shadow = cv2.GaussianBlur(shadow, (5, 5), 5)
129
    prob_map = (shadow * prob_map) / (shadow * prob_map + (1 - shadow) * (1 - prob_map))
130
131
    return prob_map
132
133
    k = cv2.waitKey(0) & 0xFF
134
    if k == 27:  # wait for ESC key to exit
135
        cv2.destroyAllWindows()
136
    elif k == ord('s'):  # wait for 's' key to save and exit
137
        cv2.imwrite('prob map of a single scan.png', prob_map)
138
        cv2.destroyAllWindows()
139
140
141
# Main File
142
# Similar to single_line_path.m of MATLAB
143
def main():
144
145
    points = []
146
    images = glob.glob('/Users/puaqieshang/Desktop/Taste of Research/MATLAB code/everything/phantom_images/phantom_3/scan_2/*.png')
147
    images.sort()
148
149
    count = 0
150
    startTime = timer()
151
    for fname in images:
152
        print(f"Image No.{count+1}")
153
        img = cv2.imread(fname)
154
        # im = plt.imread(fname)
155
        # implot = plt.imshow(im)
156
        count = count + 1
157
158
        us_img = img[80:400, 270:850]
159
        gray = cv2.cvtColor(us_img, cv2.COLOR_BGR2GRAY)
160
        # cv2.imshow('gray_image',gray)
161
        # [x, y] = np.shape(gray)
162
        # print(x)
163
        # print(y)
164
        prob_map = get_prob_map(gray)
165
        highlyLikely = 0.05*np.max(prob_map)
166
        np.savetxt("prob_map.csv", prob_map, delimiter=",")
167
        # print(np.shape(prob_map))
168
169
        """
170
        Dynamic Programming Section
171
        global variables are defined below
172
        """
173
        global inv_prob
174
        inv_prob = 0.5 - prob_map
175
        [a, b] = np.shape(prob_map)
176
        start = [np.floor(a/2), 1]
177
        global cost
178
        cost = np.ones([a, b]) * np.Inf
179
        global nexts
180
        nexts = np.ones([a, b]) * -1
181
        find_best_path_jumping(start)
182
183
        # get points on this scan
184
        point_scan = np.zeros([1, b])
185
186
        implot = plt.imshow(prob_map)
187
        # print(start[0])
188
        curr_x = start[0]
189
        for curr_y in range(b):
190
            point_scan[0, curr_y] = curr_x
191
192
            if prob_map[int(curr_x), int(curr_y)] > highlyLikely: #NEED TO CHANGE TO HIGHLY LIKELY!!!!!
193
                # print("helloooooo")
194
                # cv2.circle(gray, (int(curr_y), int(curr_x)), 1, (0, 0, 255), 1)
195
                # append coloured points
196
                plt.scatter(curr_x, curr_y, c='r', s=20)
197
                coloured_pt = [curr_x, curr_y, count * 0.2]
198
                # points = np.concatenate((points, coloured_pt), axis=1)
199
                points.append(coloured_pt)
200
201
            else:
202
                # cv2.circle(gray, (int(curr_y), int(curr_x)), 1, (255, 0, 0), 1)
203
                plt.scatter(curr_x, curr_y, c='b', s=20)
204
205
            curr_x = nexts[int(curr_x), int(curr_y)]
206
207
        plt.show()
208
209
        endTime = timer()
210
        # print(str(endTime - startTime) + " seconds")
211
        print(f"The time taken is {endTime - startTime} seconds")
212
213
    np.savetxt("pls-work.csv", [*zip(*points)], delimiter=",") # Transpose points data and save into csv format
214
215
    key = cv2.waitKey(0) & 0xFF
216
    if key == ord("q"):
217
        cv2.destroyAllWindows()
218
219
220
main()