File size: 11,124 Bytes
f44deb5
 
 
 
 
 
 
 
d05e237
f44deb5
 
 
 
 
 
 
 
01f469b
f617fda
155d468
 
 
 
 
 
 
 
 
 
3de9bec
 
 
 
 
 
 
 
 
155d468
b77f9a4
 
 
 
 
 
155d468
b77f9a4
 
fb376f7
b77f9a4
fb376f7
372ac15
b77f9a4
 
155d468
372ac15
f617fda
f44deb5
 
f617fda
 
f44deb5
 
550ba90
343d424
b5b572d
690fa46
155d468
 
 
 
 
f44deb5
111bf33
 
 
42d7162
111bf33
 
 
42d7162
 
 
caa845f
2845bbe
 
42d7162
caa845f
42d7162
 
 
111bf33
 
155d468
d77079a
42d7162
f44deb5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2094eae
f44deb5
 
37556ad
e022fa7
f44deb5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
690fa46
 
 
 
 
 
 
636376c
3d1a724
155d468
 
 
373e9d3
 
690fa46
 
 
 
0a45f6e
b085184
 
 
f44deb5
 
 
 
b085184
 
 
 
caa845f
 
b085184
 
 
 
 
 
f44deb5
 
 
 
 
 
b085184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db2f5a0
b085184
1152739
2845bbe
 
3d1a724
 
2845bbe
906e3b6
 
b085184
f44deb5
09ff7b9
f44deb5
b085184
db2f5a0
 
b085184
 
f44deb5
 
 
636376c
d4a35c1
2094eae
3d1a724
 
 
75c82d5
636376c
75c82d5
f44deb5
 
 
 
 
 
 
 
 
78a3e5e
c2f1b87
78a3e5e
e022fa7
ca10428
e022fa7
9bf791d
78a3e5e
 
40d888f
f44deb5
 
9a59f2f
 
f44deb5
 
 
 
 
 
 
 
 
 
 
 
9a59f2f
f44deb5
 
 
636376c
f44deb5
6720b69
f44deb5
 
 
0e2977d
636376c
ec1e3d9
0e2977d
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# -*- coding: utf-8 -*-
"""app.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/1EabZcU6Wk8QL6n0_cXYso4djYWFXPOIJ
"""
 
import numpy as np
import pandas as pd

import tensorflow as tf
from tensorflow import keras
import gradio as gr
from pathlib import Path
import os
import subprocess

# Run the command as a subprocess
def run_subprocess(command,subprocess_result_Q=True):
    print(f'\n{command}\n')
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = process.communicate()
    if subprocess_result_Q:
        # Print the output and errors if any
        print(f"\nOutput: {stdout}\n", )
        print(f"\nErrors: {stderr}\n", )

command = [
    "python",
    "-m",
    "pip",
    "install",
    "--upgrade",
    "pip"
]
run_subprocess(command)

command = [
    "pip",
    "install",
    "transformers"
]
run_subprocess(command)

# !pip install ultralytics
command = [
    "pip3",
    "install",
    "--upgrade",
    "ultralytics"
]
run_subprocess(command)

from ultralytics import YOLO

"""# set up paths"""

# project_path = Path('Fu-Chuen/Fungus_Classification_Genus_Species/tree/main')
project_path = Path('./')
model_path = Path(project_path,'Model')
test_path = Path(project_path,'Test')
os.makedirs(test_path, exist_ok=True)
Yolov8n_path = Path(project_path,'Result/Yolov8n')
os.makedirs(Yolov8n_path, exist_ok=True)
detect_path = Path(project_path,'runs/detect')
weight_path = Path(model_path,'best_Yolo_v8n.pt')
# 指定工作目录
# working_directory = '/home/user/app'
working_directory = os.getcwd()
print(f'\nworking directory: {working_directory}\n')

# 递归获取目录下所有文件
def get_all_files(directory):
    all_files = []
    all_directories = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            all_files.append(os.path.join(root, file))
        for dir in dirs:
            all_directories.append(os.path.join(root, dir))
   # 打印所有文件路径
    print("\n所有的文件:\n")
    for file in all_files:
        print(file)
   # 打印所有文件路径
    print("\n所有的目录:\n")
    for dir in all_directories:
        print(dir)
    return all_files, all_directories

# 列出工作目录及其子目录下的所有文件
# get_all_files(working_directory)


"""# load MobileNet model"""

