Spaces:
Sleeping
Sleeping
datnguyentien204
commited on
Commit
•
8e0b903
1
Parent(s):
b766711
Upload 338 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +14 -35
- 004f33259ee4aef671c2b95d54e4be68.png +0 -0
- Database/student_attendance.db +0 -0
- Database/test_db.py +24 -0
- Dockerfile +27 -0
- README.md +12 -10
- a.png +3 -0
- a.txt +30 -0
- app.py +74 -0
- cam_result.png +3 -0
- chestXray14/__init__.py +7 -0
- chestXray14/__pycache__/__init__.cpython-310.pyc +0 -0
- chestXray14/__pycache__/chestXray_utils.cpython-310.pyc +0 -0
- chestXray14/__pycache__/chexnet.cpython-310.pyc +0 -0
- chestXray14/__pycache__/constant.cpython-310.pyc +0 -0
- chestXray14/__pycache__/heatmap.cpython-310.pyc +0 -0
- chestXray14/__pycache__/layers.cpython-310.pyc +0 -0
- chestXray14/__pycache__/test.cpython-310.pyc +0 -0
- chestXray14/__pycache__/unet.cpython-310.pyc +0 -0
- chestXray14/cam_result.png +3 -0
- chestXray14/chestXray_utils.py +35 -0
- chestXray14/chexnet.py +67 -0
- chestXray14/constant.py +58 -0
- chestXray14/heatmap.py +38 -0
- chestXray14/layers.py +104 -0
- chestXray14/models/Model.ipynb +287 -0
- chestXray14/models/__pycache__/densenet.cpython-310.pyc +0 -0
- chestXray14/models/densenet.py +71 -0
- chestXray14/models/dpn.py +52 -0
- chestXray14/models/inception.py +91 -0
- chestXray14/models/nasnet.py +73 -0
- chestXray14/models/resnet.py +57 -0
- chestXray14/models/resnext.py +48 -0
- chestXray14/models/senet.py +61 -0
- chestXray14/segment_result.png +3 -0
- chestXray14/test.py +93 -0
- chestXray14/unet.h5 +3 -0
- chestXray14/unet.py +142 -0
- chexnet.h5 +3 -0
- config.yaml +38 -0
- face_recognition_dynamic.gif +3 -0
- faiss_index/index.faiss +0 -0
- faiss_index/index.pkl +0 -0
- image_to_3D/3d_model_requirements.txt +14 -0
- image_to_3D/__init__.py +12 -0
- image_to_3D/__pycache__/__init__.cpython-310.pyc +0 -0
- image_to_3D/__pycache__/__init__.cpython-39.pyc +0 -0
- image_to_3D/__pycache__/attention.cpython-310.pyc +0 -0
- image_to_3D/__pycache__/attention.cpython-39.pyc +0 -0
- image_to_3D/__pycache__/basic_transformer_block.cpython-310.pyc +0 -0
.gitattributes
CHANGED
@@ -1,35 +1,14 @@
|
|
1 |
-
*.
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
1 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
2 |
+
a.png filter=lfs diff=lfs merge=lfs -text
|
3 |
+
cam_result.png filter=lfs diff=lfs merge=lfs -text
|
4 |
+
face_recognition_dynamic.gif filter=lfs diff=lfs merge=lfs -text
|
5 |
+
medicalDocuments/chan-doan-va-dieu-tri-benh-phoi-tac-nghen-man-tinh-copd-2018.pdf filter=lfs diff=lfs merge=lfs -text
|
6 |
+
model.ckpt filter=lfs diff=lfs merge=lfs -text
|
7 |
+
pages/images/segment_result.png filter=lfs diff=lfs merge=lfs -text
|
8 |
+
pages/output_yolov9/temp_image.png filter=lfs diff=lfs merge=lfs -text
|
9 |
+
segment_result.png filter=lfs diff=lfs merge=lfs -text
|
10 |
+
temp_image_3d.stl filter=lfs diff=lfs merge=lfs -text
|
11 |
+
temp_image.png filter=lfs diff=lfs merge=lfs -text
|
12 |
+
visualize_x3d/Eiffel_tower_sample.stl filter=lfs diff=lfs merge=lfs -text
|
13 |
+
yolov9/figure/multitask.png filter=lfs diff=lfs merge=lfs -text
|
14 |
+
yolov9/yolov9_vinbigData.pt filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
004f33259ee4aef671c2b95d54e4be68.png
ADDED
Database/student_attendance.db
ADDED
Binary file (20.5 kB). View file
|
|
Database/test_db.py
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sqlite3
|
2 |
+
|
3 |
+
# Đường dẫn đến file cơ sở dữ liệu
|
4 |
+
db_path = 'student_attendance.db'
|
5 |
+
|
6 |
+
# Kết nối tới cơ sở dữ liệu
|
7 |
+
conn = sqlite3.connect(db_path)
|
8 |
+
|
9 |
+
# Tạo con trỏ để thực hiện các truy vấn SQL
|
10 |
+
cursor = conn.cursor()
|
11 |
+
|
12 |
+
# Thực hiện truy vấn SQL, ví dụ để lấy tất cả các bảng trong cơ sở dữ liệu
|
13 |
+
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
|
14 |
+
|
15 |
+
# Lấy kết quả
|
16 |
+
tables = cursor.fetchall()
|
17 |
+
|
18 |
+
# In danh sách các bảng
|
19 |
+
print("Danh sách các bảng trong cơ sở dữ liệu:")
|
20 |
+
for table in tables:
|
21 |
+
print(table[0])
|
22 |
+
|
23 |
+
# Đóng kết nối khi không còn sử dụng
|
24 |
+
conn.close()
|
Dockerfile
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.8.9
|
2 |
+
|
3 |
+
WORKDIR /app
|
4 |
+
|
5 |
+
COPY ./requirements.txt /app/requirements.txt
|
6 |
+
COPY ./packages.txt /app/packages.txt
|
7 |
+
|
8 |
+
RUN apt-get update && xargs -r -a /app/packages.txt apt-get install -y && rm -rf /var/lib/apt/lists/*
|
9 |
+
RUN pip3 install --no-cache-dir -r /app/requirements.txt
|
10 |
+
|
11 |
+
# User
|
12 |
+
RUN useradd -m -u 1000 user
|
13 |
+
USER user
|
14 |
+
ENV HOME /home/user
|
15 |
+
ENV PATH $HOME/.local/bin:$PATH
|
16 |
+
|
17 |
+
WORKDIR $HOME
|
18 |
+
RUN mkdir app
|
19 |
+
WORKDIR $HOME/app
|
20 |
+
COPY . $HOME/app
|
21 |
+
|
22 |
+
EXPOSE 8501
|
23 |
+
CMD streamlit run app.py \
|
24 |
+
--server.headless true \
|
25 |
+
--server.enableCORS false \
|
26 |
+
--server.enableXsrfProtection false \
|
27 |
+
--server.fileWatcherType none
|
README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1 |
-
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
-
sdk:
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
|
|
|
1 |
+
---
|
2 |
+
title: KN 2024 Final
|
3 |
+
emoji: 📊
|
4 |
+
colorFrom: indigo
|
5 |
+
colorTo: gray
|
6 |
+
sdk: streamlit
|
7 |
+
sdk_version: 1.38.0
|
8 |
+
app_file: app.py
|
9 |
+
pinned: false
|
10 |
+
---
|
11 |
+
|
12 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
a.png
ADDED
Git LFS Details
|
a.txt
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Folder PATH listing for volume Data2
|
2 |
+
Volume serial number is 6AB0-11CA
|
3 |
+
E:.
|
4 |
+
+---chestXray14
|
5 |
+
� +---imges
|
6 |
+
� +---models
|
7 |
+
� � +---__pycache__
|
8 |
+
� +---__pycache__
|
9 |
+
+---image_to_3D
|
10 |
+
� +---tsr
|
11 |
+
� � +---models
|
12 |
+
� � � +---tokenizers
|
13 |
+
� � � � +---__pycache__
|
14 |
+
� � � +---transformer
|
15 |
+
� � � � +---__pycache__
|
16 |
+
� � � +---__pycache__
|
17 |
+
� � +---__pycache__
|
18 |
+
� +---__pycache__
|
19 |
+
+---pages
|
20 |
+
� +---images
|
21 |
+
+---resources_img
|
22 |
+
+---visualize_x3d
|
23 |
+
� +---__pycache__
|
24 |
+
+---youtube-streamlit-image-grid
|
25 |
+
+---data
|
26 |
+
+---images
|
27 |
+
+---cea_FaZellweger-90A-01-2
|
28 |
+
� +---.ipynb_checkpoints
|
29 |
+
+---cjbg_fbg0006
|
30 |
+
+---csg_1276
|
app.py
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import subprocess
|
3 |
+
import time
|
4 |
+
import streamlit as st
|
5 |
+
|
6 |
+
# Install torchmcubes from GitHub
|
7 |
+
st.set_page_config(layout='wide')
|
8 |
+
|
9 |
+
with st.spinner('Lung Cancer is in force...'):
|
10 |
+
time.sleep(1.8)
|
11 |
+
|
12 |
+
col_1, col_2 = st.columns([2.6, 5])
|
13 |
+
|
14 |
+
with col_1:
|
15 |
+
st.image(f'resources_img/vita.jpg', caption='Hệ thống chẩn đoán bệnh phổi sử dụng trí tuệ nhân tạo')
|
16 |
+
|
17 |
+
with col_2:
|
18 |
+
st.markdown("<h1 style='text-align: center;'>HƯỚNG DẪN SỬ DỤNG</h1>", unsafe_allow_html=True)
|
19 |
+
st.info('**1.Chức năng Scan**')
|
20 |
+
st.write("Để sử dụng tính năng Scan, bạn hãy chọn mục **🔬 Scan** trên thanh chức năng bên trái của màn hình.")
|
21 |
+
st.image('./resources_img/guide1.jpg', caption='Hình 1: Hướng dẫn sử dụng tiện ích Scan ảnh phổi (1)')
|
22 |
+
st.write("Tiếp đến, ở phía dưới bên trái màn hình có phần **Upload your scan**, tại đây, bạn có thể chọn đầu vào tiện ích Scan. "
|
23 |
+
"Đầu vào được cho phép gồm: **Ảnh**, được thể hiện trong kí hiệu (1) của hình 2 dưới đây.")
|
24 |
+
st.image('./resources_img/guide2.png', caption='Hình 2: Hướng dẫn sử dụng tiện ích Scan ảnh phổi (2)')
|
25 |
+
st.write("Đường bao màu (tím) trong hình 2 được sử dụng để tải lên ảnh Scan phổi của bệnh nhân, khi tải lên thành công ảnh sẽ hiển thị ở phần đường bao màu (xanh lá cây)")
|
26 |
+
st.write("Nếu còn chưa hiểu cách sử dụng, hãy chọn '**Hướng dẫn**' trong hộp đánh dấu màu (cam) của hình 2. Trong phần này sẽ mô tả các bước có thể làm việc với phần mềm.")
|
27 |
+
|
28 |
+
st.info('**2. Phân loại các loại bệnh phổi**')
|
29 |
+
st.write("Để sử dụng chức năng phân loại các loại bệnh phổi, bạn hãy chọn vào mục '**⭐ Thoracic Classification**' trên thanh chức năng phía bên trái màn hình. ")
|
30 |
+
st.image('./resources_img/guide3.png', caption='Hình 3: Hướng dẫn sử dụng chức năng phân loại các loại bệnh phổi')
|
31 |
+
st.write("Tiếp đến, ở phía dưới bên trái màn hình có phần **Upload your scan**, tại đây, bạn có thể chọn đầu vào tiện ích Scan. "
|
32 |
+
"Đầu vào được cho phép gồm: **Ảnh**, được thể hiện trong kí hiệu (1) của hình 2 dưới đây.")
|
33 |
+
st.write("Sau khi duyệt và chọn ảnh cần hiển thị. Nó sẽ hiển thị hiển thị cho chúng ta ảnh ở góc trái màn hình.")
|
34 |
+
st.image('./resources_img/guide3_1.png', caption='Hình 3.1: Các chức năng phân loại các loại bệnh phổi')
|
35 |
+
|
36 |
+
st.write("**2.1. Dự đoán bệnh phổi**")
|
37 |
+
st.write("Trong giao diện chức năng. Sẽ có 5 chức năng để bạn làm việc bao gồm **Predict All Scans** (1), **Cam Visualization(2), **Segmenation Visualization for Lung** (3), **View Report** (4), **Download Report** (5).")
|
38 |
+
st.write("_**Lưu ý: Phải chọn Predict All Scan trước khi dùng các chức năng khác**_")
|
39 |
+
st.write("Bước tiếp theo, bạn cần chọn Predict All Scans. Sau khi chọn **Predict All Scans**, hệ thống sẽ tự động tính toán và lấy các kết quả đầu ra.")
|
40 |
+
st.image('./resources_img/guide4.png', caption='Hình 4: Hướng dẫn sử dụng dự đoán bệnh phổi')
|
41 |
+
st.write("Sau khi chương trình chạy thành công, nó sẽ hiện thông báo màu xanh để chúng ta biết" )
|
42 |
+
|
43 |
+
st.write("**2.2. CAM Visualization**")
|
44 |
+
st.write("Để xem ảnh CAM( Class Activation Map), bạn chọn chức năng **CAM Visualization**")
|
45 |
+
st.write("Sau đó bạn có thể lướt xuống dưới để xem ảnh")
|
46 |
+
st.image('./resources_img/guide5.png', caption='Hình 5: Hướng dẫn sử dụng chức năng Sửa thông tin định danh')
|
47 |
+
st.write("Bạn có thể phóng to và thu nhỏ ảnh bằng cách di chuột vào ảnh và cuộn chuột")
|
48 |
+
|
49 |
+
st.write("**2.3. Segmentation Visualization for Lung**")
|
50 |
+
st.write("Để xem ảnh Segmentation, bạn chọn chức năng **Segmentation Visualization for Lung**")
|
51 |
+
st.write("Sau đó bạn có thể lướt xuống dưới để xem ảnh")
|
52 |
+
st.image('./resources_img/guide6.png', caption='Hình 6: Hướng dẫn sử dụng chức năng Segmentation Visualization for Lung')
|
53 |
+
st.write("Bạn có thể phóng to và thu nhỏ ảnh bằng cách di chuột vào ảnh và cuộn chuột")
|
54 |
+
|
55 |
+
st.write("**2.4. Xem báo cáo**")
|
56 |
+
st.write("Để xem ảnh báo cáo về khả năng nhiễm bệnh, bạn chọn chức năng **View Report**")
|
57 |
+
st.write("Sau đó bạn có thể lướt xuống dưới để xem bảng thông tin về khả năng nhiễm bệnh.")
|
58 |
+
st.image('./resources_img/guide7.png',
|
59 |
+
caption='Hình 7: Hướng dẫn sử dụng chức năng xem báo cáo')
|
60 |
+
|
61 |
+
st.write("**2.5. Tải báo cáo**")
|
62 |
+
st.write("Để tải báo cáo dưới dạng PDF về khả năng nhiễm bệnh, bạn chọn chức năng **View Report**")
|
63 |
+
st.write("Sau đó bạn có thể lướt xuống dưới để điền một số trường thông tin liên quan tới bệnh nhân. Sau đó chọn Submit báo cáo sẽ tự tải về máy dưới dạng PDF")
|
64 |
+
st.image('./resources_img/guide8.png',
|
65 |
+
caption='Hình 7: Hướng dẫn sử dụng chức năng tải và in báo cáo')
|
66 |
+
|
67 |
+
st.info('**4. Chức năng x3D Lung Viewer**')
|
68 |
+
st.write("There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration "
|
69 |
+
"in some form, by injected humour, or randomised words which don't look even slightly believable. If you are"
|
70 |
+
" going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the"
|
71 |
+
" middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, "
|
72 |
+
"making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined "
|
73 |
+
"with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem "
|
74 |
+
"Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.")
|
cam_result.png
ADDED
Git LFS Details
|
chestXray14/__init__.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from test import *
|
2 |
+
from chexnet import *
|
3 |
+
from constant import *
|
4 |
+
from heatmap import *
|
5 |
+
from unet import *
|
6 |
+
from chestXray_utils import *
|
7 |
+
from layers import *
|
chestXray14/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (279 Bytes). View file
|
|
chestXray14/__pycache__/chestXray_utils.cpython-310.pyc
ADDED
Binary file (1.4 kB). View file
|
|
chestXray14/__pycache__/chexnet.cpython-310.pyc
ADDED
Binary file (2.42 kB). View file
|
|
chestXray14/__pycache__/constant.cpython-310.pyc
ADDED
Binary file (1.62 kB). View file
|
|
chestXray14/__pycache__/heatmap.cpython-310.pyc
ADDED
Binary file (1.54 kB). View file
|
|
chestXray14/__pycache__/layers.cpython-310.pyc
ADDED
Binary file (2.84 kB). View file
|
|
chestXray14/__pycache__/test.cpython-310.pyc
ADDED
Binary file (2.61 kB). View file
|
|
chestXray14/__pycache__/unet.cpython-310.pyc
ADDED
Binary file (5.83 kB). View file
|
|
chestXray14/cam_result.png
ADDED
Git LFS Details
|
chestXray14/chestXray_utils.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import numpy as np
|
3 |
+
from skimage import color, morphology
|
4 |
+
from constant import PATH, TRAIN_CSV, VAL_CSV, TEST_CSV
|
5 |
+
|
6 |
+
def get_chestxray_from_csv():
|
7 |
+
result = []
|
8 |
+
for f in [PATH/TRAIN_CSV, PATH/VAL_CSV, PATH/TEST_CSV]:
|
9 |
+
df = pd.read_csv(f, sep=' ', header=None)
|
10 |
+
images = df.iloc[:, 0].values
|
11 |
+
labels = df.iloc[:, 1:].values
|
12 |
+
result.append((images, labels))
|
13 |
+
return result
|
14 |
+
|
15 |
+
def sigmoid_np(x):
|
16 |
+
return 1. / (1. + np.exp(-x))
|
17 |
+
|
18 |
+
def blend_segmentation(image, mask, gt_mask=None, boundary=False, alpha=1):
|
19 |
+
image = np.array(image) # Convert PIL Image to NumPy array
|
20 |
+
w, h = image.shape[1], image.shape[0]
|
21 |
+
color_mask = np.zeros((h, w, 3)) # PIL Image
|
22 |
+
if boundary: mask = morphology.dilation(mask, morphology.disk(3)) - mask
|
23 |
+
color_mask[mask==1] = [1, 0, 0] # RGB
|
24 |
+
|
25 |
+
if gt_mask is not None:
|
26 |
+
gt_boundary = morphology.dilation(gt_mask, morphology.disk(3)) - gt_mask
|
27 |
+
color_mask[gt_boundary==1] = [0, 1, 0] # RGB
|
28 |
+
|
29 |
+
image_hsv = color.rgb2hsv(image)
|
30 |
+
color_mask_hsv = color.rgb2hsv(color_mask)
|
31 |
+
|
32 |
+
image_hsv[..., 0] = color_mask_hsv[..., 0]
|
33 |
+
image_hsv[..., 1] = color_mask_hsv[..., 1] * alpha
|
34 |
+
|
35 |
+
return color.hsv2rgb(image_hsv)
|
chestXray14/chexnet.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch.nn as nn
|
2 |
+
import pretrainedmodels
|
3 |
+
from torchvision.models import densenet121
|
4 |
+
from layers import Flatten
|
5 |
+
import torch
|
6 |
+
import torchvision.transforms as transforms
|
7 |
+
from pathlib import Path
|
8 |
+
from constant import IMAGENET_MEAN, IMAGENET_STD
|
9 |
+
import os
|
10 |
+
import sys
|
11 |
+
|
12 |
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
13 |
+
yolov9 = os.path.join(script_dir, '..', 'chestXray14')
|
14 |
+
sys.path.append(yolov9)
|
15 |
+
|
16 |
+
class ChexNet(nn.Module):
|
17 |
+
tfm = transforms.Compose([
|
18 |
+
transforms.Resize((224, 224)),
|
19 |
+
transforms.ToTensor(),
|
20 |
+
transforms.Normalize(IMAGENET_MEAN, IMAGENET_STD)
|
21 |
+
])
|
22 |
+
|
23 |
+
def __init__(self, trained=False, model_name='20180525-222635'):
|
24 |
+
super().__init__()
|
25 |
+
# chexnet.parameters() is freezed except head
|
26 |
+
if trained:
|
27 |
+
self.load_model(model_name)
|
28 |
+
else:
|
29 |
+
self.load_pretrained()
|
30 |
+
|
31 |
+
def load_model(self, model_name):
|
32 |
+
self.backbone = densenet121(False).features
|
33 |
+
self.head = nn.Sequential(
|
34 |
+
nn.AdaptiveAvgPool2d(1),
|
35 |
+
Flatten(),
|
36 |
+
nn.Linear(1024, 14)
|
37 |
+
)
|
38 |
+
path = Path('chestX-ray-14')
|
39 |
+
state_dict = torch.load('chexnet.h5')
|
40 |
+
self.load_state_dict(state_dict)
|
41 |
+
|
42 |
+
def load_pretrained(self, torch=False):
|
43 |
+
if torch:
|
44 |
+
self.backbone = densenet121(True).features
|
45 |
+
else:
|
46 |
+
self.backbone = pretrainedmodels.__dict__['densenet121']().features
|
47 |
+
|
48 |
+
self.head = nn.Sequential(
|
49 |
+
nn.AdaptiveAvgPool2d(1),
|
50 |
+
Flatten(),
|
51 |
+
nn.Linear(1024, 14)
|
52 |
+
)
|
53 |
+
|
54 |
+
def forward(self, x):
|
55 |
+
return self.head(self.backbone(x))
|
56 |
+
|
57 |
+
def predict(self, image):
|
58 |
+
"""
|
59 |
+
input: PIL image (w, h, c)
|
60 |
+
output: prob np.array
|
61 |
+
"""
|
62 |
+
image_tensor = self.tfm(image).unsqueeze(0) # Add batch dimension
|
63 |
+
image_tensor = image_tensor.to(next(self.parameters()).device) # Move to the same device as the model
|
64 |
+
with torch.no_grad():
|
65 |
+
py = torch.sigmoid(self(image_tensor))
|
66 |
+
prob = py.cpu().numpy()[0]
|
67 |
+
return prob
|
chestXray14/constant.py
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from pathlib import Path
|
3 |
+
import numpy as np
|
4 |
+
|
5 |
+
|
6 |
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
7 |
+
ROOT = os.path.abspath(os.path.join(current_dir, os.path.pardir))
|
8 |
+
|
9 |
+
N_CLASSES = 14
|
10 |
+
CLASS_NAMES = ['Atelectasis', 'Cardiomegaly', 'Effusion', 'Infiltration', 'Mass', 'Nodule', 'Pneumonia',
|
11 |
+
'Pneumothorax', 'Consolidation', 'Edema', 'Emphysema',
|
12 |
+
'Fibrosis', 'Pleural Thickening', 'Hernia']
|
13 |
+
|
14 |
+
IMAGENET_MEAN = np.array([0.485, 0.456, 0.406])
|
15 |
+
IMAGENET_STD = np.array([0.229, 0.224, 0.225])
|
16 |
+
|
17 |
+
PATH = Path('/home/dattran/data/xray-thesis/chestX-ray14')
|
18 |
+
ATTENTION_DN = 'tmp/attention'
|
19 |
+
IMAGE_DN = 'images'
|
20 |
+
TRAIN_CSV = 'train.csv'
|
21 |
+
VAL_CSV = 'val.csv'
|
22 |
+
TEST_CSV = 'test.csv'
|
23 |
+
|
24 |
+
"""
|
25 |
+
Below may not need any more
|
26 |
+
"""
|
27 |
+
# EPOCHS = 2# 100
|
28 |
+
# # BATCHES = 500 # 500
|
29 |
+
# BATCHSIZE = 32
|
30 |
+
# VALIDATE_EVERY_N_EPOCHS = 5
|
31 |
+
SCALE_FACTOR = .875
|
32 |
+
DATA_DIR = '/mnt/data/xray-thesis/data/chestX-ray14/images/'
|
33 |
+
PERCENTAGE = 0.01 # percentage of data use for quick run
|
34 |
+
TEST_AGUMENTED = False
|
35 |
+
DISEASE_THRESHOLD = 0.5
|
36 |
+
|
37 |
+
MODEL_DIR = '/mnt/data/xray-thesis/models'
|
38 |
+
LOG_DIR = 'mnt/data/xray-thesis/logs'
|
39 |
+
CSV_DIR = '%s/csv' % ROOT
|
40 |
+
STAT_DIR = '%s/stats' % ROOT
|
41 |
+
|
42 |
+
# chexnet file
|
43 |
+
CHEXNET_MODEL_NAME = '%s/chexnet_densenet.pth.tar' % MODEL_DIR
|
44 |
+
CHEXNET_TRAIN_CSV = '%s/chexnet_train_list.csv' % CSV_DIR
|
45 |
+
CHEXNET_VAL_CSV = '%s/chexnet_val_list.csv' % CSV_DIR
|
46 |
+
CHEXNET_TEST_CSV = '%s/chexnet_test_list.csv' % CSV_DIR
|
47 |
+
TRAIN_CSV = '%s/train_list.csv' % CSV_DIR
|
48 |
+
VAL_CSV = '%s/val_list.csv' % CSV_DIR
|
49 |
+
TEST_CSV = '%s/test_list.csv' % CSV_DIR
|
50 |
+
|
51 |
+
# different model
|
52 |
+
DENSENET121_DIR = '%s/densenet121' % MODEL_DIR
|
53 |
+
|
54 |
+
# stat
|
55 |
+
TRAIN_STAT = '%s/train.csv' % STAT_DIR
|
56 |
+
TEST_STAT = '%s/test.csv' % STAT_DIR
|
57 |
+
|
58 |
+
PREPROCESS = False
|
chestXray14/heatmap.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import numpy as np
|
3 |
+
import cv2
|
4 |
+
from chexnet import ChexNet
|
5 |
+
from layers import SaveFeature
|
6 |
+
from constant import CLASS_NAMES
|
7 |
+
|
8 |
+
|
9 |
+
class HeatmapGenerator:
|
10 |
+
|
11 |
+
# def __init__(self, model_name='20180429-130928', mode=None):
|
12 |
+
def __init__(self, chexnet, mode=None):
|
13 |
+
self.chexnet = chexnet
|
14 |
+
self.sf = SaveFeature(chexnet.backbone)
|
15 |
+
self.weight = list(list(self.chexnet.head.children())[-1].parameters())[0]
|
16 |
+
self.mapping = self.cam if mode == 'cam' else self.default
|
17 |
+
|
18 |
+
def cam(self, pred_y):
|
19 |
+
heatmap = self.sf.features[0].permute(1, 2, 0).detach().numpy() @ self.weight[pred_y].detach().numpy()
|
20 |
+
return heatmap
|
21 |
+
|
22 |
+
# def default(self, pred_ys):
|
23 |
+
# return torch.max(torch.abs(self.sf.features), dim=1)[0]
|
24 |
+
|
25 |
+
def generate(self, image):
|
26 |
+
prob = self.chexnet.predict(image)
|
27 |
+
w, h = image.size
|
28 |
+
return self.from_prob(prob, w, h)
|
29 |
+
|
30 |
+
def from_prob(self, prob, w, h):
|
31 |
+
pred_y = np.argmax(prob)
|
32 |
+
heatmap = self.mapping(pred_y)
|
33 |
+
|
34 |
+
heatmap = heatmap - np.min(heatmap)
|
35 |
+
heatmap = heatmap / np.max(heatmap)
|
36 |
+
heatmap = cv2.resize(heatmap, (w, h))
|
37 |
+
|
38 |
+
return heatmap, CLASS_NAMES[pred_y]
|
chestXray14/layers.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from torch import nn
|
2 |
+
import torch
|
3 |
+
import torch.nn.functional as F
|
4 |
+
import numpy as np
|
5 |
+
|
6 |
+
|
7 |
+
class Flatten(nn.Module):
|
8 |
+
def forward(self, x):
|
9 |
+
x = x.view(x.size()[0], -1)
|
10 |
+
return x
|
11 |
+
|
12 |
+
class LSEPool2d(nn.Module):
|
13 |
+
|
14 |
+
def __init__(self, r=3):
|
15 |
+
super().__init__()
|
16 |
+
self.r =r
|
17 |
+
|
18 |
+
def forward(self, x):
|
19 |
+
s = x.size()[3] # x: bs*2048*7*7
|
20 |
+
r = self.r
|
21 |
+
x_max = F.adaptive_max_pool2d(x, 1) # x_max: bs*2048*1*1
|
22 |
+
p = ((1/r) * torch.log((1 / (s*s)) * torch.exp(r*(x - x_max)).sum(3).sum(2)))
|
23 |
+
x_max = x_max.view(x.size(0), -1) # bs*2048
|
24 |
+
return x_max+p
|
25 |
+
|
26 |
+
|
27 |
+
class WeightedBCEWithLogitsLoss(nn.Module):
|
28 |
+
|
29 |
+
def __init__(self):
|
30 |
+
super().__init__()
|
31 |
+
|
32 |
+
def forward(self, input, target):
|
33 |
+
w = self.get_weight(input, target)
|
34 |
+
return F.binary_cross_entropy_with_logits(input, target, w, reduction='mean')
|
35 |
+
|
36 |
+
def get_weight(self, input, target):
|
37 |
+
y = target.cpu().data.numpy()
|
38 |
+
y_hat = input.cpu().data.numpy()
|
39 |
+
P = np.count_nonzero(y == 1)
|
40 |
+
N = np.count_nonzero(y == 0)
|
41 |
+
beta_p = (P + N) / (P + 1) # may not contain disease
|
42 |
+
beta_n = (P + N) / N
|
43 |
+
w = np.empty(y.shape)
|
44 |
+
w[y==0] = beta_n
|
45 |
+
w[y==1] = beta_p
|
46 |
+
w = torch.FloatTensor(w).cuda()
|
47 |
+
return w
|
48 |
+
|
49 |
+
class SaveFeature:
|
50 |
+
features = None
|
51 |
+
|
52 |
+
def __init__(self, m):
|
53 |
+
self.hook = m.register_forward_hook(self.hook_fn)
|
54 |
+
|
55 |
+
def hook_fn(self, module, input, output):
|
56 |
+
self.features = output
|
57 |
+
|
58 |
+
def remove(self):
|
59 |
+
self.hook.remove()
|
60 |
+
|
61 |
+
# class FocalLoss(WeightedBCELoss):
|
62 |
+
|
63 |
+
# def __init__(self, theta=2):
|
64 |
+
# super().__init__()
|
65 |
+
# self.theta = theta
|
66 |
+
|
67 |
+
# def forward(self, input, target):
|
68 |
+
# # pt = target*input + (1-target)*(1-input)
|
69 |
+
# # target *= (1-pt)**self.theta
|
70 |
+
# w = self.get_weight(input, target)
|
71 |
+
# return F.binary_cross_entropy_with_logits(input, target, w)
|
72 |
+
|
73 |
+
|
74 |
+
|
75 |
+
# class FocalLoss(nn.Module):
|
76 |
+
# def __init__(self, gamma=0, alpha=None, size_average=True):
|
77 |
+
# super(FocalLoss, self).__init__()
|
78 |
+
# self.gamma = gamma
|
79 |
+
# self.alpha = alpha
|
80 |
+
# if isinstance(alpha,(float,int,long)): self.alpha = torch.Tensor([alpha,1-alpha])
|
81 |
+
# if isinstance(alpha,list): self.alpha = torch.Tensor(alpha)
|
82 |
+
# self.size_average = size_average
|
83 |
+
|
84 |
+
# def forward(self, input, target):
|
85 |
+
# if input.dim()>2:
|
86 |
+
# input = input.view(input.size(0),input.size(1),-1) # N,C,H,W => N,C,H*W
|
87 |
+
# input = input.transpose(1,2) # N,C,H*W => N,H*W,C
|
88 |
+
# input = input.contiguous().view(-1,input.size(2)) # N,H*W,C => N*H*W,C
|
89 |
+
# target = target.view(-1,1)
|
90 |
+
|
91 |
+
# logpt = F.log_softmax(input)
|
92 |
+
# logpt = logpt.gather(1,target)
|
93 |
+
# logpt = logpt.view(-1)
|
94 |
+
# pt = Variable(logpt.data.exp())
|
95 |
+
|
96 |
+
# if self.alpha is not None:
|
97 |
+
# if self.alpha.type()!=input.data.type():
|
98 |
+
# self.alpha = self.alpha.type_as(input.data)
|
99 |
+
# at = self.alpha.gather(0,target.data.view(-1))
|
100 |
+
# logpt = logpt * Variable(at)
|
101 |
+
|
102 |
+
# loss = -1 * (1-pt)**self.gamma * logpt
|
103 |
+
# if self.size_average: return loss.mean()
|
104 |
+
# else: return loss.sum()
|
chestXray14/models/Model.ipynb
ADDED
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 2,
|
6 |
+
"metadata": {},
|
7 |
+
"outputs": [],
|
8 |
+
"source": [
|
9 |
+
"import torchvision\n",
|
10 |
+
"import pretrainedmodels\n",
|
11 |
+
"import torch\n",
|
12 |
+
"import pretrainedmodels.utils as utils\n",
|
13 |
+
"import torchvision.transforms as transforms\n",
|
14 |
+
"import torchvision.models as models\n",
|
15 |
+
"import torch.nn as nn\n",
|
16 |
+
"import torch.nn.functional as F\n",
|
17 |
+
"from PIL import Image\n",
|
18 |
+
"from collections import OrderedDict"
|
19 |
+
]
|
20 |
+
},
|
21 |
+
{
|
22 |
+
"cell_type": "code",
|
23 |
+
"execution_count": 3,
|
24 |
+
"metadata": {},
|
25 |
+
"outputs": [
|
26 |
+
{
|
27 |
+
"name": "stdout",
|
28 |
+
"output_type": "stream",
|
29 |
+
"text": [
|
30 |
+
"{'imagenet': {'url': 'http://data.lip6.fr/cadene/pretrainedmodels/nasnetalarge-a1897284.pth', 'input_space': 'RGB', 'input_size': [3, 331, 331], 'input_range': [0, 1], 'mean': [0.5, 0.5, 0.5], 'std': [0.5, 0.5, 0.5], 'num_classes': 1000}, 'imagenet+background': {'url': 'http://data.lip6.fr/cadene/pretrainedmodels/nasnetalarge-a1897284.pth', 'input_space': 'RGB', 'input_size': [3, 331, 331], 'input_range': [0, 1], 'mean': [0.5, 0.5, 0.5], 'std': [0.5, 0.5, 0.5], 'num_classes': 1001}}\n"
|
31 |
+
]
|
32 |
+
},
|
33 |
+
{
|
34 |
+
"name": "stderr",
|
35 |
+
"output_type": "stream",
|
36 |
+
"text": [
|
37 |
+
"Downloading: \"http://data.lip6.fr/cadene/pretrainedmodels/nasnetalarge-a1897284.pth\" to /home/dattran/.torch/models/nasnetalarge-a1897284.pth\n",
|
38 |
+
"100%|██████████| 356056626/356056626 [07:27<00:00, 795221.08it/s] \n"
|
39 |
+
]
|
40 |
+
}
|
41 |
+
],
|
42 |
+
"source": [
|
43 |
+
"print(pretrainedmodels.pretrained_settings['nasnetalarge'])\n",
|
44 |
+
"model = pretrainedmodels.__dict__['nasnetalarge'](num_classes=1000, pretrained='imagenet')"
|
45 |
+
]
|
46 |
+
},
|
47 |
+
{
|
48 |
+
"cell_type": "code",
|
49 |
+
"execution_count": 21,
|
50 |
+
"metadata": {},
|
51 |
+
"outputs": [
|
52 |
+
{
|
53 |
+
"data": {
|
54 |
+
"text/plain": [
|
55 |
+
"Variable containing:\n",
|
56 |
+
"( 0 , 0 ,.,.) = \n",
|
57 |
+
" 0.1121 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
58 |
+
" 0.4418 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
59 |
+
" 0.0000 0.0000 0.0000 ... 0.8554 0.0000 0.0000\n",
|
60 |
+
" ... ⋱ ... \n",
|
61 |
+
" 0.0000 0.5682 0.5166 ... 0.0301 0.0000 0.0000\n",
|
62 |
+
" 0.0000 0.0921 0.2531 ... 2.0754 0.4212 0.0000\n",
|
63 |
+
" 0.0000 0.0000 0.0000 ... 1.8003 0.5220 0.0000\n",
|
64 |
+
"\n",
|
65 |
+
"( 0 , 1 ,.,.) = \n",
|
66 |
+
" 0.1536 0.1211 0.0000 ... 1.3220 0.1388 0.0000\n",
|
67 |
+
" 0.4111 0.2736 0.1038 ... 0.7770 0.0000 0.0000\n",
|
68 |
+
" 0.0000 0.0000 0.0000 ... 1.5591 0.0000 0.0000\n",
|
69 |
+
" ... ⋱ ... \n",
|
70 |
+
" 0.0000 0.0000 0.3120 ... 0.0000 0.0000 0.0000\n",
|
71 |
+
" 1.2059 0.9648 0.7537 ... 0.0000 0.0000 0.0000\n",
|
72 |
+
" 1.8497 0.5725 0.0000 ... 0.0000 0.0000 0.0000\n",
|
73 |
+
"\n",
|
74 |
+
"( 0 , 2 ,.,.) = \n",
|
75 |
+
" 0.3311 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
76 |
+
" 0.0000 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
77 |
+
" 0.3876 0.2232 0.1740 ... 0.0000 0.0000 0.0000\n",
|
78 |
+
" ... ⋱ ... \n",
|
79 |
+
" 0.0000 0.0000 0.3968 ... 0.0000 0.2945 0.0000\n",
|
80 |
+
" 0.4885 0.8537 1.2278 ... 0.2380 0.6205 1.0980\n",
|
81 |
+
" 2.1136 1.3682 1.5039 ... 0.9723 0.9817 0.0760\n",
|
82 |
+
" ... \n",
|
83 |
+
"\n",
|
84 |
+
"( 0 ,1533,.,.) = \n",
|
85 |
+
" 0.8787 0.9274 0.5682 ... 0.4111 0.5084 0.5470\n",
|
86 |
+
" 0.5436 0.6317 0.5634 ... 0.5417 0.3694 0.4478\n",
|
87 |
+
" 0.0000 0.3396 0.5478 ... 0.8584 0.5552 0.5867\n",
|
88 |
+
" ... ⋱ ... \n",
|
89 |
+
" 0.0000 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
90 |
+
" 0.4349 0.2017 0.0000 ... 0.0000 0.0000 0.0000\n",
|
91 |
+
" 0.3743 0.3398 0.0000 ... 0.0000 0.0000 0.0000\n",
|
92 |
+
"\n",
|
93 |
+
"( 0 ,1534,.,.) = \n",
|
94 |
+
" 0.1190 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
95 |
+
" 0.0259 0.0000 0.0000 ... 0.3597 0.0000 0.0000\n",
|
96 |
+
" 0.0000 0.0000 0.0000 ... 1.4928 0.0000 0.0000\n",
|
97 |
+
" ... ⋱ ... \n",
|
98 |
+
" 0.0000 0.0000 0.0000 ... 1.4441 1.2858 0.6525\n",
|
99 |
+
" 0.0000 0.1889 0.5281 ... 0.7508 0.9813 0.5251\n",
|
100 |
+
" 0.0000 0.9832 1.3777 ... 0.0639 0.2403 0.0000\n",
|
101 |
+
"\n",
|
102 |
+
"( 0 ,1535,.,.) = \n",
|
103 |
+
" 0.0000 0.1068 0.3845 ... 0.0000 0.0000 0.0000\n",
|
104 |
+
" 0.0000 0.2751 0.7059 ... 0.0000 0.0000 0.0000\n",
|
105 |
+
" 0.0000 0.0711 0.4025 ... 1.2069 1.4548 1.1041\n",
|
106 |
+
" ... ⋱ ... \n",
|
107 |
+
" 0.0000 0.0000 0.0000 ... 0.7915 0.3439 0.1936\n",
|
108 |
+
" 0.0000 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
109 |
+
" 0.0275 0.0000 0.0000 ... 0.0000 0.0000 0.0000\n",
|
110 |
+
"[torch.FloatTensor of size 1x1536x8x8]"
|
111 |
+
]
|
112 |
+
},
|
113 |
+
"execution_count": 21,
|
114 |
+
"metadata": {},
|
115 |
+
"output_type": "execute_result"
|
116 |
+
}
|
117 |
+
],
|
118 |
+
"source": [
|
119 |
+
"load_img = utils.LoadImage()\n",
|
120 |
+
"# transformations depending on the model\n",
|
121 |
+
"# rescale, center crop, normalize, and others (ex: ToBGR, ToRange255)\n",
|
122 |
+
"tf_img = utils.TransformImage(model) \n",
|
123 |
+
"\n",
|
124 |
+
"path_img = '/home/dattran/data/xray/00000013_029.png'\n",
|
125 |
+
"\n",
|
126 |
+
"input_img = load_img(path_img)\n",
|
127 |
+
"input_tensor = tf_img(input_img) # 3x400x225 -> 3x299x299 size may differ\n",
|
128 |
+
"input_tensor = input_tensor.unsqueeze(0) # 3x299x299 -> 1x3x299x299\n",
|
129 |
+
"input = torch.autograd.Variable(input_tensor,\n",
|
130 |
+
" requires_grad=False)\n",
|
131 |
+
"model.features(input)"
|
132 |
+
]
|
133 |
+
},
|
134 |
+
{
|
135 |
+
"cell_type": "code",
|
136 |
+
"execution_count": 23,
|
137 |
+
"metadata": {},
|
138 |
+
"outputs": [
|
139 |
+
{
|
140 |
+
"data": {
|
141 |
+
"text/plain": [
|
142 |
+
"\u001B[0;31mInit signature:\u001B[0m \u001B[0mtorch\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mnn\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mMaxPool2d\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mkernel_size\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mstride\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;32mNone\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mpadding\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m0\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mdilation\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mreturn_indices\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;32mFalse\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mceil_mode\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;32mFalse\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n",
|
143 |
+
"\u001B[0;31mDocstring:\u001B[0m \n",
|
144 |
+
"Applies a 2D max pooling over an input signal composed of several input\n",
|
145 |
+
"planes.\n",
|
146 |
+
"\n",
|
147 |
+
"In the simplest case, the output value of the layer with input size :math:`(N, C, H, W)`,\n",
|
148 |
+
"output :math:`(N, C, H_{out}, W_{out})` and :attr:`kernel_size` :math:`(kH, kW)`\n",
|
149 |
+
"can be precisely described as:\n",
|
150 |
+
"\n",
|
151 |
+
".. math::\n",
|
152 |
+
"\n",
|
153 |
+
" \\begin{array}{ll}\n",
|
154 |
+
" out(N_i, C_j, h, w) = \\max_{{m}=0}^{kH-1} \\max_{{n}=0}^{kW-1}\n",
|
155 |
+
" input(N_i, C_j, stride[0] * h + m, stride[1] * w + n)\n",
|
156 |
+
" \\end{array}\n",
|
157 |
+
"\n",
|
158 |
+
"| If :attr:`padding` is non-zero, then the input is implicitly zero-padded on both sides\n",
|
159 |
+
" for :attr:`padding` number of points\n",
|
160 |
+
"| :attr:`dilation` controls the spacing between the kernel points. It is harder to describe,\n",
|
161 |
+
" but this `link`_ has a nice visualization of what :attr:`dilation` does.\n",
|
162 |
+
"\n",
|
163 |
+
"The parameters :attr:`kernel_size`, :attr:`stride`, :attr:`padding`, :attr:`dilation` can either be:\n",
|
164 |
+
"\n",
|
165 |
+
" - a single ``int`` -- in which case the same value is used for the height and width dimension\n",
|
166 |
+
" - a ``tuple`` of two ints -- in which case, the first `int` is used for the height dimension,\n",
|
167 |
+
" and the second `int` for the width dimension\n",
|
168 |
+
"\n",
|
169 |
+
"Args:\n",
|
170 |
+
" kernel_size: the size of the window to take a max over\n",
|
171 |
+
" stride: the stride of the window. Default value is :attr:`kernel_size`\n",
|
172 |
+
" padding: implicit zero padding to be added on both sides\n",
|
173 |
+
" dilation: a parameter that controls the stride of elements in the window\n",
|
174 |
+
" return_indices: if ``True``, will return the max indices along with the outputs.\n",
|
175 |
+
" Useful when Unpooling later\n",
|
176 |
+
" ceil_mode: when True, will use `ceil` instead of `floor` to compute the output shape\n",
|
177 |
+
"\n",
|
178 |
+
"Shape:\n",
|
179 |
+
" - Input: :math:`(N, C, H_{in}, W_{in})`\n",
|
180 |
+
" - Output: :math:`(N, C, H_{out}, W_{out})` where\n",
|
181 |
+
" :math:`H_{out} = floor((H_{in} + 2 * padding[0] - dilation[0] * (kernel\\_size[0] - 1) - 1) / stride[0] + 1)`\n",
|
182 |
+
" :math:`W_{out} = floor((W_{in} + 2 * padding[1] - dilation[1] * (kernel\\_size[1] - 1) - 1) / stride[1] + 1)`\n",
|
183 |
+
"\n",
|
184 |
+
"Examples::\n",
|
185 |
+
"\n",
|
186 |
+
" >>> # pool of square window of size=3, stride=2\n",
|
187 |
+
" >>> m = nn.MaxPool2d(3, stride=2)\n",
|
188 |
+
" >>> # pool of non-square window\n",
|
189 |
+
" >>> m = nn.MaxPool2d((3, 2), stride=(2, 1))\n",
|
190 |
+
" >>> input = autograd.Variable(torch.randn(20, 16, 50, 32))\n",
|
191 |
+
" >>> output = m(input)\n",
|
192 |
+
"\n",
|
193 |
+
".. _link:\n",
|
194 |
+
" https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md\n",
|
195 |
+
"\u001B[0;31mFile:\u001B[0m ~/miniconda2/envs/dat/lib/python3.6/site-packages/torch/nn/modules/pooling.py\n",
|
196 |
+
"\u001B[0;31mType:\u001B[0m type\n"
|
197 |
+
]
|
198 |
+
},
|
199 |
+
"metadata": {},
|
200 |
+
"output_type": "display_data"
|
201 |
+
}
|
202 |
+
],
|
203 |
+
"source": [
|
204 |
+
"torch.nn.MaxPool2d?"
|
205 |
+
]
|
206 |
+
},
|
207 |
+
{
|
208 |
+
"cell_type": "code",
|
209 |
+
"execution_count": 5,
|
210 |
+
"metadata": {},
|
211 |
+
"outputs": [],
|
212 |
+
"source": [
|
213 |
+
"from pretrainedmodels.models.dpn import adaptive_avgmax_pool2d"
|
214 |
+
]
|
215 |
+
},
|
216 |
+
{
|
217 |
+
"cell_type": "code",
|
218 |
+
"execution_count": 9,
|
219 |
+
"metadata": {},
|
220 |
+
"outputs": [
|
221 |
+
{
|
222 |
+
"data": {
|
223 |
+
"text/plain": [
|
224 |
+
"1000"
|
225 |
+
]
|
226 |
+
},
|
227 |
+
"execution_count": 9,
|
228 |
+
"metadata": {},
|
229 |
+
"output_type": "execute_result"
|
230 |
+
}
|
231 |
+
],
|
232 |
+
"source": [
|
233 |
+
"x = nn.Conv2d(1000, 14,kernel_size=1, bias=True)\n",
|
234 |
+
"x.in_channels"
|
235 |
+
]
|
236 |
+
},
|
237 |
+
{
|
238 |
+
"cell_type": "code",
|
239 |
+
"execution_count": 15,
|
240 |
+
"metadata": {},
|
241 |
+
"outputs": [
|
242 |
+
{
|
243 |
+
"data": {
|
244 |
+
"text/plain": [
|
245 |
+
"False"
|
246 |
+
]
|
247 |
+
},
|
248 |
+
"execution_count": 15,
|
249 |
+
"metadata": {},
|
250 |
+
"output_type": "execute_result"
|
251 |
+
}
|
252 |
+
],
|
253 |
+
"source": [
|
254 |
+
"model.eval()\n",
|
255 |
+
"model.training"
|
256 |
+
]
|
257 |
+
},
|
258 |
+
{
|
259 |
+
"cell_type": "code",
|
260 |
+
"execution_count": null,
|
261 |
+
"metadata": {},
|
262 |
+
"outputs": [],
|
263 |
+
"source": []
|
264 |
+
}
|
265 |
+
],
|
266 |
+
"metadata": {
|
267 |
+
"kernelspec": {
|
268 |
+
"display_name": "Python 3",
|
269 |
+
"language": "python",
|
270 |
+
"name": "python3"
|
271 |
+
},
|
272 |
+
"language_info": {
|
273 |
+
"codemirror_mode": {
|
274 |
+
"name": "ipython",
|
275 |
+
"version": 3
|
276 |
+
},
|
277 |
+
"file_extension": ".py",
|
278 |
+
"mimetype": "text/x-python",
|
279 |
+
"name": "python",
|
280 |
+
"nbconvert_exporter": "python",
|
281 |
+
"pygments_lexer": "ipython3",
|
282 |
+
"version": "3.6.4"
|
283 |
+
}
|
284 |
+
},
|
285 |
+
"nbformat": 4,
|
286 |
+
"nbformat_minor": 2
|
287 |
+
}
|
chestXray14/models/__pycache__/densenet.cpython-310.pyc
ADDED
Binary file (2.12 kB). View file
|
|
chestXray14/models/densenet.py
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torchvision
|
2 |
+
import torch.nn as nn
|
3 |
+
import pretrainedmodels
|
4 |
+
import torch.nn.functional as F
|
5 |
+
import torch
|
6 |
+
from constant import SCALE_FACTOR
|
7 |
+
import math
|
8 |
+
import pdb
|
9 |
+
|
10 |
+
class DenseNet(nn.Module):
|
11 |
+
|
12 |
+
def __init__(self, variant):
|
13 |
+
super(DenseNet, self).__init__()
|
14 |
+
assert variant in ['densenet121', 'densenet161', 'densenet201']
|
15 |
+
|
16 |
+
# load retrain model
|
17 |
+
model = pretrainedmodels.__dict__[variant](num_classes=1000, pretrained='imagenet')
|
18 |
+
self.features = model.features
|
19 |
+
num_ftrs = model.last_linear.in_features
|
20 |
+
self.classifier = nn.Sequential(
|
21 |
+
nn.Linear(num_ftrs, 14),
|
22 |
+
nn.Sigmoid()
|
23 |
+
)
|
24 |
+
# TODO: BCELoss with logit for numeric stable
|
25 |
+
# self.classifier = nn.Linear(num_ftrs, 14)
|
26 |
+
|
27 |
+
# load other info
|
28 |
+
self.mean = model.mean
|
29 |
+
self.std = model.std
|
30 |
+
self.input_size = model.input_size[1] # assume every input is a square image
|
31 |
+
self.input_range = model.input_range
|
32 |
+
self.input_space = model.input_space
|
33 |
+
self.resize_size = int(math.floor(self.input_size / SCALE_FACTOR))
|
34 |
+
|
35 |
+
def forward(self, x, **kwargs):
|
36 |
+
x = self.features(x) # 1x1024x7x7
|
37 |
+
s = x.size()[3] # 7 if input image is 224x224, 16 if input image is 512x512
|
38 |
+
x = F.relu(x, inplace=True) # 1x1024x7x7
|
39 |
+
|
40 |
+
pooling = kwargs['pooling']
|
41 |
+
if pooling == 'MAX':
|
42 |
+
x = F.max_pool2d(x, kernel_size=s, stride=1)
|
43 |
+
x = x.view(x.size(0), -1) # 1x1024
|
44 |
+
elif pooling == 'AVG':
|
45 |
+
x = F.avg_pool2d(x, kernel_size=s, stride=1) # 1x1024x1x1
|
46 |
+
x = x.view(x.size(0), -1) # 1x1024
|
47 |
+
elif pooling == 'LSE':
|
48 |
+
r = kwargs.lse_r
|
49 |
+
x_max = F.max_pool2d(x, kernel_size=s, stride=1)
|
50 |
+
p = ((1/r) * torch.log((1 / (s*s)) * torch.exp(r*(x - x_max)).sum(3).sum(2)))
|
51 |
+
x_max = x_max.view(x.size(0), -1)
|
52 |
+
x = x_max + p
|
53 |
+
else:
|
54 |
+
raise ValueError('Invalid pooling')
|
55 |
+
|
56 |
+
x = self.classifier(x) # 1x1000
|
57 |
+
return x
|
58 |
+
|
59 |
+
def extract(self, x):
|
60 |
+
return self.features(x)
|
61 |
+
|
62 |
+
# def count_params(self):
|
63 |
+
# return sum(p.numel() for p in self.parameters() if p.requires_grad)
|
64 |
+
|
65 |
+
def build(variant):
|
66 |
+
net = DenseNet(variant).cuda()
|
67 |
+
return net
|
68 |
+
|
69 |
+
architect='densenet'
|
70 |
+
|
71 |
+
|
chestXray14/models/dpn.py
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torchvision
|
2 |
+
import torch.nn as nn
|
3 |
+
import pretrainedmodels
|
4 |
+
import torch.nn.functional as F
|
5 |
+
from constant import SCALE_FACTOR
|
6 |
+
import math
|
7 |
+
from pretrainedmodels.models.dpn import adaptive_avgmax_pool2d
|
8 |
+
|
9 |
+
class DPN(nn.Module):
|
10 |
+
|
11 |
+
def __init__(self, variant):
|
12 |
+
super(DPN, self).__init__()
|
13 |
+
assert variant in ['dpn68', 'dpn68b', 'dpn92', 'dpn98', 'dpn131', 'dpn107']
|
14 |
+
|
15 |
+
# load retrain model
|
16 |
+
model = pretrainedmodels.__dict__[variant](num_classes=1000, pretrained='imagenet')
|
17 |
+
self.features = model.features
|
18 |
+
num_ftrs = model.classifier.in_channels
|
19 |
+
self.classifier = nn.Sequential(
|
20 |
+
nn.Conv2d(num_ftrs, 14, kernel_size=1, bias=True), # something wrong here abt dimension
|
21 |
+
nn.Sigmoid()
|
22 |
+
)
|
23 |
+
|
24 |
+
# load other info
|
25 |
+
self.mean = model.mean
|
26 |
+
self.std = model.std
|
27 |
+
self.input_size = model.input_size[1] # assume every input is a square image
|
28 |
+
self.input_range = model.input_range
|
29 |
+
self.input_space = model.input_space
|
30 |
+
self.resize_size = int(math.floor(self.input_size / SCALE_FACTOR))
|
31 |
+
|
32 |
+
def forward(self, x):
|
33 |
+
x = self.features(x) # 1x1024x7x7
|
34 |
+
if not self.training and self.test_time_tool:
|
35 |
+
x = F.avg_pool2d(x, kernel_size=7, stride=1)
|
36 |
+
x = self.classifier(x)
|
37 |
+
x = adaptive_avgmax_pool2d(out, pool_type='avgmax') # something wrong here abt dimension
|
38 |
+
else:
|
39 |
+
x = adaptive_avgmax_pool2d(x, pool_type='avg')
|
40 |
+
x = self.classifier(x)
|
41 |
+
return x
|
42 |
+
|
43 |
+
def extract(self, x):
|
44 |
+
return self.features(x)
|
45 |
+
|
46 |
+
def build(variant):
|
47 |
+
net = DPN(variant).cuda()
|
48 |
+
return net
|
49 |
+
|
50 |
+
architect='dpn'
|
51 |
+
|
52 |
+
|
chestXray14/models/inception.py
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torchvision
|
2 |
+
import torch.nn as nn
|
3 |
+
import pretrainedmodels
|
4 |
+
import torch.nn.functional as F
|
5 |
+
from collections import OrderedDict
|
6 |
+
from constant import SCALE_FACTOR
|
7 |
+
import math
|
8 |
+
|
9 |
+
class InceptionNet(nn.Module):
|
10 |
+
|
11 |
+
def __init__(self, variant):
|
12 |
+
super(InceptionNet, self).__init__()
|
13 |
+
assert variant in ['inceptionv4', 'inceptionv3', 'inceptionresnetv2']
|
14 |
+
|
15 |
+
# load pretrain model
|
16 |
+
model = pretrainedmodels.__dict__[variant](num_classes=1000, pretrained='imagenet')
|
17 |
+
self.features = _get_features(model, variant)
|
18 |
+
num_ftrs = model.last_linear.in_features
|
19 |
+
self.classifier = nn.Sequential(
|
20 |
+
nn.Linear(num_ftrs, 14),
|
21 |
+
nn.Sigmoid()
|
22 |
+
)
|
23 |
+
|
24 |
+
# load other info
|
25 |
+
self.mean = model.mean
|
26 |
+
self.std = model.std
|
27 |
+
self.input_size = model.input_size[1] # assume every input is a square image
|
28 |
+
self.input_range = model.input_range
|
29 |
+
self.input_space = model.input_space
|
30 |
+
self.resize_size = int(math.floor(self.input_size / SCALE_FACTOR))
|
31 |
+
|
32 |
+
def forward(self, x):
|
33 |
+
x = self.features(x) # 1x1536x8x8
|
34 |
+
s = x.size()[3] # 8 if input image is 224x224
|
35 |
+
x = F.avg_pool2d(x, kernel_size=s, count_include_pad=False) # 1x1536x1x1, same for inceptionv4 and inceptionresnetv2
|
36 |
+
x = x.view(x.size(0), -1) # 1x1536
|
37 |
+
x = self.classifier(x) # 1x1000
|
38 |
+
return x
|
39 |
+
|
40 |
+
def extract(self, x):
|
41 |
+
return self.features(x) # 1x1536x8x8
|
42 |
+
|
43 |
+
def build(variant):
|
44 |
+
net = InceptionNet(variant).cuda()
|
45 |
+
return net
|
46 |
+
|
47 |
+
def _get_features(model, variant):
|
48 |
+
if variant == 'inceptionv4':
|
49 |
+
features = model.features
|
50 |
+
elif variant == 'inceptionv3':
|
51 |
+
# TODO: Take a look on this
|
52 |
+
features = nn.Sequential(OrderedDict([
|
53 |
+
('Conv2d_1a_3x3', model.Conv2d_1a_3x3),
|
54 |
+
('Conv2d_2a_3x3', model.Conv2d_2a_3x3),
|
55 |
+
('Conv2d_2b_3x3', model.Conv2d_2b_3x3),
|
56 |
+
('max_pool2d_1', torch.nn.MaxPool2d(3, stride=2)),
|
57 |
+
('Conv2d_3b_1x1', model.Conv2d_3b_1x1),
|
58 |
+
('Conv2d_4a_3x3', model.Conv2d_4a_3x3),
|
59 |
+
('max_pool2d_2', torch.nn.MaxPool2d(3, stride=2)),
|
60 |
+
('Mixed_5b', model.Mixed_5b),
|
61 |
+
('Mixed_5c', model.Mixed_5c),
|
62 |
+
('Mixed_5d', model.Mixed_5d),
|
63 |
+
('Mixed_6a', model.Mixed_6a),
|
64 |
+
('Mixed_6b', model.Mixed_6b),
|
65 |
+
('Mixed_6c', model.Mixed_6c),
|
66 |
+
('Mixed_6d', model.Mixed_6b),
|
67 |
+
# ('Mixed_6c', model.Mixed_6c),
|
68 |
+
]))
|
69 |
+
elif variant == 'inceptionresnetv2':
|
70 |
+
features = nn.Sequential(OrderedDict([
|
71 |
+
('conv2d_1a', model.conv2d_1a),
|
72 |
+
('conv2d_2a', model.conv2d_2a),
|
73 |
+
('conv2d_2b', model.conv2d_2b),
|
74 |
+
('maxpool_3a', model.maxpool_3a),
|
75 |
+
('conv2d_3b', model.conv2d_3b),
|
76 |
+
('conv2d_4a', model.conv2d_4a),
|
77 |
+
('maxpool_5a', model.maxpool_5a),
|
78 |
+
('mixed_5b', model.mixed_5b),
|
79 |
+
('repeat', model.repeat),
|
80 |
+
('mixed_6a', model.mixed_6a),
|
81 |
+
('repeat_1', model.repeat_1),
|
82 |
+
('mixed_7a', model.mixed_7a),
|
83 |
+
('repeat_2', model.repeat_2),
|
84 |
+
('block8', model.block8),
|
85 |
+
('conv2d_7b', model.conv2d_7b)
|
86 |
+
]))
|
87 |
+
else:
|
88 |
+
raise "Unknown variant"
|
89 |
+
return features
|
90 |
+
|
91 |
+
architect='inception'
|
chestXray14/models/nasnet.py
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torchvision
|
2 |
+
import torch.nn as nn
|
3 |
+
import pretrainedmodels
|
4 |
+
import torch.nn.functional as F
|
5 |
+
from collections import OrderedDict
|
6 |
+
|
7 |
+
class Nasnet(nn.Module):
|
8 |
+
|
9 |
+
def __init__(self, variant):
|
10 |
+
super(Nasnet, self).__init__()
|
11 |
+
assert variant in ['nasnetalarge']
|
12 |
+
|
13 |
+
# load retrain model
|
14 |
+
self.model = pretrainedmodels.__dict__[variant](num_classes=1000, pretrained='imagenet')
|
15 |
+
# self.features = nn.Sequential(OrderedDict([
|
16 |
+
# ('conv0', model.conv0),
|
17 |
+
# ('cell_stem_0', model.cell_stem_0),
|
18 |
+
# ('cell_stem_1', model.cell_stem_1),
|
19 |
+
# ('cell_0', model.cell_0),
|
20 |
+
# ('cell_1', model.cell_1),
|
21 |
+
# ('cell_2', model.cell_2),
|
22 |
+
# ('cell_3', model.cell_3),
|
23 |
+
# ('cell_4', model.cell_4),
|
24 |
+
# ('cell_5', model.cell_5),
|
25 |
+
# ('reduction_cell_0', model.reduction_cell_0),
|
26 |
+
# ('cell_6', model.cell_6),
|
27 |
+
# ('cell_7', model.cell_7),
|
28 |
+
# ('cell_8', model.cell_8),
|
29 |
+
# ('cell_9', model.cell_9),
|
30 |
+
# ('cell_10', model.cell_10),
|
31 |
+
# ('cell_11', model.cell_11),
|
32 |
+
# ('reduction_cell_1', model.reduction_cell_1),
|
33 |
+
# ('cell_12', model.cell_6),
|
34 |
+
# ('cell_13', model.cell_7),
|
35 |
+
# ('cell_14', model.cell_8),
|
36 |
+
# ('cell_15', model.cell_9),
|
37 |
+
# ('cell_16', model.cell_10),
|
38 |
+
# ('cell_17', model.cell_11)
|
39 |
+
|
40 |
+
# ]))
|
41 |
+
num_ftrs = self.model.last_linear.in_features
|
42 |
+
self.model.last_linear = nn.Sequential(
|
43 |
+
nn.Linear(num_ftrs, 14),
|
44 |
+
nn.Sigmoid()
|
45 |
+
)
|
46 |
+
|
47 |
+
# load other info
|
48 |
+
# load other info
|
49 |
+
self.mean = self.model.mean
|
50 |
+
self.std = self.model.std
|
51 |
+
self.input_size = self.model.input_size[1] # assume every input is a square image
|
52 |
+
self.input_range = self.model.input_range
|
53 |
+
self.input_space = self.model.input_space
|
54 |
+
self.resize_size = 354 # as in pretrainmodels repo
|
55 |
+
|
56 |
+
def forward(self, x):
|
57 |
+
# x = self.features(x)
|
58 |
+
# x = F.avg_pool2d(x, kernel_size=11, stride=1, padding=0)
|
59 |
+
# x = x.view(x.size(0), -1)
|
60 |
+
# x = x.dropout(training=self.training)
|
61 |
+
# x = self.classifier(x) # 1x1000
|
62 |
+
# return x
|
63 |
+
return self.model.forward(x)
|
64 |
+
|
65 |
+
def extract(self, x):
|
66 |
+
# return self.features(x)
|
67 |
+
return self.model.features(x)
|
68 |
+
|
69 |
+
def build(variant):
|
70 |
+
net = Nasnet(variant).cuda()
|
71 |
+
return net
|
72 |
+
|
73 |
+
architect='nasnet'
|
chestXray14/models/resnet.py
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torchvision
|
2 |
+
import torch.nn as nn
|
3 |
+
import pretrainedmodels
|
4 |
+
import torch.nn.functional as F
|
5 |
+
from collections import OrderedDict
|
6 |
+
from constant import SCALE_FACTOR
|
7 |
+
import math
|
8 |
+
|
9 |
+
class Resnet(nn.Module):
|
10 |
+
|
11 |
+
def __init__(self, variant):
|
12 |
+
super(Resnet, self).__init__()
|
13 |
+
assert variant in ['resnet50', 'resnet101', 'resnet152']
|
14 |
+
|
15 |
+
# load retrain model
|
16 |
+
model = pretrainedmodels.__dict__[variant](num_classes=1000, pretrained='imagenet')
|
17 |
+
self.features = nn.Sequential(OrderedDict([
|
18 |
+
('conv1', model.conv1),
|
19 |
+
('bn1', model.bn1),
|
20 |
+
('relu', model.relu),
|
21 |
+
('maxpool', model.maxpool),
|
22 |
+
('layer1', model.layer1),
|
23 |
+
('layer2', model.layer2),
|
24 |
+
('layer3', model.layer3),
|
25 |
+
('layer4', model.layer4)
|
26 |
+
]))
|
27 |
+
num_ftrs = model.last_linear.in_features
|
28 |
+
self.classifier = nn.Sequential(
|
29 |
+
nn.Linear(num_ftrs, 14),
|
30 |
+
nn.Sigmoid()
|
31 |
+
)
|
32 |
+
|
33 |
+
# load other info
|
34 |
+
# load other info
|
35 |
+
self.mean = model.mean
|
36 |
+
self.std = model.std
|
37 |
+
self.input_size = model.input_size[1] # assume every input is a square image
|
38 |
+
self.input_range = model.input_range
|
39 |
+
self.input_space = model.input_space
|
40 |
+
self.resize_size = int(math.floor(self.input_size / SCALE_FACTOR))
|
41 |
+
|
42 |
+
def forward(self, x):
|
43 |
+
x = self.features(x) # 1x2048x7x7
|
44 |
+
s = x.size()[3] # 7 if input image is 224x224, 16 if input image is 512x512
|
45 |
+
x = F.avg_pool2d(x, kernel_size=s, stride=1) # 1x2048x1x1
|
46 |
+
x = x.view(x.size(0), -1) # 1x2048
|
47 |
+
x = self.classifier(x) # 1x1000
|
48 |
+
return x
|
49 |
+
|
50 |
+
def extract(self, x):
|
51 |
+
return self.features(x)
|
52 |
+
|
53 |
+
def build(variant):
|
54 |
+
net = Resnet(variant).cuda()
|
55 |
+
return net
|
56 |
+
|
57 |
+
architect='resnet'
|
chestXray14/models/resnext.py
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torchvision
|
2 |
+
import torch.nn as nn
|
3 |
+
import pretrainedmodels
|
4 |
+
import torch.nn.functional as F
|
5 |
+
from constant import SCALE_FACTOR
|
6 |
+
import math
|
7 |
+
|
8 |
+
class Resnext(nn.Module):
|
9 |
+
|
10 |
+
def __init__(self, variant):
|
11 |
+
super(Resnext, self).__init__()
|
12 |
+
assert variant in ['resnext101_32x4d', 'resnext101_64x4d']
|
13 |
+
|
14 |
+
# load retrain model
|
15 |
+
model = pretrainedmodels.__dict__[variant](num_classes=1000, pretrained='imagenet')
|
16 |
+
self.features = model.features
|
17 |
+
num_ftrs = model.last_linear.in_features
|
18 |
+
self.classifier = nn.Sequential(
|
19 |
+
nn.Linear(num_ftrs, 14),
|
20 |
+
nn.Sigmoid()
|
21 |
+
)
|
22 |
+
|
23 |
+
# load other info
|
24 |
+
self.mean = model.mean
|
25 |
+
self.std = model.std
|
26 |
+
self.input_size = model.input_size[1] # assume every input is a square image
|
27 |
+
self.input_range = model.input_range
|
28 |
+
self.input_space = model.input_space
|
29 |
+
self.resize_size = int(math.floor(self.input_size / SCALE_FACTOR))
|
30 |
+
|
31 |
+
def forward(self, x):
|
32 |
+
x = self.features(x) #
|
33 |
+
s = x.size()[3] # 7 if input image is 224x224, 16 if input image is 512x512
|
34 |
+
x = F.avg_pool2d(x, kernel_size=(7, 7), stride=(1, 1)) # 1x1024x1x1
|
35 |
+
x = x.view(x.size(0), -1) # 1x1024
|
36 |
+
x = self.classifier(x) # 1x1000
|
37 |
+
return x
|
38 |
+
|
39 |
+
def extract(self, x):
|
40 |
+
return self.features(x)
|
41 |
+
|
42 |
+
def build(variant):
|
43 |
+
net = Resnext(variant).cuda()
|
44 |
+
return net
|
45 |
+
|
46 |
+
architect='resnext'
|
47 |
+
|
48 |
+
|
chestXray14/models/senet.py
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torchvision
|
2 |
+
import torch.nn as nn
|
3 |
+
import pretrainedmodels
|
4 |
+
import torch.nn.functional as F
|
5 |
+
from collections import OrderedDict
|
6 |
+
from constant import SCALE_FACTOR
|
7 |
+
import math
|
8 |
+
|
9 |
+
class Resnet(nn.Module):
|
10 |
+
|
11 |
+
def __init__(self, variant):
|
12 |
+
super(Resnet, self).__init__()
|
13 |
+
assert variant in ['senet154', 'se_resnext101_32x4d', 'se_resnext50_32x4d', 'se_resnet152', 'se_resnet101', 'se_resnet50']
|
14 |
+
|
15 |
+
# load retrain model
|
16 |
+
model = pretrainedmodels.__dict__[variant](num_classes=1000, pretrained='imagenet')
|
17 |
+
self.features = nn.Sequential(OrderedDict([
|
18 |
+
('layer0', model.layer0),
|
19 |
+
('layer1', model.layer1),
|
20 |
+
('layer2', model.layer2),
|
21 |
+
('layer3', model.layer3),
|
22 |
+
('layer4', model.layer4)
|
23 |
+
]))
|
24 |
+
'''
|
25 |
+
Dropout
|
26 |
+
- For SENet154: 0.2
|
27 |
+
- For SE-ResNet models: None
|
28 |
+
- For SE-ResNeXt models: None
|
29 |
+
'''
|
30 |
+
self.dropout = model.dropout
|
31 |
+
num_ftrs = model.last_linear.in_features
|
32 |
+
self.classifier = nn.Sequential(
|
33 |
+
nn.Linear(num_ftrs, 14),
|
34 |
+
nn.Sigmoid()
|
35 |
+
)
|
36 |
+
|
37 |
+
# load other info
|
38 |
+
# load other info
|
39 |
+
self.mean = model.mean
|
40 |
+
self.std = model.std
|
41 |
+
self.input_size = model.input_size[1] # assume every input is a square image
|
42 |
+
self.input_range = model.input_range
|
43 |
+
self.input_space = model.input_space
|
44 |
+
self.resize_size = int(math.floor(self.input_size / SCALE_FACTOR))
|
45 |
+
|
46 |
+
def forward(self, x):
|
47 |
+
x = self.features(x) # 1x2048x7x7
|
48 |
+
s = x.size()[3] # 7 if input image is 224x224, 16 if input image is 512x512
|
49 |
+
x = F.avg_pool2d(x, kernel_size=s, stride=1) # 1x2048x1x1
|
50 |
+
x = x.view(x.size(0), -1) # 1x2048
|
51 |
+
x = self.classifier(x) # 1x1000
|
52 |
+
return x
|
53 |
+
|
54 |
+
def extract(self, x):
|
55 |
+
return self.features(x)
|
56 |
+
|
57 |
+
def build(variant):
|
58 |
+
net = Resnet(variant).cuda()
|
59 |
+
return net
|
60 |
+
|
61 |
+
architect='senet'
|
chestXray14/segment_result.png
ADDED
Git LFS Details
|
chestXray14/test.py
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PIL import Image
|
2 |
+
import numpy as np
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
import cv2
|
5 |
+
import os
|
6 |
+
|
7 |
+
from chexnet import ChexNet
|
8 |
+
from unet import Unet
|
9 |
+
from heatmap import HeatmapGenerator
|
10 |
+
from constant import IMAGENET_MEAN, IMAGENET_STD, CLASS_NAMES
|
11 |
+
|
12 |
+
import sys
|
13 |
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
14 |
+
imgto3d_path = os.path.join(script_dir, '.')
|
15 |
+
sys.path.append(imgto3d_path)
|
16 |
+
|
17 |
+
from chestXray_utils import blend_segmentation
|
18 |
+
import torch
|
19 |
+
import pandas as pd
|
20 |
+
|
21 |
+
|
22 |
+
output_dir = "pages/images"
|
23 |
+
os.makedirs(output_dir, exist_ok=True)
|
24 |
+
|
25 |
+
unet_model = '20190211-101020'
|
26 |
+
chexnet_model = '20180429-130928'
|
27 |
+
DISEASES = np.array(CLASS_NAMES)
|
28 |
+
|
29 |
+
|
30 |
+
# Initialize models
|
31 |
+
unet = Unet(trained=True, model_name=unet_model)
|
32 |
+
chexnet = ChexNet(trained=True, model_name=chexnet_model)
|
33 |
+
heatmap_generator = HeatmapGenerator(chexnet, mode='cam')
|
34 |
+
unet.eval()
|
35 |
+
chexnet.eval()
|
36 |
+
|
37 |
+
|
38 |
+
def process_image(image_path):
|
39 |
+
image = Image.open(image_path).convert('RGB')
|
40 |
+
|
41 |
+
# Run through net
|
42 |
+
(t, l, b, r), mask = unet.segment(image)
|
43 |
+
cropped_image = image.crop((l, t, r, b))
|
44 |
+
prob = chexnet.predict(cropped_image)
|
45 |
+
|
46 |
+
# Save segmentation result
|
47 |
+
blended = blend_segmentation(image, mask)
|
48 |
+
blended = (blended - blended.min()) / (blended.max() - blended.min()) # Normalize to [0, 1]
|
49 |
+
blended = (blended * 255).astype(np.uint8) # Convert to 0-255 range for cv2
|
50 |
+
cv2.rectangle(blended, (l, t), (r, b), (255, 0, 0), 5) # Color in BGR format for cv2
|
51 |
+
segment_result_path = os.path.join(output_dir, 'segment_result.png')
|
52 |
+
plt.imsave(segment_result_path, blended)
|
53 |
+
|
54 |
+
# Save CAM result
|
55 |
+
w, h = cropped_image.size
|
56 |
+
heatmap, _ = heatmap_generator.from_prob(prob, w, h)
|
57 |
+
|
58 |
+
# Resize the heatmap to match the original image dimensions
|
59 |
+
heatmap_resized = cv2.resize(heatmap, (image.width, image.height))
|
60 |
+
heatmap_resized = np.repeat(heatmap_resized[:, :, np.newaxis], 3, axis=2) # Ensure it has 3 channels
|
61 |
+
|
62 |
+
heatmap_resized = ((heatmap_resized - heatmap_resized.min()) * (
|
63 |
+
1 / (heatmap_resized.max() - heatmap_resized.min())) * 255).astype(np.uint8)
|
64 |
+
|
65 |
+
cam = cv2.applyColorMap(heatmap_resized, cv2.COLORMAP_JET)
|
66 |
+
cam = cv2.resize(cam, (image.width, image.height)) # Ensure cam has same dimensions as image
|
67 |
+
cam = cv2.addWeighted(cam, 0.4, np.array(image), 0.6, 0) # Combine heatmap with the original image
|
68 |
+
cam_result_path = os.path.join(output_dir, 'cam_result.png')
|
69 |
+
print("a",cam_result_path)
|
70 |
+
cv2.imwrite(cam_result_path, cam)
|
71 |
+
|
72 |
+
# Top-10 diseases
|
73 |
+
idx = np.argsort(-prob)
|
74 |
+
top_prob = prob[idx[:10]]
|
75 |
+
top_prob = [f'{x:.3}' for x in top_prob]
|
76 |
+
top_disease = DISEASES[idx[:10]]
|
77 |
+
prediction = dict(zip(top_disease, top_prob))
|
78 |
+
|
79 |
+
result = {'result': prediction}
|
80 |
+
df = pd.DataFrame(result['result'].items(), columns=['Disease', 'Probability'])
|
81 |
+
output_file = 'prediction_results.csv'
|
82 |
+
output_file_path = os.path.join(output_dir, output_file)
|
83 |
+
df.to_csv(output_file_path, index=False)
|
84 |
+
|
85 |
+
return result, segment_result_path, cam_result_path
|
86 |
+
|
87 |
+
|
88 |
+
# if __name__ == '__main__':
|
89 |
+
# image_path = r'E:\NLP\KN2024\chestX-ray-14\src\fibrosis.jpg' # Replace with your image path
|
90 |
+
# result, segment_result_path, cam_result_path = process_image(image_path)
|
91 |
+
# print("Prediction Results:", result)
|
92 |
+
# print(f"Segmentation Result Saved to: {segment_result_path}")
|
93 |
+
# print(f"CAM Result Saved to: {cam_result_path}")
|
chestXray14/unet.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:a1768ae75ce08bc7cb1d338e26648887e5c4d79ff0b97ab89831789666ac0ed6
|
3 |
+
size 264784168
|
chestXray14/unet.py
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch.nn as nn
|
2 |
+
import torch.nn.functional as F
|
3 |
+
import torch
|
4 |
+
from layers import SaveFeature
|
5 |
+
import pretrainedmodels
|
6 |
+
from torchvision.models import resnet34, resnet50, resnet101, resnet152
|
7 |
+
from pathlib import Path
|
8 |
+
from torchvision.models.resnet import conv3x3, BasicBlock, Bottleneck
|
9 |
+
import skimage
|
10 |
+
from scipy import ndimage
|
11 |
+
import numpy as np
|
12 |
+
import torchvision.transforms as transforms
|
13 |
+
import cv2
|
14 |
+
from constant import IMAGENET_MEAN, IMAGENET_STD
|
15 |
+
|
16 |
+
device="cuda" if torch.cuda.is_available() else "cpu"
|
17 |
+
class UpBlock(nn.Module):
|
18 |
+
expansion = 1
|
19 |
+
|
20 |
+
def __init__(self, inplanes, planes, expansion=1):
|
21 |
+
super().__init__()
|
22 |
+
inplanes = inplanes * expansion
|
23 |
+
planes = planes * expansion
|
24 |
+
self.upconv = nn.ConvTranspose2d(inplanes, planes, 2, 2, 0)
|
25 |
+
self.bn1 = nn.BatchNorm2d(planes)
|
26 |
+
self.relu = nn.ReLU(inplace=True)
|
27 |
+
self.conv1 = conv3x3(inplanes, planes)
|
28 |
+
self.bn2 = nn.BatchNorm2d(planes)
|
29 |
+
|
30 |
+
def forward(self, u, x):
|
31 |
+
up = self.relu(self.bn1(self.upconv(u)))
|
32 |
+
out = torch.cat([x, up], dim=1) # cat along channel
|
33 |
+
out = self.relu(self.bn2(self.conv1(out)))
|
34 |
+
return out
|
35 |
+
|
36 |
+
class UpLayer(nn.Module):
|
37 |
+
|
38 |
+
def __init__(self, block, inplanes, planes, blocks):
|
39 |
+
super().__init__()
|
40 |
+
self.up = UpBlock(inplanes, planes, block.expansion)
|
41 |
+
layers = [block(planes * block.expansion, planes) for _ in range(1, blocks)]
|
42 |
+
self.conv = nn.Sequential(*layers)
|
43 |
+
|
44 |
+
def forward(self, u, x):
|
45 |
+
x = self.up(u, x)
|
46 |
+
x = self.conv(x)
|
47 |
+
return x
|
48 |
+
|
49 |
+
from pathlib import Path
|
50 |
+
|
51 |
+
|
52 |
+
|
53 |
+
class Unet(nn.Module):
|
54 |
+
tfm = transforms.Compose([
|
55 |
+
transforms.Resize((256, 256)),
|
56 |
+
transforms.ToTensor(),
|
57 |
+
transforms.Normalize(IMAGENET_MEAN, IMAGENET_STD)
|
58 |
+
])
|
59 |
+
|
60 |
+
def __init__(self, trained=False, model_name=None):
|
61 |
+
super().__init__()
|
62 |
+
self.layers = [3, 4, 6]
|
63 |
+
self.block = Bottleneck
|
64 |
+
if trained:
|
65 |
+
assert model_name is not None
|
66 |
+
self.load_model(model_name)
|
67 |
+
else:
|
68 |
+
self.load_pretrained()
|
69 |
+
|
70 |
+
def cut_model(self, model, cut):
|
71 |
+
return list(model.children())[:cut]
|
72 |
+
|
73 |
+
def load_model(self, model_name):
|
74 |
+
resnet = resnet50(False)
|
75 |
+
self.backbone = nn.Sequential(*self.cut_model(resnet, 8))
|
76 |
+
self.init_head()
|
77 |
+
|
78 |
+
model_path = Path(__file__).parent / 'unet.h5'
|
79 |
+
state_dict = torch.load(model_path, map_location=torch.device(device))
|
80 |
+
self.load_state_dict(state_dict)
|
81 |
+
|
82 |
+
def load_pretrained(self, torch=False):
|
83 |
+
if torch:
|
84 |
+
resnet = resnet50(True)
|
85 |
+
else:
|
86 |
+
resnet = pretrainedmodels.__dict__['resnet50']()
|
87 |
+
self.backbone = nn.Sequential(*self.cut_model(resnet, 8))
|
88 |
+
self.init_head()
|
89 |
+
|
90 |
+
def init_head(self):
|
91 |
+
self.sfs = [SaveFeature(self.backbone[i]) for i in [2, 4, 5, 6]]
|
92 |
+
self.up_layer1 = UpLayer(self.block, 512, 256, self.layers[-1])
|
93 |
+
self.up_layer2 = UpLayer(self.block, 256, 128, self.layers[-2])
|
94 |
+
self.up_layer3 = UpLayer(self.block, 128, 64, self.layers[-3])
|
95 |
+
|
96 |
+
self.map = conv3x3(64 * self.block.expansion, 64) # 64e -> 64
|
97 |
+
self.conv = conv3x3(128, 64)
|
98 |
+
self.bn_conv = nn.BatchNorm2d(64)
|
99 |
+
self.up_conv = nn.ConvTranspose2d(64, 1, 2, 2, 0)
|
100 |
+
self.bn_up = nn.BatchNorm2d(1)
|
101 |
+
|
102 |
+
def forward(self, x):
|
103 |
+
x = F.relu(self.backbone(x))
|
104 |
+
x = self.up_layer1(x, self.sfs[3].features)
|
105 |
+
x = self.up_layer2(x, self.sfs[2].features)
|
106 |
+
x = self.up_layer3(x, self.sfs[1].features)
|
107 |
+
x = self.map(x)
|
108 |
+
x = F.interpolate(x, scale_factor=2)
|
109 |
+
x = torch.cat([self.sfs[0].features, x], dim=1)
|
110 |
+
x = F.relu(self.bn_conv(self.conv(x)))
|
111 |
+
x = F.relu(self.bn_up(self.up_conv(x)))
|
112 |
+
return x
|
113 |
+
|
114 |
+
def close(self):
|
115 |
+
for sf in self.sfs:
|
116 |
+
sf.remove()
|
117 |
+
|
118 |
+
def segment(self, image):
|
119 |
+
"""
|
120 |
+
image: cropped CXR PIL Image (h, w, 3)
|
121 |
+
"""
|
122 |
+
kernel = np.ones((10, 10))
|
123 |
+
iw, ih = image.size
|
124 |
+
|
125 |
+
image_tensor = self.tfm(image).unsqueeze(0).to(next(self.parameters()).device)
|
126 |
+
with torch.no_grad():
|
127 |
+
py = torch.sigmoid(self(image_tensor))
|
128 |
+
py = (py[0].cpu() > 0.5).type(torch.FloatTensor) # 1, 256, 256
|
129 |
+
|
130 |
+
mask = py[0].numpy()
|
131 |
+
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
|
132 |
+
mask = cv2.resize(mask, (iw, ih))
|
133 |
+
slice_y, slice_x = ndimage.find_objects(mask, 1)[0]
|
134 |
+
h, w = slice_y.stop - slice_y.start, slice_x.stop - slice_x.start
|
135 |
+
|
136 |
+
nw, nh = int(w / .875), int(h / .875)
|
137 |
+
dw, dh = (nw - w) // 2, (nh - h) // 2
|
138 |
+
t = max(slice_y.start - dh, 0)
|
139 |
+
l = max(slice_x.start - dw, 0)
|
140 |
+
b = min(slice_y.stop + dh, ih)
|
141 |
+
r = min(slice_x.stop + dw, iw)
|
142 |
+
return (t, l, b, r), mask
|
chexnet.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:8d8e4e04574c0044faff5630f942ac873681be8914ba4968b6b2070362b1a340
|
3 |
+
size 28360928
|
config.yaml
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
cond_image_size: 512
|
2 |
+
|
3 |
+
image_tokenizer_cls: tsr.models.tokenizers.image.DINOSingleImageTokenizer
|
4 |
+
image_tokenizer:
|
5 |
+
pretrained_model_name_or_path: "facebook/dino-vitb16"
|
6 |
+
|
7 |
+
tokenizer_cls: tsr.models.tokenizers.triplane.Triplane1DTokenizer
|
8 |
+
tokenizer:
|
9 |
+
plane_size: 32
|
10 |
+
num_channels: 1024
|
11 |
+
|
12 |
+
backbone_cls: tsr.models.transformer.transformer_1d.Transformer1D
|
13 |
+
backbone:
|
14 |
+
in_channels: ${tokenizer.num_channels}
|
15 |
+
num_attention_heads: 16
|
16 |
+
attention_head_dim: 64
|
17 |
+
num_layers: 16
|
18 |
+
cross_attention_dim: 768
|
19 |
+
|
20 |
+
post_processor_cls: tsr.models.network_utils.TriplaneUpsampleNetwork
|
21 |
+
post_processor:
|
22 |
+
in_channels: 1024
|
23 |
+
out_channels: 40
|
24 |
+
|
25 |
+
decoder_cls: tsr.models.network_utils.NeRFMLP
|
26 |
+
decoder:
|
27 |
+
in_channels: 120 # 3 * 40
|
28 |
+
n_neurons: 64
|
29 |
+
n_hidden_layers: 9
|
30 |
+
activation: silu
|
31 |
+
|
32 |
+
renderer_cls: tsr.models.nerf_renderer.TriplaneNeRFRenderer
|
33 |
+
renderer:
|
34 |
+
radius: 0.87 # slightly larger than 0.5 * sqrt(3)
|
35 |
+
feature_reduction: concat
|
36 |
+
density_activation: exp
|
37 |
+
density_bias: -1.0
|
38 |
+
num_samples_per_ray: 128
|
face_recognition_dynamic.gif
ADDED
Git LFS Details
|
faiss_index/index.faiss
ADDED
Binary file (98.3 kB). View file
|
|
faiss_index/index.pkl
ADDED
Binary file (395 kB). View file
|
|
image_to_3D/3d_model_requirements.txt
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
omegaconf==2.3.0
|
2 |
+
Pillow==10.1.0
|
3 |
+
einops==0.7.0
|
4 |
+
git+https://github.com/tatsy/torchmcubes.git
|
5 |
+
transformers==4.35.0
|
6 |
+
trimesh==4.0.5
|
7 |
+
rembg
|
8 |
+
huggingface-hub
|
9 |
+
imageio[ffmpeg]
|
10 |
+
gradio
|
11 |
+
xatlas==0.0.9
|
12 |
+
moderngl==5.10.0
|
13 |
+
torch==2.0.0
|
14 |
+
setuptools==68.2.0
|
image_to_3D/__init__.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from attention import *
|
2 |
+
from basic_transformer_block import *
|
3 |
+
from image import *
|
4 |
+
from isosurface import *
|
5 |
+
from nerf_renderer import *
|
6 |
+
from network_utils import *
|
7 |
+
from rotate import *
|
8 |
+
from run import *
|
9 |
+
from transformer_1d import *
|
10 |
+
from triplane import *
|
11 |
+
from ui import *
|
12 |
+
from x3D_utils import *
|
image_to_3D/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (403 Bytes). View file
|
|
image_to_3D/__pycache__/__init__.cpython-39.pyc
ADDED
Binary file (397 Bytes). View file
|
|
image_to_3D/__pycache__/attention.cpython-310.pyc
ADDED
Binary file (15.3 kB). View file
|
|
image_to_3D/__pycache__/attention.cpython-39.pyc
ADDED
Binary file (15.1 kB). View file
|
|
image_to_3D/__pycache__/basic_transformer_block.cpython-310.pyc
ADDED
Binary file (9.59 kB). View file
|
|