Upload folder using huggingface_hub
Browse files- .vs/detectron_model/FileContentIndex/41db3a26-7ff6-483d-a361-f297ad6da18e.vsidx +0 -0
- .vs/detectron_model/FileContentIndex/85bb5c5c-11eb-434c-8427-b75d39bcd171.vsidx +0 -0
- .vs/detectron_model/FileContentIndex/b78701b3-342c-48c5-b440-4495ec02309d.vsidx +0 -0
- .vs/detectron_model/v17/.suo +0 -0
- .vs/detectron_model/v17/DocumentLayout.backup.json +37 -0
- .vs/detectron_model/v17/DocumentLayout.json +35 -0
- README.md +1 -0
- app.py +19 -0
- det_model.py +301 -0
- hf.py +9 -0
- pix3d_dimension_estimator_mask_crop.pth +3 -0
- requirements.txt +7 -0
.vs/detectron_model/FileContentIndex/41db3a26-7ff6-483d-a361-f297ad6da18e.vsidx
ADDED
Binary file (29 kB). View file
|
|
.vs/detectron_model/FileContentIndex/85bb5c5c-11eb-434c-8427-b75d39bcd171.vsidx
ADDED
Binary file (20.6 kB). View file
|
|
.vs/detectron_model/FileContentIndex/b78701b3-342c-48c5-b440-4495ec02309d.vsidx
ADDED
Binary file (107 Bytes). View file
|
|
.vs/detectron_model/v17/.suo
ADDED
Binary file (27.1 kB). View file
|
|
.vs/detectron_model/v17/DocumentLayout.backup.json
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Version": 1,
|
3 |
+
"WorkspaceRootPath": "C:\\Users\\pc\\TLproj\\detectron_model\\",
|
4 |
+
"Documents": [
|
5 |
+
{
|
6 |
+
"AbsoluteMoniker": "D:0:0:{547F1ED0-B3CB-4F4C-B952-A38644838CF5}|detectron_model.pyproj|C:\\Users\\pc\\TLproj\\detectron_model\\detectron_model.py||{8B382828-6202-11D1-8870-0000F87579D2}",
|
7 |
+
"RelativeMoniker": "D:0:0:{547F1ED0-B3CB-4F4C-B952-A38644838CF5}|detectron_model.pyproj|solutionrelative:detectron_model.py||{8B382828-6202-11D1-8870-0000F87579D2}"
|
8 |
+
}
|
9 |
+
],
|
10 |
+
"DocumentGroupContainers": [
|
11 |
+
{
|
12 |
+
"Orientation": 0,
|
13 |
+
"VerticalTabListWidth": 256,
|
14 |
+
"DocumentGroups": [
|
15 |
+
{
|
16 |
+
"DockedWidth": 200,
|
17 |
+
"SelectedChildIndex": 0,
|
18 |
+
"Children": [
|
19 |
+
{
|
20 |
+
"$type": "Document",
|
21 |
+
"DocumentIndex": 0,
|
22 |
+
"Title": "detectron_model.py",
|
23 |
+
"DocumentMoniker": "C:\\Users\\pc\\TLproj\\detectron_model\\detectron_model.py",
|
24 |
+
"RelativeDocumentMoniker": "detectron_model.py",
|
25 |
+
"ToolTip": "C:\\Users\\pc\\TLproj\\detectron_model\\detectron_model.py",
|
26 |
+
"RelativeToolTip": "detectron_model.py",
|
27 |
+
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
28 |
+
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
29 |
+
"WhenOpened": "2025-05-10T12:10:14.159Z",
|
30 |
+
"EditorCaption": ""
|
31 |
+
}
|
32 |
+
]
|
33 |
+
}
|
34 |
+
]
|
35 |
+
}
|
36 |
+
]
|
37 |
+
}
|
.vs/detectron_model/v17/DocumentLayout.json
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"Version": 1,
|
3 |
+
"WorkspaceRootPath": "C:\\Users\\pc\\TLproj\\detectron_model\\",
|
4 |
+
"Documents": [
|
5 |
+
{
|
6 |
+
"AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\pc\\TLproj\\detectron_model\\detectron_model.py||{8B382828-6202-11D1-8870-0000F87579D2}",
|
7 |
+
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:detectron_model.py||{8B382828-6202-11D1-8870-0000F87579D2}"
|
8 |
+
}
|
9 |
+
],
|
10 |
+
"DocumentGroupContainers": [
|
11 |
+
{
|
12 |
+
"Orientation": 0,
|
13 |
+
"VerticalTabListWidth": 256,
|
14 |
+
"DocumentGroups": [
|
15 |
+
{
|
16 |
+
"DockedWidth": 200,
|
17 |
+
"SelectedChildIndex": 0,
|
18 |
+
"Children": [
|
19 |
+
{
|
20 |
+
"$type": "Document",
|
21 |
+
"DocumentIndex": 0,
|
22 |
+
"Title": "detectron_model.py",
|
23 |
+
"DocumentMoniker": "C:\\Users\\pc\\TLproj\\detectron_model\\detectron_model.py",
|
24 |
+
"RelativeDocumentMoniker": "detectron_model.py",
|
25 |
+
"ToolTip": "C:\\Users\\pc\\TLproj\\detectron_model\\detectron_model.py",
|
26 |
+
"RelativeToolTip": "detectron_model.py",
|
27 |
+
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|",
|
28 |
+
"WhenOpened": "2025-05-10T12:10:14.159Z"
|
29 |
+
}
|
30 |
+
]
|
31 |
+
}
|
32 |
+
]
|
33 |
+
}
|
34 |
+
]
|
35 |
+
}
|
README.md
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
# detectron_model
|
app.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from det_model import predict_dimensions # function you'll define
|
3 |
+
from detectron_model import load_detectron_model # function you'll define
|
4 |
+
from PIL import Image
|
5 |
+
import torch
|
6 |
+
|
7 |
+
st.title("Object Dimension Estimator using Detectron2")
|
8 |
+
|
9 |
+
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "png", "jpeg"])
|
10 |
+
|
11 |
+
if uploaded_file:
|
12 |
+
image = Image.open(uploaded_file).convert("RGB")
|
13 |
+
st.image(image, caption="Uploaded Image", use_column_width=True)
|
14 |
+
|
15 |
+
st.write("Running detection and dimension estimation...")
|
16 |
+
detectron = load_detectron_model()
|
17 |
+
dimensions = predict_dimensions(image, detectron)
|
18 |
+
|
19 |
+
st.success(f"Estimated Dimensions (LxWxH): {dimensions}")
|
det_model.py
ADDED
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import torch
|
3 |
+
import torchvision.transforms as T
|
4 |
+
import numpy as np
|
5 |
+
import cv2
|
6 |
+
from PIL import Image, UnidentifiedImageError
|
7 |
+
import os
|
8 |
+
import subprocess # For Detectron2 installation check
|
9 |
+
import sys # For Detectron2 installation check
|
10 |
+
|
11 |
+
# --- Detectron2 Imports (handle potential import errors) ---
|
12 |
+
d2_imported_successfully = False
|
13 |
+
try:
|
14 |
+
import detectron2
|
15 |
+
from detectron2.engine import DefaultPredictor
|
16 |
+
from detectron2.config import get_cfg
|
17 |
+
from detectron2 import model_zoo
|
18 |
+
from detectron2.utils.visualizer import Visualizer, ColorMode
|
19 |
+
from detectron2.data import MetadataCatalog
|
20 |
+
from detectron2.structures import Boxes # For Bounding Boxes
|
21 |
+
d2_imported_successfully = True
|
22 |
+
print("Detectron2 utilities imported successfully.")
|
23 |
+
except ImportError:
|
24 |
+
st.error("Detectron2 not found or not installed correctly. Please ensure it's installed in your environment.")
|
25 |
+
print("❌ Failed to import Detectron2 utilities.")
|
26 |
+
except Exception as e:
|
27 |
+
st.error(f"An error occurred during Detectron2 imports: {e}")
|
28 |
+
print(f"❌ An error occurred during Detectron2 imports: {e}")
|
29 |
+
|
30 |
+
|
31 |
+
# --- PyTorch Model Imports ---
|
32 |
+
from torchvision import models as torchvision_models
|
33 |
+
import torch.nn as nn
|
34 |
+
|
35 |
+
# ------------------------------
|
36 |
+
# Configuration
|
37 |
+
# ------------------------------
|
38 |
+
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
39 |
+
CNN_INPUT_SIZE = 224
|
40 |
+
IMAGENET_MEAN = [0.485, 0.456, 0.406]
|
41 |
+
IMAGENET_STD = [0.229, 0.224, 0.225]
|
42 |
+
# Ensure this path is correct for your environment
|
43 |
+
MODEL_PATH = r"pix3d_dimension_estimator_mask_crop.pth"
|
44 |
+
OUTPUT_DIR = 'streamlit_d2_output'
|
45 |
+
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
46 |
+
|
47 |
+
|
48 |
+
# ------------------------------
|
49 |
+
# Dimension Estimation CNN
|
50 |
+
# ------------------------------
|
51 |
+
def create_dimension_estimator_cnn_for_inference(num_outputs=4):
|
52 |
+
model = torchvision_models.resnet50(weights=None) # Load architecture only
|
53 |
+
num_ftrs = model.fc.in_features
|
54 |
+
model.fc = nn.Sequential(
|
55 |
+
nn.Linear(num_ftrs, 512),
|
56 |
+
nn.ReLU(),
|
57 |
+
nn.Dropout(0.5),
|
58 |
+
nn.Linear(512, num_outputs) # Outputs L, W, H, V
|
59 |
+
)
|
60 |
+
return model
|
61 |
+
|
62 |
+
@st.cache_resource
|
63 |
+
def load_dimension_model():
|
64 |
+
model = None
|
65 |
+
if not os.path.exists(MODEL_PATH):
|
66 |
+
st.error(f"Dimension estimation model not found at {MODEL_PATH}. Please check the path.")
|
67 |
+
return None
|
68 |
+
try:
|
69 |
+
model = create_dimension_estimator_cnn_for_inference()
|
70 |
+
model.load_state_dict(torch.load(MODEL_PATH, map_location=DEVICE))
|
71 |
+
model.to(DEVICE)
|
72 |
+
model.eval()
|
73 |
+
print(f"Dimension estimation model loaded from {MODEL_PATH}")
|
74 |
+
except Exception as e:
|
75 |
+
st.error(f"Error loading dimension estimation model: {e}")
|
76 |
+
return None
|
77 |
+
return model
|
78 |
+
|
79 |
+
# ------------------------------
|
80 |
+
# Detectron2 Model
|
81 |
+
# ------------------------------
|
82 |
+
@st.cache_resource
|
83 |
+
def load_detectron2_model():
|
84 |
+
if not d2_imported_successfully:
|
85 |
+
return None, None
|
86 |
+
try:
|
87 |
+
cfg = get_cfg()
|
88 |
+
# Example: Mask R-CNN for instance segmentation
|
89 |
+
cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
|
90 |
+
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 # Set threshold for detection
|
91 |
+
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
|
92 |
+
if not torch.cuda.is_available():
|
93 |
+
cfg.MODEL.DEVICE = "cpu"
|
94 |
+
else:
|
95 |
+
cfg.MODEL.DEVICE = "cuda" # Explicitly set
|
96 |
+
predictor = DefaultPredictor(cfg)
|
97 |
+
print("Detectron2 predictor created.")
|
98 |
+
return predictor, cfg
|
99 |
+
except Exception as e:
|
100 |
+
st.error(f"Error loading Detectron2 model: {e}")
|
101 |
+
return None, None
|
102 |
+
|
103 |
+
# ------------------------------
|
104 |
+
# Helper Functions
|
105 |
+
# ------------------------------
|
106 |
+
def get_largest_instance_index(instances):
|
107 |
+
"""Returns the index of the largest instance based on mask area or box area."""
|
108 |
+
if not len(instances):
|
109 |
+
return -1 # No instances
|
110 |
+
|
111 |
+
if instances.has("pred_masks"):
|
112 |
+
areas = instances.pred_masks.sum(dim=(1,2)) # Sum of True pixels in boolean mask
|
113 |
+
if len(areas) > 0:
|
114 |
+
return areas.argmax().item()
|
115 |
+
elif instances.has("pred_boxes"):
|
116 |
+
boxes_tensor = instances.pred_boxes.tensor
|
117 |
+
areas = (boxes_tensor[:, 2] - boxes_tensor[:, 0]) * (boxes_tensor[:, 3] - boxes_tensor[:, 1])
|
118 |
+
if len(areas) > 0:
|
119 |
+
return areas.argmax().item()
|
120 |
+
return 0 # Default to first instance if area calculation fails or no masks/boxes
|
121 |
+
|
122 |
+
def crop_from_mask(image_np_rgb, mask_tensor):
|
123 |
+
"""Crops an object from an image using a boolean mask tensor."""
|
124 |
+
mask_np = mask_tensor.cpu().numpy().astype(np.uint8) # Ensure mask is on CPU and uint8
|
125 |
+
if mask_np.sum() == 0: return None # Empty mask
|
126 |
+
|
127 |
+
rows = np.any(mask_np, axis=1)
|
128 |
+
cols = np.any(mask_np, axis=0)
|
129 |
+
if not np.any(rows) or not np.any(cols): return None
|
130 |
+
|
131 |
+
ymin, ymax = np.where(rows)[0][[0, -1]]
|
132 |
+
xmin, xmax = np.where(cols)[0][[0, -1]]
|
133 |
+
|
134 |
+
# Add padding to the bounding box from mask
|
135 |
+
padding = 5
|
136 |
+
ymin = max(0, ymin - padding)
|
137 |
+
xmin = max(0, xmin - padding)
|
138 |
+
ymax = min(image_np_rgb.shape[0] - 1, ymax + padding)
|
139 |
+
xmax = min(image_np_rgb.shape[1] - 1, xmax + padding)
|
140 |
+
|
141 |
+
|
142 |
+
if ymin >= ymax or xmin >= xmax : return None
|
143 |
+
cropped_image = image_np_rgb[ymin:ymax+1, xmin:xmax+1, :]
|
144 |
+
return cropped_image
|
145 |
+
|
146 |
+
def predict_dimensions_cnn(image_patch_np_rgb, model):
|
147 |
+
"""Predicts dimensions using the custom CNN."""
|
148 |
+
if model is None:
|
149 |
+
return {"L": "N/A", "W": "N/A", "H": "N/A", "V": "N/A", "Note": "DimCNN not loaded"}
|
150 |
+
try:
|
151 |
+
if image_patch_np_rgb.dtype != np.uint8:
|
152 |
+
image_patch_np_rgb = image_patch_np_rgb.astype(np.uint8)
|
153 |
+
|
154 |
+
transform = T.Compose([
|
155 |
+
T.ToPILImage(),
|
156 |
+
T.Resize((CNN_INPUT_SIZE, CNN_INPUT_SIZE)),
|
157 |
+
T.ToTensor(),
|
158 |
+
T.Normalize(mean=IMAGENET_MEAN, std=IMAGENET_STD)
|
159 |
+
])
|
160 |
+
input_tensor = transform(image_patch_np_rgb).unsqueeze(0).to(DEVICE)
|
161 |
+
with torch.no_grad():
|
162 |
+
pred = model(input_tensor)
|
163 |
+
dims = pred.squeeze().cpu().tolist()
|
164 |
+
|
165 |
+
if not isinstance(dims, list): dims = [dims]
|
166 |
+
while len(dims) < 4: dims.append(0.0) # Pad if model outputs fewer
|
167 |
+
|
168 |
+
# Assuming model was trained to output in meters, convert to cm for display
|
169 |
+
L_cm = dims[0] * 100
|
170 |
+
W_cm = dims[1] * 100
|
171 |
+
H_cm = dims[2] * 100
|
172 |
+
V_cm3 = dims[3] * 1_000_000 # Convert m^3 to cm^3
|
173 |
+
|
174 |
+
return {
|
175 |
+
"Length (cm)": f"{L_cm:.1f}",
|
176 |
+
"Width (cm)": f"{W_cm:.1f}",
|
177 |
+
"Height (cm)": f"{H_cm:.1f}",
|
178 |
+
"Volume (cm³)": f"{V_cm3:.1f}",
|
179 |
+
"Note": "CustomCNN (Pix3D Scale)"
|
180 |
+
}
|
181 |
+
except Exception as e:
|
182 |
+
print(f"Error in predict_dimensions_cnn: {e}")
|
183 |
+
return {"L": "N/A", "W": "N/A", "H": "N/A", "V": "N/A", "Note": "CNN Predict Error"}
|
184 |
+
|
185 |
+
# ------------------------------
|
186 |
+
# Streamlit UI
|
187 |
+
# ------------------------------
|
188 |
+
st.set_page_config(layout="wide", page_title="Object Dimension Estimator")
|
189 |
+
st.title("📦 Object Dimension & Volume Estimation")
|
190 |
+
st.write("Upload an image. The system will detect objects using Detectron2, draw bounding boxes and masks, and estimate dimensions for the largest detected object using a custom-trained CNN.")
|
191 |
+
|
192 |
+
# Load models
|
193 |
+
dim_model = load_dimension_model()
|
194 |
+
if d2_imported_successfully:
|
195 |
+
d2_predictor, d2_cfg = load_detectron2_model()
|
196 |
+
if d2_cfg is not None:
|
197 |
+
# Attempt to get metadata, handle potential KeyErrors
|
198 |
+
try:
|
199 |
+
d2_metadata = MetadataCatalog.get(d2_cfg.DATASETS.TRAIN[0] if d2_cfg.DATASETS.TRAIN else "coco_2017_val")
|
200 |
+
except KeyError:
|
201 |
+
st.warning("Default COCO metadata not found. Trying 'coco_2017_train'. Class names might be generic if this also fails.")
|
202 |
+
try:
|
203 |
+
d2_metadata = MetadataCatalog.get("coco_2017_train")
|
204 |
+
except KeyError:
|
205 |
+
st.warning("Could not load standard COCO metadata. Using dummy metadata.")
|
206 |
+
dummy_name = "streamlit_dummy_coco_dataset_main"
|
207 |
+
if dummy_name not in MetadataCatalog.list():
|
208 |
+
MetadataCatalog.get(dummy_name).thing_classes = [f"class_{i}" for i in range(80)] # COCO has 80 classes
|
209 |
+
d2_metadata = MetadataCatalog.get(dummy_name)
|
210 |
+
else:
|
211 |
+
d2_metadata = None # Set to None if cfg is None
|
212 |
+
else:
|
213 |
+
d2_predictor = None
|
214 |
+
d2_cfg = None
|
215 |
+
d2_metadata = None
|
216 |
+
|
217 |
+
|
218 |
+
uploaded_file = st.file_uploader("Upload a single image (JPG/PNG)", accept_multiple_files=False, type=['jpg', 'jpeg', 'png'])
|
219 |
+
|
220 |
+
if uploaded_file:
|
221 |
+
st.subheader(f"🖼️ Processing: {uploaded_file.name}")
|
222 |
+
try:
|
223 |
+
image_pil = Image.open(uploaded_file).convert("RGB")
|
224 |
+
image_np_rgb = np.array(image_pil) # Convert PIL to NumPy RGB
|
225 |
+
image_bgr = cv2.cvtColor(image_np_rgb, cv2.COLOR_RGB2BGR) # OpenCV BGR for Detectron2
|
226 |
+
except UnidentifiedImageError:
|
227 |
+
st.error("Cannot identify image file. Please upload a valid image.")
|
228 |
+
image_bgr = None
|
229 |
+
except Exception as e:
|
230 |
+
st.error(f"Error loading image: {e}")
|
231 |
+
image_bgr = None
|
232 |
+
|
233 |
+
if image_bgr is not None:
|
234 |
+
st.image(image_pil, caption="Uploaded Image", use_container_width=True)
|
235 |
+
|
236 |
+
if d2_predictor is None or dim_model is None:
|
237 |
+
st.error("One or more models (Detectron2, Dimension CNN) failed to load. Cannot process.")
|
238 |
+
else:
|
239 |
+
with st.spinner("Detecting objects and estimating dimensions..."):
|
240 |
+
# --- Detectron2 Inference ---
|
241 |
+
outputs = d2_predictor(image_bgr) # Detectron2 expects BGR
|
242 |
+
instances = outputs["instances"].to("cpu")
|
243 |
+
|
244 |
+
if len(instances) == 0:
|
245 |
+
st.warning("No objects detected by Detectron2.")
|
246 |
+
else:
|
247 |
+
# --- Visualization with Bounding Boxes and Masks ---
|
248 |
+
# Create a copy for drawing Detectron2's full visualization
|
249 |
+
viz_image_bgr = image_bgr.copy()
|
250 |
+
v = Visualizer(viz_image_bgr[:, :, ::-1], metadata=d2_metadata, scale=0.8, instance_mode=ColorMode.IMAGE_BW)
|
251 |
+
out_vis = v.draw_instance_predictions(instances)
|
252 |
+
annotated_img_d2_rgb = out_vis.get_image()[:, :, ::-1] # Visualizer gives RGB
|
253 |
+
|
254 |
+
st.image(annotated_img_d2_rgb, caption="Detectron2 Detections (Masks & Boxes)", use_container_width=True)
|
255 |
+
|
256 |
+
# --- Process the largest detected instance for dimension estimation ---
|
257 |
+
largest_idx = get_largest_instance_index(instances)
|
258 |
+
if largest_idx != -1:
|
259 |
+
instance = instances[largest_idx]
|
260 |
+
|
261 |
+
class_name = "Unknown"
|
262 |
+
if instance.has("pred_classes") and d2_metadata and hasattr(d2_metadata, 'thing_classes'):
|
263 |
+
class_id = instance.pred_classes.item()
|
264 |
+
if class_id < len(d2_metadata.thing_classes):
|
265 |
+
class_name = d2_metadata.thing_classes[class_id]
|
266 |
+
score = instance.scores.item() if instance.has("scores") else 0.0
|
267 |
+
st.write(f"**Processing largest detected object:** {class_name} (Confidence: {score:.2f})")
|
268 |
+
|
269 |
+
# --- Crop from Mask for Custom CNN ---
|
270 |
+
if instance.has("pred_masks"):
|
271 |
+
mask_tensor = instance.pred_masks[0] # Get the mask for the largest instance
|
272 |
+
# Crop from the RGB numpy array
|
273 |
+
object_crop_rgb = crop_from_mask(image_np_rgb, mask_tensor)
|
274 |
+
|
275 |
+
if object_crop_rgb is not None and object_crop_rgb.shape[0] > 0 and object_crop_rgb.shape[1] > 0:
|
276 |
+
st.image(object_crop_rgb, caption="Cropped Object Patch for Dimension CNN", width=250) # Smaller display
|
277 |
+
|
278 |
+
# --- Predict Dimensions with Custom CNN ---
|
279 |
+
dims = predict_dimensions_cnn(object_crop_rgb, dim_model)
|
280 |
+
st.write("📏 **Predicted Dimensions (from Custom CNN):**")
|
281 |
+
st.json(dims)
|
282 |
+
else:
|
283 |
+
st.error("Could not crop a valid object patch from the mask.")
|
284 |
+
else:
|
285 |
+
st.warning("No segmentation mask found for the largest instance. Cannot estimate dimensions with custom CNN.")
|
286 |
+
else:
|
287 |
+
st.info("Could not determine the largest object to process for dimensions.")
|
288 |
+
else:
|
289 |
+
if uploaded_file: # If a file was uploaded but image_bgr is None
|
290 |
+
st.error("Image could not be loaded for processing.")
|
291 |
+
|
292 |
+
|
293 |
+
# --- Status Footer ---
|
294 |
+
st.sidebar.markdown("---")
|
295 |
+
st.sidebar.subheader("ℹ️ System Status")
|
296 |
+
st.sidebar.markdown(f"**Processing Device:** `{DEVICE}`")
|
297 |
+
st.sidebar.markdown(f"**Detectron2 Predictor:** `{'Loaded' if d2_predictor else 'Not Loaded'}`")
|
298 |
+
st.sidebar.markdown(f"**Dimension CNN:** `{'Loaded' if dim_model else 'Not Loaded'}`")
|
299 |
+
if not os.path.exists(MODEL_PATH):
|
300 |
+
st.sidebar.warning(f"Dimension CNN weights file not found at the specified path.")
|
301 |
+
|
hf.py
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from huggingface_hub import HfApi
|
2 |
+
import os
|
3 |
+
|
4 |
+
api = HfApi(token=os.getenv("HF_TOKEN"))
|
5 |
+
api.upload_folder(
|
6 |
+
folder_path=r"C:\Users\pc\TLproj\detectron_model",
|
7 |
+
repo_id="suryaprakash01/dimension_Detect",
|
8 |
+
repo_type="model",
|
9 |
+
)
|
pix3d_dimension_estimator_mask_crop.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:9ab2ec97426df1b3d74e7c9c22760edb774ae3f0015afe1f69ad5ba087356950
|
3 |
+
size 98564182
|
requirements.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
torch
|
3 |
+
torchvision
|
4 |
+
Pillow
|
5 |
+
numpy
|
6 |
+
opencv-python-headless
|
7 |
+
detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu118/torch2.1/index.html
|