MobileNet_model = keras.models.load_model(Path(model_path,'MobileNetV3Large_Genus_5th_fold_model'))
genus_labels = ['Aspergillus', "Cladosporium", 'Penicillium', 'Trichophyton', "Others"]

"""# find the most frequent element"""

def most_frequent_element(my_list):

  # Create an empty dictionary to store element frequencies
  element_count = {}

  # Count the occurrences of each element in the list
  for element in my_list:
      if element in element_count:
          element_count[element] += 1
      else:
          element_count[element] = 1

  # Find the element(s) with the highest frequency
  max_frequency = max(element_count.values())
  most_frequent_elements = [element for element, frequency in element_count.items() if frequency == max_frequency]

  # Print the result
  # print("The element(s) with the highest frequency:", most_frequent_elements)
  # print("The highest frequency:", max_frequency)
  return most_frequent_elements, max_frequency

"""# genus classify using MobileNet model"""

def genus_classify_images(files,threshold):
    results = ""
    predict = []
    for i, file_path in enumerate(files):
        print(f'\ngenus_classify_image {i+1}:  {file_path.name} \n')
        try:
            inp = tf.keras.preprocessing.image.load_img(file_path.name, target_size=(224, 224))
            inp = tf.keras.preprocessing.image.img_to_array(inp)
            inp = inp.reshape((-1, 224, 224, 3))
            inp = tf.keras.applications.mobilenet_v3.preprocess_input(inp)
            model, labels = (MobileNet_model,genus_labels)
            prediction = model.predict(inp).flatten()
            confidences = {labels[i]: float(prediction[i]) for i in range(len(labels))}
            top_3 = sorted(confidences.items(), key=lambda x: x[1], reverse=True)[:3]
            predict.append(top_3[0][0])
            results += f"Image {i+1}: Top 3 predictions: {', '.join([f'{label}: {probab:.3f}' for label, probab in top_3])}\n"
        except Exception as e:
            results += f"Image: {file_path.name} - Error: {str(e)}\n"
    ensemble_predict, max_frequency = most_frequent_element(predict)
    predict_result = ensemble_predict[0] if max_frequency/len(files) >= threshold else "Unclassified"
    results = f'Prediction of genus: {predict_result}\n\n' + results

    return predict_result, results

"""# Aspergillus classify and count statistics"""

# 實時偵測 2013-10-05 OK
# --source 偵測圖像路徑
# --save-txt 儲存標籤文件
# --conf 0.25 只保留置信度分數高於0.25的

def delete_files_in_folder(path):
    for root, dirs, files in os.walk(path):
        print(f'root: {root}')
        for file in files:
            print(f'file: {file}')
            file_path = os.path.join(root, file)
            os.remove(file_path)

def find_the_most_recent_predict_path(path):
  path = list(map(lambda x: x.split('/'),path))
  path = [i for i in path if 'predict' in i[-1]]
  # Sort the list by the last element of each inner list
  path = sorted(path, key=lambda x: x[-1])
  return '/'.join(path[-1])
    
