James106204 commited on
Commit
77fa523
·
verified ·
1 Parent(s): 0685814

Upload folder using huggingface_hub

Browse files
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Nguyễn Việt Hoàng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,3 +1,46 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Brain Tumor Detect
2
+
3
+ Deep learning is a rapidly evolving field with significant implications for medical imaging. Currently, the interpretation of medical images, such as MRI and CT scans, is predominantly performed by radiologists and specialized physicians. However, this interpretation process can sometimes be subjective. Even experienced professionals may face challenges in consistently evaluating scans, for instance, when determining the presence or classifying a tumor solely from visual information. Furthermore, medical experts often need to review large volumes of images, which can lead to fatigue and an increased risk of oversight or errors. Consequently, the need for automation and decision support in this domain is increasingly critical.
4
+
5
+ Traditional machine learning algorithms, such as Support Vector Machines (SVMs), have been employed for tumor detection and classification. However, their effectiveness is often constrained by the assumptions made during manual feature definition, which can result in suboptimal sensitivity and specificity. In contrast, deep learning emerges as an ideal solution because these algorithms can automatically learn complex and hierarchical features directly from raw image data, potentially improving accuracy and objectivity.
6
+
7
+ One of the major challenges in implementing deep learning algorithms in healthcare is the scarcity of high-quality, labeled medical image data, partly due to patient confidentiality concerns and the intensive labor required for accurate annotation.
8
+
9
+ This project focuses on developing a Convolutional Neural Network (CNN) based on the Xception architecture. This network is trained to detect and classify common types of brain tumors (glioma, meningioma, pituitary tumor) along with non-tumor cases from MRI scans. The data used for this project is sourced from the "Brain Tumor MRI Dataset" available on Kaggle.
10
+
11
+ Beyond image classification, this project integrates an AI chatbot, powered by the Gemini API. This chatbot aims to provide initial, general explanations of the classification results, answer users' general questions, and, most importantly, always guide users to consult with specialist doctors for definitive medical diagnoses and advice. The goal is to create a responsible informational support tool that can assist in managing the workload of medical professionals and offer patients an initial, understandable point of reference for their results.
12
+
13
+
14
+ ## Dataset
15
+ download dataset at : https://www.kaggle.com/datasets/masoudnickparvar/brain-tumor-mri-dataset
16
+
17
+ ## How to Use
18
+
19
+ ### 1. Training the Model (Optional)
20
+
21
+ * If you want to retrain the model yourself, you can use the `Trainingmodel.ipynb` notebook.
22
+ * Open this notebook using Jupyter Notebook, JupyterLab, Google Colab, or VS Code.
23
+ * Execute the cells in the notebook to preprocess data, build the model, train it, and save the trained model.
24
+ * Ensure you have access to the necessary dataset.
25
+
26
+ ### 2. Running the Gradio Web Application
27
+
28
+ After completing the setup and having the model file:
29
+ 1. Open a terminal or command prompt in the root directory of the project (where `app.py` is located).
30
+ 2. Activate the virtual environment (if you created one).
31
+ 3. Run the application:
32
+ ```bash
33
+ python app.py
34
+ ```
35
+ 4. The Gradio application will launch and provide a local URL (usually `http://127.0.0.1:7860` or similar). Open this URL in your web browser.
36
+ 5. Upload a brain MRI image to get the classification result and interact with the chatbot.
37
+
38
+ ## Medical Disclaimer
39
+
40
+ ⚠️ **CRITICALLY IMPORTANT NOTE:**
41
+ * This application and the information it provides (including image classification results and chatbot responses) are **FOR REFERENCE AND INITIAL INFORMATIONAL SUPPORT PURPOSES ONLY.**
42
+ * It **IS NOT** a professional medical diagnostic tool and **ABSOLUTELY DOES NOT REPLACE** examination, diagnosis, consultation, and treatment from qualified doctors or medical professionals.
43
+ * All decisions related to health and medical treatment must be made after direct consultation with a specialist doctor.
44
+ * The developer is not responsible for any decisions made based on information from this application.
45
+
46
+
main.py ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import tensorflow as tf
3
+ from PIL import Image
4
+ import numpy as np
5
+ import os
6
+ import google.generativeai as genai
7
+ TF_ENABLE_ONEDNN_OPTS= 3 # Tắt tối ưu hóa OneDNN để tránh lỗi với TensorFlow
8
+
9
+
10
+ # --- Cấu hình ---
11
+ print("Đang cấu hình môi trường...")
12
+ MODEL_PATH = 'xception_brain_tumor_classifier.keras' # Đảm bảo tên file model chính xác
13
+ IMAGE_WIDTH = 299 # Hoặc 224, tùy thuộc vào model của bạn
14
+ IMAGE_HEIGHT = 299 # Hoặc 224, tùy thuộc vào model của bạn
15
+ CLASS_NAMES = ['glioma', 'meningioma', 'notumor', 'pituitary']
16
+ print("Cấu hình đã sẵn sàng.")
17
+ # --- Cấu hình Gemini API ---
18
+ GEMINI_API_KEY = "AIzaSyBz3NDNS5m7R3SLUvIxXk3GaLCxW_PNddM"
19
+ gemini_model = None
20
+ if GEMINI_API_KEY:
21
+ try:
22
+ genai.configure(api_key=GEMINI_API_KEY)
23
+ gemini_model = genai.GenerativeModel('gemini-1.5-flash') # Hoặc model bạn muốn
24
+ print("Gemini model loaded successfully.")
25
+ except Exception as e:
26
+ print(f"Lỗi cấu hình Gemini: {e}. Chatbot sẽ không hoạt động tối ưu.")
27
+ else:
28
+ print("CẢNH BÁO: Biến môi trường GEMINI_API_KEY chưa được đặt. Chatbot sẽ không hoạt động.")
29
+
30
+ # --- Tải Model Keras ---
31
+ keras_model = None
32
+ if os.path.exists(MODEL_PATH):
33
+ try:
34
+ keras_model = tf.keras.models.load_model(MODEL_PATH)
35
+ print("Keras model loaded successfully.")
36
+ except Exception as e:
37
+ print(f"Error loading Keras model: {e}.")
38
+ else:
39
+ print(f"Model file not found at {MODEL_PATH}. Image classification will not work.")
40
+
41
+
42
+ # --- Hàm tiền xử lý ảnh ---
43
+ def preprocess_image(image_pil):
44
+ if image_pil is None: return None
45
+ image_resized = image_pil.resize((IMAGE_WIDTH, IMAGE_HEIGHT))
46
+ image_array = np.array(image_resized)
47
+ if image_array.ndim == 2: image_array = np.stack((image_array,)*3, axis=-1)
48
+ elif image_array.shape[2] == 1: image_array = np.concatenate([image_array]*3, axis=-1)
49
+ elif image_array.shape[2] == 4: image_array = image_array[:, :, :3]
50
+ image_normalized = image_array / 255.0
51
+ return np.expand_dims(image_normalized, axis=0)
52
+
53
+ # --- Hàm xử lý khi tải ảnh lên và bắt đầu chat ---
54
+ def handle_image_analysis_and_start_chat(image_pil, current_chat_state):
55
+ if keras_model is None:
56
+ return {CLASS_NAMES[0]: "N/A (Model không tải được)"}, [(None, "Không thể phân tích ảnh do model Keras chưa được tải.")], current_chat_state, gr.update(visible=False)
57
+ if image_pil is None:
58
+ return None, [(None, "Vui lòng tải ảnh lên trước khi phân tích.")], current_chat_state, gr.update(visible=False)
59
+
60
+ preprocessed_image = preprocess_image(image_pil)
61
+ predictions = keras_model.predict(preprocessed_image)
62
+ confidences = {CLASS_NAMES[i]: float(predictions[0][i]) for i in range(len(CLASS_NAMES))}
63
+
64
+ predicted_class_index = np.argmax(predictions[0])
65
+ predicted_class_name = CLASS_NAMES[predicted_class_index]
66
+
67
+ # Cập nhật trạng thái chat
68
+ new_chat_state = {
69
+ "diagnosis": predicted_class_name,
70
+ "gemini_chat_session": None # Sẽ được tạo khi gửi tin nhắn đầu tiên
71
+ }
72
+ initial_bot_message = ""
73
+
74
+ if gemini_model:
75
+
76
+ new_chat_state["gemini_chat_session"] = gemini_model.start_chat(history=[])
77
+
78
+
79
+ if predicted_class_name == "notumor":
80
+ initial_user_prompt_for_gemini = f"""
81
+ NGỮ CẢNH:
82
+ Bạn sẽ vào vai một bác sĩ chuyên khoa. Mục tiêu của bạn là thông báo và giải thích kết quả MRI não là "{predicted_class_name}" (được hiểu theo ngữ cảnh là không phát hiện khối u) cho bệnh nhân một cách rõ ràng, ngắn gọn, dễ hiểu. Đồng thời, bạn cần đưa ra những lời khuyên y tế tổng quát hữu ích với tư cách là một bác sĩ.
83
+
84
+ NHIỆM VỤ CỦA BẠN (cho tin nhắn đầu tiên này):
85
+
86
+ Báo tin tốt và giải thích: Mở đầu bằng việc xác nhận kết quả MRI là "{predicted_class_name}". Hãy diễn giải một cách tích cực rằng đây là một tin tốt, cho thấy không có dấu hiệu của khối u theo phân tích hình ảnh này.
87
+ Đưa lời khuyên chuyên môn về sức khỏe não bộ: Với vai trò bác sĩ, hãy cung cấp 2-3 lời khuyên cụ thể, thiết thực và dễ áp dụng để người bệnh có thể chủ động duy trì và tăng cường sức khỏe não bộ của mình (ví dụ: nhấn mạnh về chế độ dinh dưỡng tốt cho não, lợi ích của vận động đều đặn, tầm quan trọng của giấc ngủ chất lượng, và các hoạt động kích thích trí não).
88
+ Đặt kết quả trong bối cảnh y tế rộng hơn: Giải thích rằng kết quả MRI (kể cả khi được AI hỗ trợ phân tích) là một công cụ chẩn đoán hình ảnh quan trọng. Tuy nhiên, việc thăm kh��m sức khỏe tổng quát và trao đổi trực tiếp với bác sĩ (như bạn hoặc bác sĩ gia đình của họ) vẫn vô cùng cần thiết để có cái nhìn đầy đủ và chính xác nhất về tình trạng sức khỏe, cũng như để được tư vấn về việc theo dõi sức khỏe định kỳ.
89
+ Khuyến khích tương tác và đặt câu hỏi: Mời người bệnh đặt thêm câu hỏi nếu họ có bất kỳ thắc mắc nào liên quan đến sức khỏe não bộ nói chung, hoặc muốn hiểu rõ hơn về ý nghĩa của kết quả MRI trong bức tranh tổng thể sức khỏe của họ.
90
+ Duy trì giọng điệu: Tự tin, chuyên nghiệp, mang tính thông tin như một bác sĩ, nhưng vẫn cần sự ấm áp, tích cực và dễ tiếp cận.
91
+ HƯỚNG DẪN QUAN TRỌNG CHO VAI TRÒ BÁC SĨ AI NÀY (áp dụng cho mọi tương tác):
92
+
93
+
94
+ Bây giờ, hãy soạn tin nhắn đầu tiên của bạn cho người dùng, bắt đầu từ việc thông báo kết quả MRI là "{predicted_class_name}".
95
+
96
+
97
+ """
98
+ else:
99
+ initial_user_prompt_for_gemini = f"""
100
+
101
+
102
+ Bạn sẽ vào vai một bác sĩ chuyên khoa AI có kiến thức sâu rộng, khả năng giao tiếp xuất sắc, đặc biệt là rất thấu cảm và cẩn trọng khi truyền đạt thông tin nhạy cảm.
103
+
104
+ NGỮ CẢNH BAN ĐẦU:
105
+ Bệnh nhân vừa nhận được kết quả phân tích hình ảnh MRI não từ một công cụ AI. Kết quả phân tích này, được thể hiện qua giá trị {predicted_class_name}, cho thấy có dấu hiệu nghi ngờ một khối u não. Giá trị của {predicted_class_name} ở đây có thể là tên một loại khối u cụ thể mà AI dự đoán (ví dụ: "U màng não", "U tế bào thần kinh đệm") hoặc một mô tả chung hơn về phát hiện đó (ví dụ: "Tổn thương nghi ngờ ác tính", "Phát hiện khối choán chỗ").
106
+
107
+ NHIỆM VỤ CHO TIN NHẮN ĐẦU TIÊN CỦA BẠN (và chỉ tin nhắn này):
108
+ Dựa trên NGỮ CẢNH BAN ĐẦU (kết quả {predicted_class_name} gợi ý có khối u), hãy soạn một tin nhắn đầu tiên gửi cho bệnh nhân. Tin nhắn này phải được thực hiện với sự thận trọng, rõ ràng và thấu cảm tối đa:
109
+
110
+ Thông báo kết quả một cách cẩn trọng và minh bạch:
111
+ Chào bệnh nhân. Bắt đầu bằng cách thông báo một cách nhẹ nhàng nhưng rõ ràng rằng kết quả phân tích hình ảnh MRI não cho thấy có một dấu hiệu cần được các bác sĩ chuyên khoa đánh giá thêm một cách kỹ lưỡng.
112
+ Giải thích rằng dấu hiệu này, được AI xác định là {predicted_class_name}, gợi ý khả năng có sự hiện diện của một khối u.
113
+ Nhấn mạnh ngay lập tức vai trò của đánh giá y tế chuyên sâu:
114
+ Khẳng định mạnh mẽ rằng đây là kết quả phân tích sơ bộ từ một công cụ hỗ trợ AI và TUYỆT ĐỐI KHÔNG PHẢI LÀ CHẨN ĐOÁN Y KHOA CUỐI CÙNG.
115
+ Nhấn mạnh rằng việc chẩn đoán chính xác bản chất của {predicted_class_name}, mức độ nghiêm trọng (nếu có), và việc xác định các bước xử trí tiếp theo phải được thực hiện bởi các bác sĩ chuyên khoa (ví dụ: bác sĩ thần kinh, bác sĩ ung bướu) sau khi họ đã xem xét toàn bộ hồ sơ bệnh án, kết quả MRI gốc và có thể cần thêm các thông tin khác.
116
+ Đưa ra khuyến nghị hành động cụ thể, rõ ràng và khẩn trương:
117
+ Lời khuyên quan trọng nhất: bệnh nhân nên liên hệ ngay và đặt lịch hẹn với bác sĩ đã chỉ định thực hiện MRI này cho họ, hoặc một bác sĩ chuyên khoa Thần kinh hoặc Ung bướu trong thời gian sớm nhất có thể để thảo luận chi tiết về kết quả này.
118
+ Thông báo rằng bác sĩ có thể sẽ cần làm thêm một số xét nghiệm hoặc đánh giá chuyên sâu khác để làm rõ hơn về tình trạng.
119
+ Thể hiện sự đồng hành và hỗ trợ tinh thần ban đầu:
120
+ Thể hiện sự thấu hiểu sâu sắc rằng thông tin này có thể gây ra sự lo lắng hoặc bất ngờ lớn cho bệnh nhân.
121
+ Động viên một cách nhẹ nhàng rằng việc phát hiện sớm các dấu hiệu sẽ giúp các bác sĩ có kế hoạch can thiệp tốt hơn, và y học hiện đại có nhiều tiến bộ. Quan trọng nhất là họ không đơn độc và đội ngũ y tế sẽ hỗ trợ họ. (Tránh đưa ra tiên lượng hay những lời hứa không có cơ sở).
122
+ Mời đặt câu hỏi (mang tính chất tổng quát ban đầu):
123
+ Mời người dùng đặt các câu hỏi tổng quát mà họ có thể có ngay lúc này về ý nghĩa chung của việc có một phát hiện như {predicted_class_name} trên MRI, hoặc các bước thông thường trong quá trình chẩn đoán tiếp theo là gì. Nhấn mạnh rằng những câu hỏi rất cụ thể về trường hợp cá nhân của họ nên được dành cho buổi gặp bác sĩ chuyên khoa.
124
+ Giọng điệu: Phải cực kỳ bình tĩnh, nghiêm túc nhưng đầy thấu cảm và trắc ẩn. Sử dụng ngôn ngữ rõ ràng, trực tiếp nhưng không gây hoảng loạn, và cũng không được làm giảm nhẹ mức độ cần thiết của việc theo dõi y tế chặt chẽ.
125
+ HƯỚNG DẪN TƯƠNG TÁC TIẾP THEO:
126
+ SAU KHI GỬI TIN NHẮN ĐẦU TIÊN Ở TRÊN, BẠN SẼ DỪNG LẠI VÀ CHỜ BỆNH NHÂN ĐẶT CÂU HỎI.
127
+ Khi bệnh nhân đặt câu hỏi, bạn sẽ dựa vào các nguyên tắc và hướng dẫn xử lý câu hỏi dưới đây để trả lời. Mỗi lần chỉ trả lời một câu hỏi hoặc một cụm câu hỏi liên quan của bệnh nhân.
128
+
129
+ Nguyên tắc hoạt động cốt lõi (áp dụng cho toàn bộ cuộc trò chuyện sau tin nhắn đầu tiên):
130
+
131
+ Vai trò Bác sĩ AI (Thận trọng và Hỗ trợ): Bạn là AI mô phỏng bác sĩ, có nhiệm vụ cung cấp thông tin y khoa tổng quát một cách chính xác và hỗ trợ tinh thần. Luôn nhấn mạnh rằng bạn không thể thay thế việc chẩn đoán, tư vấn điều trị và theo dõi trực tiếp từ đội ngũ y bác sĩ chuyên khoa.
132
+ Thông tin Y khoa Tổng quát (Chính xác và Cập nhật): Các thông tin về bệnh lý, xét nghiệm, điều trị phải dựa trên kiến thức y khoa phổ thông, được công nhận và cập nhật. Tránh suy diễn hoặc thông tin không có cơ sở.
133
+ Luôn hướng đến Hành động Y tế Chính thống: Mọi lời khuyên phải tập trung vào việc khuyến khích bệnh nhân tuân thủ theo hướng dẫn của bác sĩ điều trị và hệ thống y tế chính thống.
134
+ Giao tiếp Thấu cảm và Kiên nhẫn: Sử dụng ngôn ngữ Tiếng Việt đơn giản, dễ hiểu. Luôn thể hiện sự kiên nhẫn, thấu cảm sâu sắc với những lo lắng, sợ hãi hoặc các cảm xúc khác của bệnh nhân.
135
+ Hướng dẫn Xử lý Cụ thể cho Các Câu hỏi TIẾP THEO của Bệnh nhân (trong bối cảnh có dấu hiệu khối u {predicted_class_name}):
136
+
137
+ A. NẾU Bệnh nhân hỏi về ý nghĩa của kết quả {predicted_class_name} hoặc các thuật ngữ liên quan:
138
+ (Ví dụ: "Bác sĩ nói rõ hơn về {predicted_class_name} được không?", "Kết quả này có chắc chắn là ung thư không?")
139
+
140
+ Cách tiếp cận (Bác sĩ AI): Giải thích {predicted_class_name} là gì dựa trên thuật ngữ y khoa tổng quát (ví dụ, nếu đó là "u màng não", bạn có thể giải thích chung về u màng não là gì). Nhấn mạnh lại đây là mô tả hình ảnh ban đầu, không phải chẩn đoán bệnh xác định. Tuyệt đối không xác nhận hay phủ định việc đó có phải là ung thư hay không nếu {predicted_class_name} không phải là một chẩn đoán mô bệnh học. Nhấn mạnh chỉ có bác sĩ sau khi làm thêm xét nghiệm (có thể bao gồm sinh thiết) mới kết luận được bản chất chính xác.
141
+ B. NẾU Bệnh nhân hỏi về thông tin tổng quát của loại khối u được gợi ý bởi {predicted_class_name}:
142
+ (Ví dụ: "Nếu đây là {predicted_class_name}, thì nó nguy hiểm như thế nào?", "Bệnh {predicted_class_name} thường có triệu chứng gì?")
143
+
144
+ Cách tiếp cận (Bác sĩ AI): Cung cấp thông tin tổng quát, khách quan về loại khối u đó (ví dụ: bản chất thường gặp, vị trí, đặc điểm chung, các triệu chứng có thể gặp do vị trí hoặc ảnh hưởng của khối u). Hết sức cẩn trọng, không được ám chỉ tiên lượng cá nhân. Luôn kèm theo lời nhắc thông tin này là chung, và tiên lượng cũng như diễn biến ở mỗi người là khác nhau, cần bác sĩ đánh giá cụ thể.
145
+ C. NẾU Bệnh nhân hỏi về các bước nên làm tiếp theo hoặc các xét nghiệm khác:
146
+ (Ví dụ: "Vậy tôi phải làm gì ngay bây giờ?", "Bác sĩ của tôi sẽ cho làm xét nghiệm gì tiếp?")
147
+
148
+ Cách tiếp cận (Bác sĩ AI): Nhắc lại lời khuyên quan trọng nhất là gặp bác sĩ chuyên khoa. Có thể mô tả các loại xét nghiệm ho��c quy trình chẩn đoán phổ biến mà bác sĩ có thể chỉ định trong trường hợp nghi ngờ khối u não (ví dụ: MRI chuyên sâu hơn với thuốc cản quang, CT ngực bụng để tìm nguồn gốc nếu nghi ngờ di căn, PET-CT, xét nghiệm máu tìm dấu ấn ung thư, và đặc biệt là sinh thiết não) để bệnh nhân có sự chuẩn bị tinh thần, nhưng không khẳng định họ chắc chắn sẽ phải làm gì.
149
+ D. NẾU Bệnh nhân hỏi những câu hỏi rất cụ thể về tình trạng cá nhân của họ (tiên lượng, kế hoạch điều trị, "tôi có bị X không?"):
150
+ (Ví dụ: "Vậy tôi có bị ung thư giai đoạn cuối không?", "Tôi còn bao nhiêu thời gian?", "Phương pháp điều trị tốt nhất cho {predicted_class_name} của tôi là gì?")
151
+
152
+ Cách tiếp cận (Bác sĩ AI): Thể hiện sự đồng cảm sâu sắc với nỗi lo của bệnh nhân. Dứt khoát và rõ ràng trả lời rằng bạn không thể cung cấp những thông tin mang tính cá nhân cao và chuyên sâu như vậy. Giải thích rằng tiên lượng và kế hoạch điều trị phụ thuộc vào rất nhiều yếu tố (loại u chính xác sau sinh thiết, giai đoạn, kích thước, vị trí, đột biến gen, thể trạng bệnh nhân...) và chỉ có đội ngũ bác sĩ điều trị trực tiếp sau khi có đầy đủ thông tin mới có thể thảo luận được.
153
+ E. NẾU Bệnh nhân hỏi về các thay đổi lối sống hoặc các nguồn hỗ trợ:
154
+ (Ví dụ: "Tôi có nên ăn uống gì đặc biệt để chống lại khối u không?", "Tôi có thể tìm sự hỗ trợ ở đâu khi nhận được tin này?")
155
+
156
+ Cách tiếp cận (Bác sĩ AI): Khuyến khích duy trì một lối sống lành mạnh chung (dinh dưỡng tốt, nghỉ ngơi đầy đủ, vận động nhẹ nhàng nếu sức khỏe cho phép) để hỗ trợ sức khỏe tổng thể, nhưng nhấn mạnh nó không phải là phương pháp điều trị khối u và không thay thế các can thiệp y khoa. Hướng dẫn các nguồn tìm kiếm sự hỗ trợ tâm lý, các nhóm bệnh nhân có cùng chẩn đoán (sau khi có chẩn đoán chính thức từ bác sĩ), hoặc các tổ chức tư vấn ung thư uy tín.
157
+ G. NẾU Bệnh nhân bày tỏ cảm xúc mạnh (sợ hãi, tuyệt vọng, tức giận, hoang mang):
158
+ (Ví dụ: "Tôi quá sợ hãi và không biết làm gì cả.", "Tại sao chuyện này lại xảy ra với tôi?", "Tôi không muốn tin đây là sự thật.")
159
+
160
+ Cách tiếp cận (Bác sĩ AI): Dành không gian cho bệnh nhân bày tỏ cảm xúc. Sử dụng ngôn ngữ thể hiện sự lắng nghe chủ động, đồng cảm sâu sắc và chấp nhận những cảm xúc đó ("Tôi hiểu rằng bạn đang cảm thấy vô cùng [nêu cảm xúc của họ] và đó là điều hoàn toàn tự nhiên trong tình huống này...", "Việc bạn cảm thấy... cho thấy bạn đang đối diện với một thông tin rất khó khăn."). Không cố gắng đưa ra giải pháp ngay cho cảm xúc, mà khuyến khích họ chia sẻ với người thân tin cậy, tìm kiếm sự hỗ trợ từ chuyên gia tâm lý nếu cần, và nhắc họ rằng việc trao đổi cởi mở với bác sĩ điều trị sẽ giúp họ có thông tin rõ ràng hơn để đối diện và đưa ra quyết định.
161
+ Lưu ý quan trọng về văn phong và kết thúc (áp dụng cho mọi câu trả lời sau tin nhắn đầu tiên):
162
+ Văn phong của bạn phải luôn thể hiện sự bình tĩnh, chuyên nghiệp, thấu hiểu sâu sắc và đáng tin cậy.
163
+ Sau khi trả lời câu hỏi của bệnh nhân, LUÔN KẾT THÚC bằng một lời nhắc nhở rõ ràng và mạnh mẽ về việc bệnh nhân cần tham vấn trực tiếp với bác sĩ chuyên khoa của họ để được đánh giá tình trạng cá nhân một cách toàn diện, nhận chẩn đoán chính xác và thảo luận về kế hoạch chăm sóc điều trị phù hợp nhất với bản thân. (Lưu ý: Tin nhắn đầu tiên đã có hướng dẫn riêng về việc nhắc nhở này).
164
+
165
+ Bây giờ, hãy bắt đầu bằng cách soạn tin nhắn đầu tiên cho bệnh nhân dựa trên NGỮ CẢNH BAN ĐẦU và NHIỆM VỤ CHO TIN NHẮN ĐẦU TIÊN."""
166
+ try:
167
+ response = new_chat_state["gemini_chat_session"].send_message(initial_user_prompt_for_gemini)
168
+ initial_bot_message = response.text
169
+ except Exception as e:
170
+ print(f"Lỗi khi gửi tin nhắn đầu tiên đến Gemini: {e}")
171
+ initial_bot_message = "Xin lỗi, tôi không thể khởi tạo cuộc trò chuyện vào lúc này."
172
+
173
+ else:
174
+ initial_bot_message = "Chatbot hiện không khả dụng do lỗi cấu hình API."
175
+
176
+ # Hiển thị box chat và tin nhắn đầu tiên
177
+ return confidences, [(None, initial_bot_message)], new_chat_state, gr.update(visible=True)
178
+
179
+
180
+ # --- Hàm xử lý khi người dùng gửi tin nhắn chat ---
181
+ def handle_user_chat_message(user_message, chat_history, chat_state):
182
+ if not user_message.strip(): # Bỏ qua nếu tin nhắn trống
183
+ return chat_history, chat_state
184
+
185
+ if chat_state is None or "gemini_chat_session" not in chat_state or chat_state["gemini_chat_session"] is None:
186
+ chat_history.append((user_message, "Lỗi: Phiên chat chưa được khởi tạo. Vui lòng phân tích ảnh trước."))
187
+ return chat_history, chat_state
188
+
189
+ # Thêm tin nhắn của người dùng vào lịch sử hiển thị
190
+ chat_history.append((user_message, None)) # Placeholder cho phản hồi của bot
191
+
192
+ # Gửi tin nhắn đến Gemini
193
+ gemini_chat_session = chat_state["gemini_chat_session"]
194
+ bot_response_text = ""
195
+ try:
196
+ # Prompt có thể cần thêm ngữ cảnh về chẩn đoán ban đầu nếu cần,
197
+ # nhưng ChatSession của Gemini nên tự quản lý lịch sử.
198
+ # contextual_user_message = f"Based on the initial finding of '{chat_state.get('diagnosis', 'unknown')}', the user asks: {user_message}"
199
+ # response = gemini_chat_session.send_message(contextual_user_message)
200
+ response = gemini_chat_session.send_message(user_message) # Gửi thẳng tin nhắn người dùng
201
+ bot_response_text = response.text
202
+ except Exception as e:
203
+ print(f"Lỗi khi gửi tin nhắn đến Gemini: {e}")
204
+ bot_response_text = "Xin lỗi, tôi gặp sự cố khi xử lý yêu cầu của bạn."
205
+
206
+ # Cập nhật tin nhắn cuối cùng trong lịch sử với phản hồi của bot
207
+ chat_history[-1] = (user_message, bot_response_text)
208
+
209
+ # Trạng thái chat_state (đặc biệt là gemini_chat_session) được cập nhật nội bộ
210
+ return chat_history, chat_state
211
+
212
+
213
+ # --- Xây dựng giao diện Gradio ---
214
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
215
+ gr.Markdown(
216
+ """
217
+ <div style='text-align: center;'>
218
+ <h1>🧠 Phân Loại Khối U Não & Chatbot Gợi Ý Y Tế</h1>
219
+ </div>
220
+ Tải lên ảnh MRI não để phân loại khối u. Sau đó, bạn có thể trò chuyện với chatbot để hỏi thêm thông tin.
221
+ **LƯU Ý CỰC KỲ QUAN TRỌNG:** Thông tin từ chatbot **KHÔNG PHẢI** là chẩn đoán y khoa và **KHÔNG THAY THẾ** tư vấn từ bác sĩ chuyên nghiệp.
222
+ Luôn tham khảo ý kiến bác sĩ để có thông tin chính xác và kế hoạch chăm sóc sức khỏe phù hợp.
223
+ """
224
+ )
225
+
226
+ # Biến trạng thái để lưu trữ thông tin giữa các lần tương tác
227
+ # diagnosis: kết quả chẩn đoán từ model Keras
228
+ # gemini_chat_session: đối tượng chat session của Gemini
229
+ app_state = gr.State({"diagnosis": None, "gemini_chat_session": None})
230
+
231
+ with gr.Row():
232
+ with gr.Column(scale=2):
233
+ input_image = gr.Image(type="pil", label="1. Tải lên ảnh MRI não")
234
+ analyze_button = gr.Button("🔬 Phân tích ảnh & Bắt đầu Chat", variant="primary")
235
+ output_prediction = gr.Label(label="Kết quả phân loại (Keras Model)")
236
+ gr.Markdown("### Ảnh MRI minh họa") # Tiêu đề nhỏ cho phần ảnh
237
+
238
+ # Đường dẫn đến thư mục chứa ảnh tĩnh
239
+ STATIC_IMAGE_DIR = "static_mri_examples" # Đảm bảo thư mục này tồn tại cùng cấp file .py hoặc cung cấp đường dẫn tuyệt đối
240
+
241
+ # Danh sách các tệp ảnh (đảm bảo tên tệp chính xác)
242
+ example_image_files = [
243
+ os.path.join(STATIC_IMAGE_DIR, "Te-gl_0012.jpg"),
244
+ os.path.join(STATIC_IMAGE_DIR, "Te-meTr_0002.jpg"),
245
+ os.path.join(STATIC_IMAGE_DIR, "Te-noTr_0000.jpg"),
246
+ os.path.join(STATIC_IMAGE_DIR, "Te-piTr_0007.jpg")
247
+ ]
248
+ # Kiểm tra xem các tệp ảnh có tồn tại không
249
+ existing_images = [img_path for img_path in example_image_files if os.path.exists(img_path)]
250
+
251
+ if len(existing_images) == 4:
252
+ # Sử dụng gr.update() để set giá trị ban đầu cho Gallery sau khi Blocks được định nghĩa
253
+ gallery_value = existing_images
254
+ else:
255
+ print(f"Cảnh báo: Không tìm thấy đủ 4 ảnh trong thư mục '{STATIC_IMAGE_DIR}'. Tìm thấy: {len(existing_images)} ảnh.")
256
+ print(f"Các ảnh không tìm thấy: {[p for p in example_image_files if not os.path.exists(p)]}")
257
+ # Có thể hiển thị ảnh placeholder hoặc không hiển thị gì cả
258
+ gallery_value = existing_images # Sẽ chỉ hiển thị những ảnh tìm thấy
259
+
260
+ # Nếu muốn Gallery luôn có slot cho 4 ảnh, kể cả khi file không tồn tại (sẽ hiển thị lỗi ảnh)
261
+ # thì dùng example_image_files trực tiếp, nhưng tốt hơn là kiểm tra file
262
+ if gallery_value: # Chỉ hiển thị gallery nếu có ít nhất 1 ảnh
263
+ gr.Gallery(
264
+ value=gallery_value,
265
+ label="4 Ảnh MRI Minh Họa",
266
+ columns=2, # Hiển thị 2 ảnh trên một hàng (tổng 2 hàng) hoặc 4 để 4 ảnh trên 1 hàng
267
+ object_fit="contain", # hoặc "cover"
268
+ height="auto" # Tự động điều chỉnh chiều cao
269
+ )
270
+ else:
271
+ gr.Markdown("<p style='color:orange;'>Không thể tải ảnh minh họa. Vui lòng kiểm tra đường dẫn và tên tệp.</p>")
272
+ with gr.Column(scale=1):
273
+ gr.Markdown("### 💬 Trò chuyện với Chatbot Y Tế")
274
+ # Ẩn vùng chat ban đầu, chỉ hiện sau khi phân tích ảnh
275
+ with gr.Group(visible=False) as chat_interface_group:
276
+ chatbot_display = gr.Chatbot(label="Chatbot", height=400)
277
+ user_chat_input = gr.Textbox(label="Nhập câu hỏi của bạn:", placeholder="Hỏi tôi về thông tin chung liên quan đến kết quả...")
278
+ send_button = gr.Button("✉️ Gửi")
279
+
280
+ gr.Markdown(
281
+ "<p style='text-align:center; color:red; font-weight:bold;'>Chatbot chỉ cung cấp thông tin tham khảo. Luôn hỏi ý kiến bác sĩ!</p>"
282
+ )
283
+
284
+ # Kết nối các hành động
285
+ analyze_button.click(
286
+ fn=handle_image_analysis_and_start_chat,
287
+ inputs=[input_image, app_state],
288
+ outputs=[output_prediction, chatbot_display, app_state, chat_interface_group]
289
+ )
290
+
291
+ # Xử lý khi người dùng gửi tin nhắn trong textbox (nhấn Enter)
292
+ user_chat_input.submit(
293
+ fn=handle_user_chat_message,
294
+ inputs=[user_chat_input, chatbot_display, app_state],
295
+ outputs=[chatbot_display, app_state]
296
+ ).then(lambda: "", outputs=[user_chat_input]) # Xóa textbox sau khi gửi
297
+
298
+ # Xử lý khi người dùng nhấn nút "Gửi"
299
+ send_button.click(
300
+ fn=handle_user_chat_message,
301
+ inputs=[user_chat_input, chatbot_display, app_state],
302
+ outputs=[chatbot_display, app_state]
303
+ ).then(lambda: "", outputs=[user_chat_input]) # Xóa textbox sau khi gửi
304
+
305
+
306
+ if __name__ == "__main__":
307
+ if keras_model is None:
308
+ print("Không thể khởi chạy ứng dụng do model Keras chưa được tải.")
309
+ elif gemini_model is None:
310
+ print("Khởi chạy ứng dụng, nhưng chatbot Gemini sẽ không hoạt động do API key chưa được cấu hình hoặc có lỗi.")
311
+ demo.launch()
312
+ else:
313
+ demo.launch()
model_evaluation.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import seaborn as sns
4
+ from sklearn.metrics import confusion_matrix, classification_report, roc_curve, auc, precision_score, f1_score, recall_score
5
+ import pandas as pd
6
+ from tensorflow.keras.models import load_model
7
+ import argparse
8
+
9
+ def plot_confusion_matrix(y_true, y_pred, classes):
10
+ """
11
+ Vẽ ma trận nhầm lẫn
12
+ """
13
+ cm = confusion_matrix(y_true, y_pred)
14
+ plt.figure(figsize=(10, 8))
15
+ sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
16
+ xticklabels=classes, yticklabels=classes)
17
+ plt.title('Ma trận nhầm lẫn')
18
+ plt.ylabel('Nhãn thực tế')
19
+ plt.xlabel('Nhãn dự đoán')
20
+ plt.savefig('confusion_matrix.png')
21
+ plt.close()
22
+
23
+ def plot_roc_curve(y_true, y_pred_proba, classes):
24
+ """
25
+ Vẽ đường cong ROC
26
+ """
27
+ plt.figure(figsize=(10, 8))
28
+ for i, class_name in enumerate(classes):
29
+ fpr, tpr, _ = roc_curve(y_true == i, y_pred_proba[:, i])
30
+ roc_auc = auc(fpr, tpr)
31
+ plt.plot(fpr, tpr, label=f'{class_name} (AUC = {roc_auc:.2f})')
32
+
33
+ plt.plot([0, 1], [0, 1], 'k--')
34
+ plt.xlim([0.0, 1.0])
35
+ plt.ylim([0.0, 1.05])
36
+ plt.xlabel('Tỷ lệ dương tính giả')
37
+ plt.ylabel('Tỷ lệ dương tính thật')
38
+ plt.title('Đường cong ROC')
39
+ plt.legend(loc="lower right")
40
+ plt.savefig('roc_curve.png')
41
+ plt.close()
42
+
43
+ def plot_training_history(history):
44
+ """
45
+ Vẽ đồ thị quá trình huấn luyện
46
+ """
47
+ plt.figure(figsize=(12, 4))
48
+
49
+ # Vẽ đồ thị loss
50
+ plt.subplot(1, 2, 1)
51
+ plt.plot(history.history['loss'], label='Training Loss')
52
+ plt.plot(history.history['val_loss'], label='Validation Loss')
53
+ plt.title('Loss trong quá trình huấn luyện')
54
+ plt.xlabel('Epoch')
55
+ plt.ylabel('Loss')
56
+ plt.legend()
57
+
58
+ # Vẽ đồ thị accuracy
59
+ plt.subplot(1, 2, 2)
60
+ plt.plot(history.history['accuracy'], label='Training Accuracy')
61
+ plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
62
+ plt.title('Accuracy trong quá trình huấn luyện')
63
+ plt.xlabel('Epoch')
64
+ plt.ylabel('Accuracy')
65
+ plt.legend()
66
+
67
+ plt.tight_layout()
68
+ plt.savefig('training_history.png')
69
+ plt.close()
70
+
71
+ def plot_metrics_bar(y_true, y_pred, classes):
72
+ """
73
+ Vẽ biểu đồ cột cho các chỉ số Precision, Recall và F1-score
74
+ """
75
+ precision = precision_score(y_true, y_pred, average=None)
76
+ recall = recall_score(y_true, y_pred, average=None)
77
+ f1 = f1_score(y_true, y_pred, average=None)
78
+
79
+ metrics = np.vstack((precision, recall, f1))
80
+
81
+ plt.figure(figsize=(12, 6))
82
+ x = np.arange(len(classes))
83
+ width = 0.25
84
+
85
+ plt.bar(x - width, precision, width, label='Precision')
86
+ plt.bar(x, recall, width, label='Recall')
87
+ plt.bar(x + width, f1, width, label='F1-score')
88
+
89
+ plt.xlabel('Classes')
90
+ plt.ylabel('Scores')
91
+ plt.title('Precision, Recall và F1-score cho từng lớp')
92
+ plt.xticks(x, classes, rotation=45)
93
+ plt.legend()
94
+ plt.tight_layout()
95
+ plt.savefig('metrics_bar.png')
96
+ plt.close()
97
+
98
+ def evaluate_model(model, X_test, y_test, classes, history=None):
99
+ """
100
+ Đánh giá mô hình và vẽ các sơ đồ
101
+ """
102
+ # Dự đoán
103
+ y_pred = model.predict(X_test)
104
+ y_pred_classes = np.argmax(y_pred, axis=1)
105
+ y_true = np.argmax(y_test, axis=1)
106
+
107
+ # In báo cáo phân loại
108
+ print("\nBáo cáo phân loại:")
109
+ print(classification_report(y_true, y_pred_classes, target_names=classes))
110
+
111
+ # Tính toán các chỉ số
112
+ precision = precision_score(y_true, y_pred_classes, average=None)
113
+ recall = recall_score(y_true, y_pred_classes, average=None)
114
+ f1 = f1_score(y_true, y_pred_classes, average=None)
115
+
116
+ # In các chỉ số chi tiết
117
+ print("\nChi tiết các chỉ số cho từng lớp:")
118
+ for i, class_name in enumerate(classes):
119
+ print(f"\n{class_name}:")
120
+ print(f"Precision: {precision[i]:.4f}")
121
+ print(f"Recall: {recall[i]:.4f}")
122
+ print(f"F1-score: {f1[i]:.4f}")
123
+
124
+ # Vẽ ma trận nhầm lẫn
125
+ plot_confusion_matrix(y_true, y_pred_classes, classes)
126
+
127
+ # Vẽ đường cong ROC
128
+ plot_roc_curve(y_true, y_pred, classes)
129
+
130
+ # Vẽ biểu đồ các chỉ số
131
+ plot_metrics_bar(y_true, y_pred_classes, classes)
132
+
133
+ # Vẽ đồ thị quá trình huấn luyện nếu có
134
+ if history is not None:
135
+ plot_training_history(history)
136
+
137
+ # Tính toán và in các metric
138
+ accuracy = np.mean(y_pred_classes == y_true)
139
+ print(f"\nĐộ chính xác tổng thể: {accuracy:.4f}")
140
+
141
+ # Lưu kết quả vào file
142
+ results = {
143
+ 'accuracy': accuracy,
144
+ 'precision': precision,
145
+ 'recall': recall,
146
+ 'f1_score': f1,
147
+ 'classification_report': classification_report(y_true, y_pred_classes, target_names=classes, output_dict=True)
148
+ }
149
+
150
+ # Chuyển đổi kết quả thành DataFrame và lưu
151
+ metrics_df = pd.DataFrame({
152
+ 'Class': classes,
153
+ 'Precision': precision,
154
+ 'Recall': recall,
155
+ 'F1-score': f1
156
+ })
157
+ metrics_df.to_csv('detailed_metrics.csv', index=False)
158
+
159
+ results_df = pd.DataFrame(results['classification_report']).transpose()
160
+ results_df.to_csv('model_evaluation_results.csv')
161
+
162
+ return results
163
+
164
+ if __name__ == "__main__":
165
+ # Tạo parser để nhận tham số từ command line
166
+ parser = argparse.ArgumentParser(description='Đánh giá mô hình phân loại khối u não')
167
+ parser.add_argument('--model_path', type=str, required=True, help='Đường dẫn đến file model (.keras)')
168
+ parser.add_argument('--test_data', type=str, required=True, help='Đường dẫn đến file dữ liệu test (.npy)')
169
+ parser.add_argument('--test_labels', type=str, required=True, help='Đường dẫn đến file nhãn test (.npy)')
170
+ parser.add_argument('--history', type=str, help='Đường dẫn đến file lịch sử huấn luyện (.npy)')
171
+
172
+ args = parser.parse_args()
173
+
174
+ # Load model
175
+ print(f"Đang tải model từ {args.model_path}...")
176
+ model = load_model(args.model_path)
177
+
178
+ # Load dữ liệu test
179
+ print(f"Đang tải dữ liệu test từ {args.test_data}...")
180
+ X_test = np.load(args.test_data)
181
+ y_test = np.load(args.test_labels)
182
+
183
+ # Load lịch sử huấn luyện nếu có
184
+ history = None
185
+ if args.history:
186
+ print(f"Đang tải lịch sử huấn luyện từ {args.history}...")
187
+ history = np.load(args.history, allow_pickle=True).item()
188
+
189
+ # Đánh giá mô hình
190
+ print("Bắt đầu đánh giá mô hình...")
191
+ results = evaluate_model(
192
+ model=model,
193
+ X_test=X_test,
194
+ y_test=y_test,
195
+ classes=['glioma', 'meningioma', 'notumor', 'pituitary'],
196
+ history=history
197
+ )
198
+
199
+ print("\nĐánh giá hoàn tất! Các kết quả đã được lưu vào:")
200
+ print("- confusion_matrix.png")
201
+ print("- roc_curve.png")
202
+ print("- metrics_bar.png")
203
+ print("- detailed_metrics.csv")
204
+ print("- model_evaluation_results.csv")
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio
2
+ tensorflow
3
+ Pillow
4
+ numpy
5
+ google-generativeai
static_mri_examples/Te-gl_0012.jpg ADDED
static_mri_examples/Te-meTr_0002.jpg ADDED
static_mri_examples/Te-noTr_0000.jpg ADDED
static_mri_examples/Te-piTr_0007.jpg ADDED