Skip to content

Commit 6ac86c4

Browse files
authored
Merge pull request #3 from techstartucalgary/arham
Arham
2 parents 05b30dd + 916deb1 commit 6ac86c4

File tree

4 files changed

+166
-1
lines changed

4 files changed

+166
-1
lines changed

.gitignore

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
22

3-
# dependencies
3+
# Python
4+
__pycache__/
5+
*.py[cod]
6+
*$py.class
7+
*.so
8+
.Python
9+
venv/
10+
env/
11+
ENV/
12+
.venv
13+
14+
# Node.js / Next.js
415
/node_modules
516
/.pnp
617
.pnp.js
@@ -17,6 +28,7 @@
1728

1829
# misc
1930
.DS_Store
31+
Thumbs.db
2032
*.pem
2133

2234
# debug
@@ -33,3 +45,10 @@ yarn-error.log*
3345
# typescript
3446
*.tsbuildinfo
3547
next-env.d.ts
48+
49+
# IDE
50+
.vscode/
51+
.idea/
52+
*.swp
53+
*.swo
54+
*~
37.8 MB
Binary file not shown.

backend-workflow/blurry.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import cv2
2+
import numpy as np
3+
4+
def is_blurry(img_path):
5+
img = cv2.imread(img_path)
6+
if img is None:
7+
return False
8+
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
9+
laplacian = cv2.Laplacian(gray, cv2.CV_64F)
10+
cv2.imshow("img", img)
11+
cv2.imshow("gray", gray)
12+
cv2.imshow("laplacian", laplacian)
13+
cv2.waitKey(0)
14+
cv2.destroyAllWindows()
15+
score = laplacian.var()
16+
return score < 100
17+
18+
def check_contrast_brightness(img_path, min_contrast=40.0, min_brightness=30.0, max_brightness=230.0):
19+
img = cv2.imread(img_path)
20+
if img is None:
21+
return {
22+
'has_sufficient_contrast': False,
23+
'has_good_brightness': False,
24+
'contrast_score': 0.0,
25+
'brightness_score': 0.0,
26+
'is_acceptable': False
27+
}
28+
29+
# Convert to grayscale for analysis
30+
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
31+
32+
# Calculate contrast (standard deviation of pixel intensities)
33+
# Higher std dev = more contrast between different regions
34+
contrast_score = float(gray.std())
35+
has_sufficient_contrast = contrast_score >= min_contrast
36+
37+
# Calculate brightness (mean pixel intensity)
38+
# Values range from 0 (black) to 255 (white)
39+
brightness_score = float(gray.mean())
40+
has_good_brightness = min_brightness <= brightness_score <= max_brightness
41+
42+
is_acceptable = has_sufficient_contrast and has_good_brightness
43+
44+
return {
45+
'has_sufficient_contrast': has_sufficient_contrast,
46+
'has_good_brightness': has_good_brightness,
47+
'contrast_score': contrast_score,
48+
'brightness_score': brightness_score,
49+
'is_acceptable': is_acceptable
50+
}
51+
52+
def check_aspect_ratio(img_path, min_ratio=0.7, max_ratio=1.4):
53+
img = cv2.imread(img_path)
54+
if img is None:
55+
return {
56+
'has_valid_aspect_ratio': False,
57+
'aspect_ratio': 0.0,
58+
'width': 0,
59+
'height': 0,
60+
'ratio_description': 'invalid'
61+
}
62+
63+
height, width = img.shape[:2]
64+
65+
# Calculate min(width, height) / max(width, height)
66+
# This gives a value between 0 and 1, where 1 means square
67+
min_dim = min(width, height)
68+
max_dim = max(width, height)
69+
aspect_ratio = float(min_dim) / float(max_dim)
70+
71+
# Check if ratio is within valid range: 0.7 ≤ ratio ≤ 1.4
72+
# Note: Since min/max ratio is always ≤ 1.0, the effective range is 0.7 to 1.0
73+
has_valid_aspect_ratio = min_ratio <= aspect_ratio <= max_ratio
74+
75+
# Calculate traditional width:height ratio for description
76+
width_height_ratio = float(width) / float(height)
77+
78+
# Create a readable description of the ratio
79+
if 0.95 <= width_height_ratio <= 1.05:
80+
ratio_description = "1:1 (square)"
81+
elif width_height_ratio < 1.0:
82+
# Portrait orientation (height > width)
83+
simplified_ratio = f"1:{1/width_height_ratio:.2f}"
84+
ratio_description = f"{simplified_ratio} (portrait)"
85+
else:
86+
# Landscape orientation (width > height)
87+
simplified_ratio = f"{width_height_ratio:.2f}:1"
88+
ratio_description = f"{simplified_ratio} (landscape)"
89+
90+
return {
91+
'has_valid_aspect_ratio': has_valid_aspect_ratio,
92+
'aspect_ratio': aspect_ratio, # This is min/max ratio
93+
'width_height_ratio': width_height_ratio, # Traditional width:height ratio
94+
'width': width,
95+
'height': height,
96+
'ratio_description': ratio_description
97+
}
98+
99+
if __name__ == "__main__":
100+
img_path = "test5.png" # Relative path for cross-platform compatibility
101+
102+
# Blurriness check
103+
blurry = is_blurry(img_path)
104+
print("blurry" if blurry else "not blurry")
105+
106+
# Contrast/Brightness check
107+
result = check_contrast_brightness(img_path)
108+
print("bright/contrasted enough" if result['is_acceptable'] else "not bright/contrasted enough")
109+
110+
# Aspect Ratio check
111+
aspect_result = check_aspect_ratio(img_path)
112+
print("valid aspect ratio" if aspect_result['has_valid_aspect_ratio'] else "invalid aspect ratio")

backend-workflow/predict.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import tensorflow as tf
2+
from tensorflow import keras
3+
from tensorflow.keras.utils import load_img, img_to_array
4+
import numpy as np
5+
import sys
6+
from pathlib import Path
7+
8+
# Get the directory where the model is located
9+
script_dir = Path(__file__).parent
10+
model_path = script_dir / 'binary_image_classifier_model.keras'
11+
model = keras.models.load_model(str(model_path))
12+
13+
# Get image path from command line
14+
img_path = sys.argv[1]
15+
16+
# Load image and convert to array
17+
img = load_img(img_path, target_size=(180, 180))
18+
img_array = img_to_array(img)
19+
img_array = np.expand_dims(img_array, axis=0)
20+
21+
# Make prediction
22+
prediction = model.predict(img_array, verbose=0)
23+
score = prediction[0][0]
24+
25+
# Display results
26+
print(f"\nImage: {Path(img_path).name}")
27+
print(f"Raw prediction score: {score:.4f}")
28+
print(f"Threshold: 0.5\n")
29+
if score > 0.5:
30+
print("[+] FLOOR PLAN DETECTED")
31+
print(f"Confidence: {score:.2%}")
32+
else:
33+
print("[-] NOT A FLOOR PLAN")
34+
print(f"Confidence: {(1-score):.2%}")

0 commit comments

Comments
 (0)