def Aspergillus_Detect(threshold):
    # get_all_files(working_directory)
    
    model = YOLO(weight_path)  # pretrained YOLOv8n model

    # model.predict(test_path, save = True , save_txt = True, output_dir = Yolov8n_path )  # predict on an image
    model.predict(test_path, save = True , save_txt = True, )  # predict on an image
    all_files, all_directories = get_all_files(working_directory)

    image_path = Path(find_the_most_recent_predict_path(all_directories))
    label_path = Path(image_path,'labels')
    print('\nmost_recent_predict_path: {image_path}\n')
    
    file_paths = []
    for root, dirs, files in os.walk(label_path):
      for file in files:
          if file.lower().endswith('.jpg'):
              file_path = os.path.join(root, file)
              file_paths.append(file_path)
    
    df_test = pd.DataFrame({'filepath': file_paths})
    
    files = os.listdir(label_path)

    print(f'\nfiles in label_path: {files}\n')
    
    # initialize an empty list to store data
    data = []
    
    # loop through each file and extract the data
    for file in files:
      if file.endswith('.txt'):
          with open(os.path.join(label_path, file), 'r') as f:
              lines = f.readlines()
              for line in lines:
                  line = line.strip().split(' ')
                  data.append([file[:-4], line[0], float(line[1]), float(line[2]), float(line[3]), float(line[4])])
    
    # convert list of data to data frame
    df = pd.DataFrame(data, columns=['image', 'class', 'xmin', 'ymin', 'xmax', 'ymax'])
    # group by labels, count the number of detections for each label
    counts = df.groupby(['image', 'class']).size().reset_index(name='count')
    # add the file name to the data frame
    counts['file'] = counts['image'].apply(lambda x: x + '.jpg')
    
    counts['filepath'] = counts['file'].apply(lambda x: Path(label_path,x))
    
    replace_dict = {'0': 'flavus-oryzae', '1': 'fumigatus', '2': 'niger', '3': 'terreus', '4': 'versicolor'}
    counts['label'] = counts['class'].replace(replace_dict)
    
    # Select only the relevant columns
    counts = counts[['filepath', 'label', 'count']]
    df_pivot = pd.pivot_table(counts, values='count', index=['filepath'], columns='label', aggfunc='sum')
    df_pivot['detect'] = df_pivot.sum(axis=1)
    pd.options.display.float_format = '{:,.0f}'.format
    df_pivot = pd.DataFrame(df_pivot)
    
    total_col = df_pivot.pop('detect')
    df_pivot.insert(0, 'detect', total_col)
    detect_number = round(df_pivot['detect'].sum())
    a = []
    for i in df_pivot.columns[1:]:
        a.append([i,round(df_pivot[i].sum()/detect_number,3)])
    a = sorted(a,key=lambda x: x[1],reverse=True)

    print(f'\na: {a}\n')

    # # 列出工作目录及其子目录下的所有文件
    # get_all_files(working_directory)

    # delete_files_in_folder(image_path)

    result = [f'Prediction of species of Aspergillus: {a[0][0] if a[0][1] >= threshold else "Unclassified"}',
      f'There are {df_pivot.shape[0]} mold images.',
            f'Yolov8n detects {detect_number} instances.',
            f'The top {len(a)} percentage of specifies:']
    for i in a:
        # print(f'i: {i}')
        result.append(f'{i[0]} {i[1]}')
    
    return '\n'.join(result)

"""# classify images: genus and Aspergillus"""

def classify_images(files,threshold):
    print(f'threshold = {threshold}')
    predict, result1 = genus_classify_images(files,threshold)
    # # 列出工作目录及其子目录下的所有文件
    # all_files = get_all_files(working_directory)
            
    if predict == 'Aspergillus':
      result2 = Aspergillus_Detect(threshold)
      return f'{result1}\n\n{result2}'
    return result1

import shutil

def upload_file(files):
    delete_folder(test_path)
    file_paths = []
    for file in files:
        # Save the uploaded image to the 'Test' folder
        file_path = Path(test_path, file.name.split('/')[-1])
        print(f'\nupload_file:{file}, {file.name}, {os.path.abspath(file_path)}\n')
        try:
            shutil.copy(file.name, file_path)
            file_paths.append(file_path)
            print(f"File copied successfully.")
                
        except:
            print("\nError occurred while copying file.\n")
    # print(f'\nfile_paths: {file_paths}\n')
    return file_paths

# # Define the path to the directory you want to delete files from
# directory_path = test_path

# Iterate through all files in the directory and delete them
def delete_folder(directory_path):
  for filename in os.listdir(directory_path):
    file_path = os.path.join(directory_path, filename)
    try:
        if os.path.isfile(file_path) or os.path.islink(file_path):
            os.unlink(file_path)
        elif os.path.isdir(file_path):
            shutil.rmtree(file_path)
    except Exception as e:
        print(f"Failed to delete {file_path}: {e}")
# delete_folder(test_path)

"""# main of gradio"""

# threshold = 0.6
with gr.Blocks() as fungus_classification:
    threshold = gr.Slider(minimum=0.1, maximum=1, step=0.1, value=0.6, label="Threshold", info="Choose between 0.1 and 1")
    image_output = gr.Gallery(label = 'Images of Molds')
    predict_outputs = gr.Textbox(label = 'Prediction Result')
    upload_button = gr.UploadButton("Click to Upload Files", file_types=["image", "video"], file_count="multiple")
    upload_button.upload(upload_file, upload_button, image_output)
    upload_button.upload(classify_images, [upload_button,threshold], predict_outputs)
fungus_classification.launch(share=True, debug=True)
# fungus_classification.launch(share=True, debug=True, enable_queue=True)