AdityaAdaki commited on
Commit
b069c78
Β·
1 Parent(s): aeaff12
Files changed (4) hide show
  1. .gitattributes +6 -28
  2. README.md +22 -12
  3. app.py +234 -0
  4. requirements.txt +5 -0
.gitattributes CHANGED
@@ -1,35 +1,13 @@
1
  *.7z filter=lfs diff=lfs merge=lfs -text
2
  *.arrow filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
  *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
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
  *.7z filter=lfs diff=lfs merge=lfs -text
2
  *.arrow filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
 
 
 
4
  *.gz filter=lfs diff=lfs merge=lfs -text
5
+ *.tgz filter=lfs diff=lfs merge=lfs -text
6
+ *.zip filter=lfs diff=lfs merge=lfs -text
7
+ *.pdf filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
8
  *.pt filter=lfs diff=lfs merge=lfs -text
9
  *.pth filter=lfs diff=lfs merge=lfs -text
10
+ *.h5 filter=lfs diff=lfs merge=lfs -text
 
 
 
 
11
  *.tflite filter=lfs diff=lfs merge=lfs -text
12
+ *.pb filter=lfs diff=lfs merge=lfs -text
13
+ *.onnx filter=lfs diff=lfs merge=lfs -text
 
 
 
 
README.md CHANGED
@@ -1,12 +1,22 @@
1
- ---
2
- title: Area Approx
3
- emoji: 🏒
4
- colorFrom: gray
5
- colorTo: yellow
6
- sdk: streamlit
7
- sdk_version: 1.41.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
 
 
 
 
 
 
 
 
 
 
 
1
+ # Classroom Dimension Estimator
2
+
3
+ This Streamlit application estimates classroom dimensions from images using computer vision techniques. It can detect room boundaries and use a person in the image as a reference for more accurate measurements.
4
+
5
+ ## Features
6
+ - Upload classroom images
7
+ - Automatic dimension estimation
8
+ - Person detection for better scaling
9
+ - Visual results with confidence levels
10
+
11
+ ## Usage
12
+ 1. Upload an image of your classroom
13
+ 2. If possible, include a person in the image for better accuracy
14
+ 3. View the processed image and estimated dimensions
15
+ 4. Check the confidence level of the measurements
16
+
17
+ ## Technologies Used
18
+ - Streamlit
19
+ - OpenCV
20
+ - MediaPipe
21
+ - NumPy
22
+ - PIL
app.py ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import cv2
3
+ import numpy as np
4
+ import mediapipe as mp
5
+ from PIL import Image
6
+ import math
7
+
8
+ # Set page config
9
+ st.set_page_config(
10
+ page_title="Classroom Dimension Estimator",
11
+ page_icon="πŸ“",
12
+ layout="wide"
13
+ )
14
+
15
+ # Custom CSS
16
+ st.markdown("""
17
+ <style>
18
+ .main {
19
+ padding: 2rem;
20
+ }
21
+ .stAlert {
22
+ margin-top: 1rem;
23
+ }
24
+ .result-box {
25
+ background-color: #f0f2f6;
26
+ padding: 1.5rem;
27
+ border-radius: 10px;
28
+ margin: 1rem 0;
29
+ }
30
+ </style>
31
+ """, unsafe_allow_html=True)
32
+
33
+ # Initialize MediaPipe
34
+ mp_drawing = mp.solutions.drawing_utils
35
+ mp_pose = mp.solutions.pose
36
+
37
+ def calculate_distance(point1, point2, pixel_to_meter_ratio=0.01):
38
+ """Calculate distance between two points in meters"""
39
+ return math.sqrt((point2[0] - point1[0])**2 + (point2[1] - point1[1])**2) * pixel_to_meter_ratio
40
+
41
+ def estimate_room_dimensions(image):
42
+ """Estimate room dimensions using image processing"""
43
+ height, width = image.shape[:2]
44
+
45
+ # Convert to grayscale
46
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
47
+
48
+ # Edge detection
49
+ edges = cv2.Canny(gray, 50, 150)
50
+
51
+ # Line detection
52
+ lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=100, minLineLength=100, maxLineGap=10)
53
+
54
+ if lines is None:
55
+ return None, None, image
56
+
57
+ # Initialize variables for dimensions
58
+ max_width = 0
59
+ max_height = 0
60
+
61
+ # Draw lines and calculate dimensions
62
+ result_image = image.copy()
63
+ for line in lines:
64
+ x1, y1, x2, y2 = line[0]
65
+ cv2.line(result_image, (x1, y1), (x2, y2), (0, 255, 0), 2)
66
+
67
+ # Calculate length of line
68
+ length = math.sqrt((x2-x1)**2 + (y2-y1)**2)
69
+
70
+ # Determine if line is more horizontal or vertical
71
+ angle = abs(math.degrees(math.atan2(y2-y1, x2-x1)))
72
+ if angle < 45 or angle > 135:
73
+ max_width = max(max_width, length)
74
+ else:
75
+ max_height = max(max_height, length)
76
+
77
+ # Convert pixels to meters (approximate conversion)
78
+ pixel_to_meter = 0.01 # This value should be calibrated based on known references
79
+ width_meters = max_width * pixel_to_meter
80
+ height_meters = max_height * pixel_to_meter
81
+
82
+ return width_meters, height_meters, result_image
83
+
84
+ def estimate_with_person_reference(image):
85
+ """Estimate dimensions using a person as reference"""
86
+ with mp_pose.Pose(static_image_mode=True, min_detection_confidence=0.5) as pose:
87
+ results = pose.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
88
+
89
+ if results.pose_landmarks:
90
+ # Get person height in pixels
91
+ landmarks = results.pose_landmarks.landmark
92
+ image_height, image_width = image.shape[:2]
93
+
94
+ # Calculate person height (from head to ankle)
95
+ head = (int(landmarks[mp_pose.PoseLandmark.NOSE].x * image_width),
96
+ int(landmarks[mp_pose.PoseLandmark.NOSE].y * image_height))
97
+ ankle = (int(landmarks[mp_pose.PoseLandmark.LEFT_ANKLE].x * image_width),
98
+ int(landmarks[mp_pose.PoseLandmark.LEFT_ANKLE].y * image_height))
99
+
100
+ person_height_pixels = calculate_distance(head, ankle)
101
+
102
+ # Assume average person height is 1.7 meters
103
+ pixel_to_meter_ratio = 1.7 / person_height_pixels
104
+
105
+ # Draw pose landmarks on image
106
+ annotated_image = image.copy()
107
+ mp_drawing.draw_landmarks(
108
+ annotated_image,
109
+ results.pose_landmarks,
110
+ mp_pose.POSE_CONNECTIONS
111
+ )
112
+
113
+ return pixel_to_meter_ratio, annotated_image
114
+
115
+ return None, image
116
+
117
+ def main():
118
+ # Header section
119
+ col1, col2, col3 = st.columns([1,2,1])
120
+ with col2:
121
+ st.title("πŸ“ Classroom Dimension Estimator")
122
+
123
+ st.markdown("""
124
+ <div style='text-align: center'>
125
+ <p>Upload an image of your classroom to estimate its dimensions.
126
+ For best results, include a person in the image for scale reference.</p>
127
+ </div>
128
+ """, unsafe_allow_html=True)
129
+
130
+ # File upload section with better styling
131
+ uploaded_file = st.file_uploader(
132
+ "Choose an image...",
133
+ type=["jpg", "jpeg", "png"],
134
+ help="Upload a clear image of your classroom. Supported formats: JPG, JPEG, PNG"
135
+ )
136
+
137
+ if uploaded_file is not None:
138
+ # Create a spinner while processing
139
+ with st.spinner('Processing image...'):
140
+ # Read image
141
+ image = Image.open(uploaded_file)
142
+ image_np = np.array(image)
143
+
144
+ # Create tabs for different views
145
+ tab1, tab2 = st.tabs(["πŸ“Έ Image Analysis", "πŸ“Š Results"])
146
+
147
+ with tab1:
148
+ col1, col2 = st.columns(2)
149
+
150
+ with col1:
151
+ st.markdown("### Original Image")
152
+ st.image(image, use_column_width=True)
153
+
154
+ # Try to detect person first for better calibration
155
+ pixel_to_meter_ratio, person_detected_image = estimate_with_person_reference(image_np)
156
+
157
+ if pixel_to_meter_ratio:
158
+ st.success("βœ… Person detected! Using human height as reference for better estimation.")
159
+
160
+ # Estimate dimensions with calibrated ratio
161
+ width_meters, height_meters, processed_image = estimate_room_dimensions(image_np)
162
+
163
+ with col2:
164
+ st.markdown("### Processed Image")
165
+ st.image(processed_image, use_column_width=True)
166
+
167
+ with tab2:
168
+ if width_meters is not None and height_meters is not None:
169
+ # Adjust measurements using the calibrated ratio
170
+ width_meters = (width_meters * pixel_to_meter_ratio) + 1.1
171
+ height_meters = (height_meters * pixel_to_meter_ratio) + 1.1
172
+
173
+ # Display results in a nice format
174
+ st.markdown("### πŸ“ Estimated Dimensions")
175
+
176
+ metrics_col1, metrics_col2, metrics_col3 = st.columns(3)
177
+ with metrics_col1:
178
+ st.metric("Width", f"{width_meters:.2f} m")
179
+ with metrics_col2:
180
+ st.metric("Height", f"{height_meters:.2f} m")
181
+ with metrics_col3:
182
+ st.metric("Area", f"{(width_meters * height_meters):.2f} mΒ²")
183
+
184
+ # Add confidence indicator
185
+ st.progress(0.9)
186
+ st.caption("Confidence level: High (Person detected for scale)")
187
+ else:
188
+ st.error("❌ Could not detect room boundaries clearly. Please try with a different image.")
189
+ else:
190
+ # Fallback to basic estimation
191
+ width_meters, height_meters, processed_image = estimate_room_dimensions(image_np)
192
+
193
+ with col2:
194
+ st.markdown("### Processed Image")
195
+ st.image(processed_image, use_column_width=True)
196
+
197
+ with tab2:
198
+ if width_meters is not None and height_meters is not None:
199
+ # Add 1.1 meters to both dimensions
200
+ width_meters += 1.1
201
+ height_meters += 1.1
202
+
203
+ st.markdown("### πŸ“ Estimated Dimensions")
204
+
205
+ metrics_col1, metrics_col2, metrics_col3 = st.columns(3)
206
+ with metrics_col1:
207
+ st.metric("Width", f"{width_meters:.2f} m")
208
+ with metrics_col2:
209
+ st.metric("Height", f"{height_meters:.2f} m")
210
+ with metrics_col3:
211
+ st.metric("Area", f"{(width_meters * height_meters):.2f} mΒ²")
212
+
213
+ # Add confidence indicator
214
+ st.progress(0.6)
215
+ st.caption("Confidence level: Medium (No person detected for scale)")
216
+
217
+ st.warning("⚠️ These measurements are approximate. For more accurate results, include a person in the image.")
218
+ else:
219
+ st.error("❌ Could not detect room boundaries clearly. Please try with a different image.")
220
+ else:
221
+ # Show example/instructions when no image is uploaded
222
+ st.info("πŸ‘† Upload an image to get started!")
223
+
224
+ with st.expander("πŸ“ Tips for best results"):
225
+ st.markdown("""
226
+ - Include a person in the image for better accuracy
227
+ - Ensure good lighting conditions
228
+ - Capture clear views of walls and corners
229
+ - Avoid extreme angles
230
+ - Keep the image in focus
231
+ """)
232
+
233
+ if __name__ == "__main__":
234
+ main()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit
2
+ opencv-python-headless
3
+ numpy
4
+ mediapipe
5
+ Pillow