diff --git a/Team 104- Skin Disease Analysis/assets/test_images/BCC-test.jpg b/Team 104- Skin Disease Analysis/assets/test_images/BCC-test.jpg new file mode 100644 index 00000000..d087994b Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/BCC-test.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/Benign Keratosis-like Lesions (BKL)-test.jpg b/Team 104- Skin Disease Analysis/assets/test_images/Benign Keratosis-like Lesions (BKL)-test.jpg new file mode 100644 index 00000000..7da992c0 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/Benign Keratosis-like Lesions (BKL)-test.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/Benign-keratosis.png b/Team 104- Skin Disease Analysis/assets/test_images/Benign-keratosis.png new file mode 100644 index 00000000..e9633d39 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/Benign-keratosis.png differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/Eczema.png b/Team 104- Skin Disease Analysis/assets/test_images/Eczema.png new file mode 100644 index 00000000..66f5defe Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/Eczema.png differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/Lichen Planus.jpg b/Team 104- Skin Disease Analysis/assets/test_images/Lichen Planus.jpg new file mode 100644 index 00000000..7d7ef8fd Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/Lichen Planus.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/Psoriasis Lichen Planus and related diseases-test.jpg b/Team 104- Skin Disease Analysis/assets/test_images/Psoriasis Lichen Planus and related diseases-test.jpg new file mode 100644 index 00000000..bdd4c282 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/Psoriasis Lichen Planus and related diseases-test.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/Seborrheic Keratoses -test.jpg b/Team 104- Skin Disease Analysis/assets/test_images/Seborrheic Keratoses -test.jpg new file mode 100644 index 00000000..6ce4580d Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/Seborrheic Keratoses -test.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/Tinea Ringworm Candidiasis and other Fungal Infections-test.png b/Team 104- Skin Disease Analysis/assets/test_images/Tinea Ringworm Candidiasis and other Fungal Infections-test.png new file mode 100644 index 00000000..fc73e268 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/Tinea Ringworm Candidiasis and other Fungal Infections-test.png differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/aptopic derm.jpg b/Team 104- Skin Disease Analysis/assets/test_images/aptopic derm.jpg new file mode 100644 index 00000000..86d75d01 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/aptopic derm.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/atopic-test.png b/Team 104- Skin Disease Analysis/assets/test_images/atopic-test.png new file mode 100644 index 00000000..8dc31fda Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/atopic-test.png differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/melanocytic nevi-test.jpg b/Team 104- Skin Disease Analysis/assets/test_images/melanocytic nevi-test.jpg new file mode 100644 index 00000000..50177364 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/melanocytic nevi-test.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/melanoma-test.jpg b/Team 104- Skin Disease Analysis/assets/test_images/melanoma-test.jpg new file mode 100644 index 00000000..0f6fc3a0 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/melanoma-test.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/seborrheic keratosis.jpg b/Team 104- Skin Disease Analysis/assets/test_images/seborrheic keratosis.jpg new file mode 100644 index 00000000..33b1f4ec Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/seborrheic keratosis.jpg differ diff --git a/Team 104- Skin Disease Analysis/assets/test_images/warts molluscum.jpg b/Team 104- Skin Disease Analysis/assets/test_images/warts molluscum.jpg new file mode 100644 index 00000000..83e2e592 Binary files /dev/null and b/Team 104- Skin Disease Analysis/assets/test_images/warts molluscum.jpg differ diff --git a/Team 104- Skin Disease Analysis/core/feature_extraction/__pycache__/extractor.cpython-313.pyc b/Team 104- Skin Disease Analysis/core/feature_extraction/__pycache__/extractor.cpython-313.pyc new file mode 100644 index 00000000..bbc92c3a Binary files /dev/null and b/Team 104- Skin Disease Analysis/core/feature_extraction/__pycache__/extractor.cpython-313.pyc differ diff --git a/Team 104- Skin Disease Analysis/core/feature_extraction/__pycache__/loading.cpython-313.pyc b/Team 104- Skin Disease Analysis/core/feature_extraction/__pycache__/loading.cpython-313.pyc new file mode 100644 index 00000000..07f1474b Binary files /dev/null and b/Team 104- Skin Disease Analysis/core/feature_extraction/__pycache__/loading.cpython-313.pyc differ diff --git a/Team 104- Skin Disease Analysis/core/feature_extraction/extractor.py b/Team 104- Skin Disease Analysis/core/feature_extraction/extractor.py new file mode 100644 index 00000000..41079c69 --- /dev/null +++ b/Team 104- Skin Disease Analysis/core/feature_extraction/extractor.py @@ -0,0 +1,72 @@ +import os +import glob +import cv2 +import numpy as np +from skimage.feature import local_binary_pattern +from sklearn.neighbors import KDTree + +# Constants +IMG_SIZE = (128, 128) + +# ------------------------------ +# Feature Extraction Function +# ------------------------------ +def extract_features(image): + image = cv2.resize(image, IMG_SIZE) + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + + # Color Histogram (RGB) + hist = cv2.calcHist([image], [0, 1, 2], None, [8, 8, 8], + [0, 256, 0, 256, 0, 256]) + hist = cv2.normalize(hist, hist).flatten() + + # LBP Texture + lbp = local_binary_pattern(gray, P=8, R=1, method='uniform') + (lbp_hist, _) = np.histogram(lbp.ravel(), + bins=np.arange(0, 11), + range=(0, 10)) + lbp_hist = lbp_hist.astype("float") + lbp_hist /= (lbp_hist.sum() + 1e-7) + + return np.hstack([hist, lbp_hist]) + + +# ------------------------------ +# Dataset Loader + KDTree Builder +# ------------------------------ +def load_dataset_and_build_kdtree(dataset_path): + features_list = [] + labels_list = [] + label_map = {} + label_names = sorted(os.listdir(dataset_path)) + + for idx, disease_folder in enumerate(label_names): + full_path = os.path.join(dataset_path, disease_folder) + if not os.path.isdir(full_path): + continue + + label_clean = disease_folder.split(' ')[0].strip().lower().replace(' ', '_') + label_map[idx] = label_clean + + for ext in ('*.jpg', '*.jpeg', '*.png'): + for img_path in glob.glob(os.path.join(full_path, ext)): + try: + img = cv2.imread(img_path) + if img is None: + continue + feat = extract_features(img) + features_list.append(feat) + labels_list.append(idx) + except Exception as e: + print(f"Error with {img_path}: {e}") + + features_array = np.array(features_list) + labels_array = np.array(labels_list) + + if len(features_array) > 0: + tree = KDTree(features_array) + print(f"โœ… KD-Tree built with {features_array.shape[0]} feature vectors.") + return tree, features_array, labels_array, label_map + else: + print("โš ๏ธ No features extracted. Please check your image folder paths and formats.") + return None, None, None, None diff --git a/Team 104- Skin Disease Analysis/core/feature_extraction/loading.py b/Team 104- Skin Disease Analysis/core/feature_extraction/loading.py new file mode 100644 index 00000000..cc0259f6 --- /dev/null +++ b/Team 104- Skin Disease Analysis/core/feature_extraction/loading.py @@ -0,0 +1,26 @@ +# import numpy as np +# from sklearn.neighbors import KDTree +# import pickle + +# def load_features_and_tree(path='features_tree.pkl'): +# with open(path, 'rb') as f: +# data = pickle.load(f) +# return data['tree'], data['features'], data['labels'], data['label_map'] + +import pickle +import numpy as np + +def load_kdtree(): + with open('kdtree.pkl', 'rb') as f: + tree = pickle.load(f) + return tree + +def load_features(): + return np.load('features.npy') + +def load_labels(): + return np.load('labels.npy') + +def load_label_map(): + with open('label_map.pkl', 'rb') as f: + return pickle.load(f) diff --git a/Team 104- Skin Disease Analysis/core/severity_scoring/__pycache__/severity_minheap.cpython-313.pyc b/Team 104- Skin Disease Analysis/core/severity_scoring/__pycache__/severity_minheap.cpython-313.pyc new file mode 100644 index 00000000..95a67154 Binary files /dev/null and b/Team 104- Skin Disease Analysis/core/severity_scoring/__pycache__/severity_minheap.cpython-313.pyc differ diff --git a/Team 104- Skin Disease Analysis/core/severity_scoring/severity_minheap.py b/Team 104- Skin Disease Analysis/core/severity_scoring/severity_minheap.py new file mode 100644 index 00000000..466fc970 --- /dev/null +++ b/Team 104- Skin Disease Analysis/core/severity_scoring/severity_minheap.py @@ -0,0 +1,63 @@ +import csv +import heapq + +# Global dictionary to store per-disease severity weights +SEVERITY_WEIGHTS = {} + +def load_severity_weights(csv_path='data/severity_weights.csv'): + global SEVERITY_WEIGHTS + with open(csv_path, mode='r', encoding='utf-8') as file: + reader = csv.DictReader(file) + for row in reader: + disease = row["Disease"].strip() + SEVERITY_WEIGHTS[disease] = { + "pain_level": float(row["pain_level"]), + "itching_level": float(row["itching_level"]), + "duration_days": float(row["duration_days"]), + "area_factor": float(row["area_factor"]), + "fever_present": float(row["fever_present"]), + "bleeding": float(row["bleeding"]), + "spread_rate_factor": float(row["spread_rate_factor"]), + } + +class SeverityScorer: + def __init__(self): + self.heap = [] # Heap of (score, disease) + self.direct_scores = {} # Optional raw score addition + + def add_raw_score(self, disease, score): + """Add precomputed score (e.g., from image similarity)""" + self.direct_scores[disease] = self.direct_scores.get(disease, 0) + score + + def calculate_and_add_score(self, disease, pain_level, itching_level, duration_days, max_duration, + area_factor, fever_present, bleeding, spread_rate_factor): + """ + Calculates weighted severity using global SEVERITY_WEIGHTS. + """ + if disease not in SEVERITY_WEIGHTS: + return + + weights = SEVERITY_WEIGHTS[disease] + score = ( + weights.get("pain_level", 0) * (pain_level / 10) + + weights.get("itching_level", 0) * (itching_level / 10) + + weights.get("duration_days", 0) * (duration_days / max_duration if max_duration else 0) + + weights.get("area_factor", 0) * area_factor + + weights.get("fever_present", 0) * int(fever_present) + + weights.get("bleeding", 0) * int(bleeding) + + weights.get("spread_rate_factor", 0) * spread_rate_factor + ) + + heapq.heappush(self.heap, (round(score, 4), disease)) + + def get_most_severe(self): + if self.heap: + return heapq.nlargest(1, self.heap)[0] + if self.direct_scores: + return max(self.direct_scores.items(), key=lambda x: x[1]) + return None + + def get_all_ranked(self): + if self.heap: + return heapq.nlargest(len(self.heap), self.heap) + return sorted(self.direct_scores.items(), key=lambda x: x[1], reverse=True) diff --git a/Team 104- Skin Disease Analysis/core/symptom_checker/__pycache__/symptom_trie.cpython-313.pyc b/Team 104- Skin Disease Analysis/core/symptom_checker/__pycache__/symptom_trie.cpython-313.pyc new file mode 100644 index 00000000..da35a515 Binary files /dev/null and b/Team 104- Skin Disease Analysis/core/symptom_checker/__pycache__/symptom_trie.cpython-313.pyc differ diff --git a/Team 104- Skin Disease Analysis/core/symptom_checker/symptom_trie.py b/Team 104- Skin Disease Analysis/core/symptom_checker/symptom_trie.py new file mode 100644 index 00000000..5a0f6604 --- /dev/null +++ b/Team 104- Skin Disease Analysis/core/symptom_checker/symptom_trie.py @@ -0,0 +1,33 @@ +class TrieNode: + def __init__(self): + self.children = {} + self.is_end = False + self.diseases = set() + +class SymptomTrie: + def __init__(self): + self.root = TrieNode() + + def insert(self, symptom, disease): + node = self.root + for char in symptom.lower(): + if char not in node.children: + node.children[char] = TrieNode() + node = node.children[char] + node.is_end = True + node.diseases.add(disease) + + def search(self, prefix): + node = self.root + for char in prefix.lower(): + if char in node.children: + node = node.children[char] + else: + return set() + return self._collect_diseases(node) + + def _collect_diseases(self, node): + results = set(node.diseases) + for child in node.children.values(): + results.update(self._collect_diseases(child)) + return results diff --git a/Team 104- Skin Disease Analysis/core/treatment_suggester/__pycache__/treatment_map.cpython-313.pyc b/Team 104- Skin Disease Analysis/core/treatment_suggester/__pycache__/treatment_map.cpython-313.pyc new file mode 100644 index 00000000..668a8a5c Binary files /dev/null and b/Team 104- Skin Disease Analysis/core/treatment_suggester/__pycache__/treatment_map.cpython-313.pyc differ diff --git a/Team 104- Skin Disease Analysis/core/treatment_suggester/treatment_map.py b/Team 104- Skin Disease Analysis/core/treatment_suggester/treatment_map.py new file mode 100644 index 00000000..9bba35b7 --- /dev/null +++ b/Team 104- Skin Disease Analysis/core/treatment_suggester/treatment_map.py @@ -0,0 +1,26 @@ +import csv + +class TreatmentMap: + def __init__(self, csv_path): + self.map = {} + with open(csv_path, mode='r', encoding='utf-8') as f: + reader = csv.DictReader(f) + for row in reader: + disease = row['Disease'].strip() + treatments = [t.strip() for t in row['Recommended Treatment'].split(',')] + self.map[disease] = treatments # Disease as key, list of treatments as value + + def get_treatment(self, disease_name): + # Get the list of treatments for a given disease name + return self.map.get(disease_name, ["Consult a specialist for tailored treatment."]) + + def match_symptoms(self, input_symptoms): + # Match input symptoms to diseases and return diseases with common symptoms + input_set = set(s.strip().lower() for s in input_symptoms.split(',')) + matches = [] + + for disease in self.map.keys(): + # Placeholder: Add symptom matching logic here + matches.append(disease) + + return matches diff --git a/Team 104- Skin Disease Analysis/data/disease_info.csv b/Team 104- Skin Disease Analysis/data/disease_info.csv new file mode 100644 index 00000000..b93b3fa5 --- /dev/null +++ b/Team 104- Skin Disease Analysis/data/disease_info.csv @@ -0,0 +1,11 @@ +Disease,Common Symptoms,Severity Level,Recommended Treatment,ICD-10 Code +Eczema,"Dry skin, itching, red patches, inflammation, scaling, crusting, redness, cracked skin, swelling",Moderate,"Topical corticosteroids, moisturizers, antihistamines",L20.9 +"Warts, Molluscum, and other Viral Infections","Raised bumps, rough texture, small flesh-colored growths, sometimes itchy or painful, small bumps, brown growths, itching",Mild,"Cryotherapy, salicylic acid, topical antivirals",B07.9 +Melanoma,"New or changing mole, asymmetry, irregular borders, varied colors, bleeding, itching",Severe,"Surgical excision, immunotherapy, targeted therapy",C43.9 +Atopic Dermatitis,"Intense itching, dry scaly skin, red inflamed patches, especially in folds of skin, itching, rashes, swelling, crusting",Moderate,"Topical steroids, emollients, immunomodulators",L20.0 +Basal Cell Carcinoma (BCC),"Pearly or waxy bump, flat flesh-colored lesion, bleeding sore that doesn't heal, scaly area",Severe,"Mohs surgery, radiation therapy, topical chemo",C44.91 +Melanocytic Nevi (NV),"Small and dark brown spots, flat or raised moles, typically uniform in shape and color, ",Mild,"Observation, excision if suspicious or for cosmetic reasons",D22.9 +Benign Keratosis-like Lesions (BKL),"Waxy or wart-like growth, brown/tan/black, scaly surface, can be flat or slightly raised",Mild,"Cryotherapy, curettage, laser removal",L82.1 +"Psoriasis, Lichen Planus, and related diseases","Thick red patches with silvery scales, purple flat-topped bumps, severe itching, cracked skin",Moderate to Severe,"Topical corticosteroids, phototherapy, biologics",L40.9 +Seborrheic Keratoses and other Benign Tumors,"Brown/black growths, waxy/stuck-on appearance, generally painless, ",Mild,"Cryosurgery, curettage, no treatment if asymptomatic",L82.0 +"Tinea, Ringworm, Candidiasis, and other Fungal Infections","Red circular rashes, itching, peeling skin, white patches in mouth or moist areas, scaling, cracking skin",Moderate,"Topical antifungals, oral antifungals in severe cases",B35.9 diff --git a/Team 104- Skin Disease Analysis/data/disease_labels.json b/Team 104- Skin Disease Analysis/data/disease_labels.json new file mode 100644 index 00000000..ef029fa9 --- /dev/null +++ b/Team 104- Skin Disease Analysis/data/disease_labels.json @@ -0,0 +1,13 @@ +{ + "Disease_0": "Eczema", + "Disease_1": "Warts, Molluscum, and other Viral Infections", + "Disease_2": "Melanoma", + "Disease_3": "Atopic Dermatitis", + "Disease_4": "Basal Cell Carcinoma (BCC)", + "Disease_5": "Melanocytic Nevi (NV)", + "Disease_6": "Benign Keratosis-like Lesions (BKL)", + "Disease_7": "Psoriasis, Lichen Planus, and related diseases", + "Disease_8": "Seborrheic Keratoses and other Benign Tumors", + "Disease_9": "Tinea, Ringworm, Candidiasis, and other Fungal Infections" + } + \ No newline at end of file diff --git a/Team 104- Skin Disease Analysis/data/severity_weights.csv b/Team 104- Skin Disease Analysis/data/severity_weights.csv new file mode 100644 index 00000000..c376bb44 --- /dev/null +++ b/Team 104- Skin Disease Analysis/data/severity_weights.csv @@ -0,0 +1,11 @@ +Disease,pain_level,itching_level,duration_days,area_factor,fever_present,bleeding,spread_rate_factor +Eczema,0.15,0.25,0.1,0.2,0.05,0.1,0.15 +"Warts, Molluscum, and other Viral Infections",0.2,0.1,0.1,0.25,0.05,0.1,0.2 +Melanoma,0.1,0.05,0.1,0.2,0.2,0.15,0.2 +Atopic Dermatitis,0.1,0.3,0.1,0.15,0.05,0.1,0.2 +Basal Cell Carcinoma (BCC),0.15,0.1,0.15,0.2,0.1,0.15,0.15 +Melanocytic Nevi (NV),0.05,0.05,0.1,0.3,0.05,0.1,0.35 +Benign Keratosis-like Lesions (BKL),0.05,0.1,0.1,0.25,0.05,0.15,0.3 +"Psoriasis, Lichen Planus, and related diseases",0.1,0.25,0.1,0.2,0.05,0.1,0.2 +Seborrheic Keratoses and other Benign Tumors,0.05,0.1,0.1,0.25,0.05,0.1,0.35 +"Tinea, Ringworm, Candidiasis, and other Fungal Infections",0.1,0.25,0.1,0.2,0.05,0.05,0.25 diff --git a/Team 104- Skin Disease Analysis/main.py b/Team 104- Skin Disease Analysis/main.py new file mode 100644 index 00000000..3fb9c772 --- /dev/null +++ b/Team 104- Skin Disease Analysis/main.py @@ -0,0 +1,851 @@ +# import os +# import cv2 +# import numpy as np +# from skimage.feature import local_binary_pattern +# from sklearn.neighbors import KDTree +# import streamlit as st +# from PIL import Image +# import json +# import sys + +# from core.feature_extraction.extractor import extract_features +# from core.feature_extraction.loading import load_kdtree, load_labels, load_label_map +# from core.severity_scoring.severity_minheap import SeverityScorer, SEVERITY_WEIGHTS +# from core.treatment_suggester.treatment_map import TreatmentMap +# from core.symptom_checker.symptom_trie import SymptomTrie + +# # Adjust system path if needed +# sys.path.append('C:/Users/aryas/OneDrive/Desktop/skin_disease_detector') + +# # Dataset and constants +# DATASET_PATH = '/kaggle/input/skin-diseases-image-dataset/IMG_CLASSES' +# IMG_SIZE = (128, 128) + +# # Load necessary resources +# tree = load_kdtree() +# labels = load_labels() +# label_map = load_label_map() +# treatment_map = TreatmentMap(r'C:\Users\aryas\OneDrive\Desktop\skin_disease_detector\data\disease_info.csv') +# scorer = SeverityScorer() + +# # Streamlit UI +# st.set_page_config(page_title="Skin Disease Detector", layout="wide") +# st.title("๐Ÿฉบ AI-Powered Skin Disease Analyzer") + +# tab1, tab2 = st.tabs(["๐Ÿ“ท Disease Detection", "๐Ÿ“ Symptom Checker"]) + +# # ------------------ TAB 1 ------------------ +# with tab1: +# uploaded_file = st.file_uploader("Upload a skin image", type=['jpg', 'jpeg', 'png']) + +# if uploaded_file: +# image = Image.open(uploaded_file) +# st.image(image, caption="Uploaded Image", use_container_width=True) + +# img_cv = np.array(image.convert('RGB'))[:, :, ::-1] +# feat = extract_features(img_cv).reshape(1, -1) + +# dist, idx = tree.query(feat, k=5) + +# st.subheader("๐Ÿ” Top Predictions:") +# diseases = [] +# for i in range(len(idx[0])): +# label_id = labels[idx[0][i]] +# # If label_map uses integer keys: +# disease = label_map.get(label_id, f"Disease_{label_id}") +# # If label_map uses string keys: +# disease = label_map.get(str(label_id), f"Disease_{label_id}") + +# diseases.append(disease) +# score = round(1 / (dist[0][i] + 1e-6), 2) +# scorer.add_raw_score(disease, score) +# st.markdown(f"**{disease}** (Score: {score})") + +# _, top_disease = scorer.get_most_severe() +# if not isinstance(top_disease, str): +# top_disease = str(top_disease) + +# st.success(f"๐Ÿงช Most Likely: **{top_disease}**") + +# st.subheader("๐Ÿ“Š Severity Scoring") +# with st.form("severity_form"): +# pain_level = st.slider("Pain Level", 0, 10, 5) +# itching_level = st.slider("Itching Level", 0, 10, 5) +# duration_days = st.number_input("Duration of Symptoms (days)", min_value=0, value=5) +# max_duration = st.number_input("Max Expected Duration (days)", min_value=1, value=10) +# area_factor = st.slider("Affected Area Percentage", 0.0, 1.0, 0.2) +# fever_present = st.checkbox("Fever Present?") +# bleeding = st.checkbox("Bleeding Observed?") +# spread_rate_factor = st.slider("Spread Rate (0.0 - stable to 1.0 - spreading fast)", 0.0, 1.0, 0.3) +# submitted = st.form_submit_button("Compute Severity") + +# if submitted: +# def compute_weighted_severity(disease): +# weights = SEVERITY_WEIGHTS.get(disease, {}) +# score = ( +# weights.get("pain_level", 0) * (pain_level / 10) + +# weights.get("itching_level", 0) * (itching_level / 10) + +# weights.get("duration_days", 0) * (duration_days / max_duration) + +# weights.get("area_factor", 0) * area_factor + +# weights.get("fever_present", 0) * (1 if fever_present else 0) + +# weights.get("bleeding", 0) * (1 if bleeding else 0) + +# weights.get("spread_rate_factor", 0) * spread_rate_factor +# ) +# return max(round(score, 3), 0.01) + +# severity_score = compute_weighted_severity(top_disease) +# st.metric(label=f"๐Ÿ”ฅ Severity Score for {top_disease}", value=severity_score) + +# st.subheader("๐Ÿ’Š Recommended Treatment:") +# try: +# treatment_info = treatment_map.get_treatment(top_disease) +# except Exception as e: +# treatment_info = f"Error fetching treatment info: {str(e)}" +# st.info(treatment_info) + +# # ------------------ TAB 2 ------------------ +# with tab2: +# st.subheader("๐Ÿง  Enter Symptoms to Predict Possible Diseases") +# symptoms_input = st.text_input("Enter symptoms separated by commas (e.g. itchy skin, redness, dry patches)") + +# if symptoms_input: +# symptoms = [s.strip() for s in symptoms_input.split(',') if s.strip()] +# trie = SymptomTrie() + +# # Sample mappings +# trie.insert("itchy skin", "Eczema") +# trie.insert("redness", "Rosacea") +# trie.insert("dry patches", "Psoriasis") +# trie.insert("oozing blisters", "Impetigo") +# trie.insert("scaly rash", "Ringworm") + +# all_diseases = set() +# for symptom in symptoms: +# matched = trie.search(symptom) +# all_diseases.update(matched) + +# if all_diseases: +# st.success("๐Ÿฉป Possible Diseases Based on Symptoms:") +# for dis in sorted(all_diseases): +# st.markdown(f"- **{dis}**") +# st.markdown(f" ๐Ÿ’Š *{treatment_map.get_treatment(dis)}*") +# else: +# st.warning("No matches found. Try different or simpler symptom terms.") + +import os +import glob +import cv2 +import numpy as np +from skimage.feature import local_binary_pattern +from sklearn.neighbors import KDTree +import streamlit as st +from PIL import Image +from core.feature_extraction.extractor import extract_features +from core.feature_extraction.loading import load_kdtree, load_labels, load_label_map +from core.severity_scoring.severity_minheap import SeverityScorer +from core.treatment_suggester.treatment_map import TreatmentMap +from core.symptom_checker.symptom_trie import SymptomTrie +from core.severity_scoring.severity_minheap import SEVERITY_WEIGHTS +import sys +import json +with open("data/disease_labels.json") as f: + label_map = json.load(f) +sys.path.append('C:/Users/aryas/OneDrive/Desktop/skin_disease_detector') + +# ๐Ÿ‘‡ Add disease_labels here +disease_labels = { + 0: "Eczema", + 1: "Melanoma", + 2: "Psoriasis", + 3: "Atopic Dermatitis", + 4: "Basal Cell Carcinoma (BCC)", + 5: "Actinic Keratosis" +} + +# Dataset path and image size constants +DATASET_PATH = '/kaggle/input/skin-diseases-image-dataset/IMG_CLASSES' +IMG_SIZE = (128, 128) # Resize images + +# 1. Helper Function to Extract Features +def extract_features(image): + # Resize + image = cv2.resize(image, IMG_SIZE) + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + + # Color Histogram + hist = cv2.calcHist([image], [0, 1, 2], None, [8, 8, 8], + [0, 256, 0, 256, 0, 256]) + hist = cv2.normalize(hist, hist).flatten() + + # LBP Texture Features + lbp = local_binary_pattern(gray, P=8, R=1, method='uniform') + (lbp_hist, _) = np.histogram(lbp.ravel(), + bins=np.arange(0, 10), + range=(0, 9)) + lbp_hist = lbp_hist.astype("float") + lbp_hist /= (lbp_hist.sum() + 1e-7) + + # Final Feature Vector + features = np.hstack([hist, lbp_hist]) + return features + +# ==================== Streamlit Interface ==================== +# Load pre-trained model +tree = load_kdtree() # Pre-trained KDTree for image feature matching +labels = load_labels() # Labels corresponding to each feature vector +label_map = load_label_map() # Mapping of label IDs to disease names +treatment_map = TreatmentMap(r'C:\Users\aryas\OneDrive\Desktop\skin_disease_detector\data\disease_info.csv') +# Initialize Severity Scorer +scorer = SeverityScorer() + +st.set_page_config(page_title="Skin Disease Detector", layout="wide") +st.title("๐Ÿฉบ AI-Powered Skin Disease Analyzer") + +tab1, tab2 = st.tabs(["๐Ÿ“ท Disease Detection", "๐Ÿ“ Symptom Checker"]) + +# ===================== TAB 1: IMAGE DIAGNOSIS ==================== +with tab1: + uploaded_file = st.file_uploader("Upload a skin image", type=['jpg', 'jpeg', 'png']) + + if uploaded_file is None: + st.warning("Please upload a valid image file.") + + if uploaded_file: + # Display uploaded image + image = Image.open(uploaded_file) + st.image(image, caption="Uploaded Image", use_container_width=True) + + img_cv = np.array(image.convert('RGB'))[:, :, ::-1] # Convert to OpenCV format + feat = extract_features(img_cv) # Extract features + + # Ensure feat is a 1D array (reshape if necessary) + feat = feat.reshape(1, -1) + + # Perform the KD-tree query to find the closest matches + dist, idx = tree.query(feat, k=5) + + # Display top disease predictions and severity scoring + st.subheader("๐Ÿ” Top Predictions:") + diseases = [] + for i in range(len(idx[0])): + label_id = labels[idx[0][i]] + + # Fetch disease name from label_map + disease = label_map.get(str(label_id), f"Disease_{label_id}") + diseases.append(disease) + score = round(1 / (dist[0][i] + 1e-6), 2) # Avoid division by zero + + scorer.add_raw_score(disease, score) + st.markdown(f"**{disease}** (Score: {score})") + + # Get most severe prediction + _, top_disease = scorer.get_most_severe() + + # Ensure top_disease is a string + if not isinstance(top_disease, str): + top_disease = str(top_disease) + + st.success(f"๐Ÿงช Most Likely: **{top_disease}**") + + st.subheader("๐Ÿ“Š Severity Scoring") + + # Severity scoring form + with st.form("severity_form"): + pain_level = st.slider("Pain Level", 0, 10, 5) + itching_level = st.slider("Itching Level", 0, 10, 5) + duration_days = st.number_input("Duration of Symptoms (days)", min_value=0, value=5) + max_duration = st.number_input("Max Expected Duration (days)", min_value=1, value=10) + area_factor = st.slider("Affected Area Percentage", 0.0, 1.0, 0.2) + fever_present = st.checkbox("Fever Present?") + bleeding = st.checkbox("Bleeding Observed?") + spread_rate_factor = st.slider("Spread Rate (0.0 - stable to 1.0 - spreading fast)", 0.0, 1.0, 0.3) + submitted = st.form_submit_button("Compute Severity") + + if submitted: + def compute_weighted_severity(disease): + weights = SEVERITY_WEIGHTS.get(disease, {}) + score = ( + weights.get("pain_level", 0) * (pain_level / 10) + + weights.get("itching_level", 0) * (itching_level / 10) + + weights.get("duration_days", 0) * (duration_days / max_duration) + + weights.get("area_factor", 0) * area_factor + + weights.get("fever_present", 0) * (1 if fever_present else 0) + + weights.get("bleeding", 0) * (1 if bleeding else 0) + + weights.get("spread_rate_factor", 0) * spread_rate_factor + ) + return max(round(score, 3), 0.01) # Ensure score isn't zero + + severity_score = compute_weighted_severity(top_disease) + st.metric(label=f"๐Ÿ”ฅ Severity Score for {top_disease}", value=severity_score) + + st.subheader("๐Ÿ’Š Recommended Treatment:") + + + + # Assuming treatment_map is already loaded in the code + try: + treatment_info = treatment_map.get_treatment(top_disease) + except Exception as e: + treatment_info = f"Error fetching treatment info: {str(e)}" + + st.info(treatment_info) + +# ===================== TAB 2: SYMPTOM CHECKER ==================== +with tab2: + st.subheader("๐Ÿง  Enter Symptoms to Predict Possible Diseases") + symptoms_input = st.text_input("Enter symptoms separated by commas (e.g. itchy skin, redness, dry patches)") + + if symptoms_input: + symptoms = [s.strip() for s in symptoms_input.split(',') if s.strip()] + trie = SymptomTrie() + + # Sample symptom-disease mappings (can be expanded or loaded from CSV) + trie.insert("itchy skin", "Eczema") + trie.insert("redness", "Rosacea") + trie.insert("dry patches", "Psoriasis") + trie.insert("oozing blisters", "Impetigo") + trie.insert("scaly rash", "Ringworm") + + all_diseases = set() + for symptom in symptoms: + matched = trie.search(symptom) + all_diseases.update(matched) + + if all_diseases: + st.success("๐Ÿฉป Possible Diseases Based on Symptoms:") + for dis in sorted(all_diseases): + st.markdown(f"- **{dis}**") + st.markdown(f" ๐Ÿ’Š *{treatment_map.get_treatment(dis)}*") + else: + st.warning("No matches found. Try different or simpler symptom terms.") + + +# # # # import streamlit as st +# # # # import cv2 +# # # # import numpy as np +# # # # from PIL import Image + +# # # # from core.feature_extraction.extractor import extract_features +# # # # from core.feature_extraction.loading import load_kdtree, load_labels, load_label_map +# # # # from core.severity_scoring.severity_minheap import SeverityScorer +# # # # from core.symptom_checker.symptom_trie import SymptomTrie +# # # # from core.treatment_suggester.treatment_map import TreatmentMap +# # # # from core.severity_scoring.severity_minheap import load_severity_weights, SEVERITY_WEIGHTS + +# # # # # Load weights at the beginning +# # # # load_severity_weights("data/severity_weights.csv") + +# # # # # Load model/data only once +# # # # tree = load_kdtree() +# # # # labels = load_labels() +# # # # label_map = load_label_map() +# # # # treatment_map = TreatmentMap('data/disease_info.csv') + +# # # # st.set_page_config(page_title="Skin Disease Detector", layout="wide") +# # # # st.title("๐Ÿฉบ AI-Powered Skin Disease Analyzer") + +# # # # tab1, tab2 = st.tabs(["๐Ÿ“ท Disease Detection", "๐Ÿ“ Symptom Checker"]) + +# # # # # ===================== TAB 1: IMAGE DIAGNOSIS ==================== +# # # # with tab1: +# # # # uploaded_file = st.file_uploader("Upload a skin image", type=['jpg', 'jpeg', 'png']) + +# # # # if uploaded_file is None: +# # # # st.warning("Please upload a valid image file.") + +# # # # if uploaded_file: +# # # # image = Image.open(uploaded_file) +# # # # st.image(image, caption="Uploaded Image", use_container_width=True) + +# # # # img_cv = np.array(image.convert('RGB'))[:, :, ::-1] +# # # # feat = extract_features(img_cv) +# # # # dist, idx = tree.query([feat], k=5) + +# # # # st.subheader("๐Ÿ” Top Predictions:") +# # # # diseases = [] +# # # # scorer = SeverityScorer() + +# # # # for i in range(len(idx[0])): +# # # # label_id = labels[idx[0][i]] + +# # # # # Ensure label_id is str and mapped correctly +# # # # disease = label_map.get(str(label_id), f"Disease_{label_id}") + +# # # # diseases.append(disease) +# # # # score = round(1 / (dist[0][i] + 1e-6), 2) # Avoid division by zero +# # # # scorer.add_raw_score(disease, score) +# # # # # Display disease names, not scores +# # # # st.markdown(f"**{disease}** (Score: {score})") + +# # # # # Get most severe prediction (disease name) +# # # # _, top_disease = scorer.get_most_severe() + +# # # # # Ensure it's a string +# # # # if not isinstance(top_disease, str): +# # # # top_disease = str(top_disease) + +# # # # # Display the most likely disease +# # # # st.success(f"๐Ÿงช Most Likely: **{top_disease}**") + +# # # # st.subheader("๐Ÿ“Š Severity Scoring") + +# # # # with st.form("severity_form"): +# # # # pain_level = st.slider("Pain Level", 0, 10, 5) +# # # # itching_level = st.slider("Itching Level", 0, 10, 5) +# # # # duration_days = st.number_input("Duration of Symptoms (days)", min_value=0, value=5) +# # # # max_duration = st.number_input("Max Expected Duration (days)", min_value=1, value=10) +# # # # area_factor = st.slider("Affected Area Percentage", 0.0, 1.0, 0.2) +# # # # fever_present = st.checkbox("Fever Present?") +# # # # bleeding = st.checkbox("Bleeding Observed?") +# # # # spread_rate_factor = st.slider("Spread Rate (0.0 - stable to 1.0 - spreading fast)", 0.0, 1.0, 0.3) +# # # # submitted = st.form_submit_button("Compute Severity") + +# # # # if submitted: +# # # # def compute_weighted_severity(disease): +# # # # weights = SEVERITY_WEIGHTS.get(disease, {}) +# # # # score = ( +# # # # weights.get("pain_level", 0) * (pain_level / 10) + +# # # # weights.get("itching_level", 0) * (itching_level / 10) + +# # # # weights.get("duration_days", 0) * (duration_days / max_duration) + +# # # # weights.get("area_factor", 0) * area_factor + +# # # # weights.get("fever_present", 0) * (1 if fever_present else 0) + +# # # # weights.get("bleeding", 0) * (1 if bleeding else 0) + +# # # # weights.get("spread_rate_factor", 0) * spread_rate_factor +# # # # ) +# # # # return max(round(score, 3), 0.01) # Ensure score isn't zero + +# # # # severity_score = compute_weighted_severity(top_disease) +# # # # st.metric(label=f"๐Ÿ”ฅ Severity Score for {top_disease}", value=severity_score) + +# # # # st.subheader("๐Ÿ’Š Recommended Treatment:") +# # # # try: +# # # # treatment_info = treatment_map.get_treatment(top_disease) +# # # # except Exception as e: +# # # # treatment_info = f"Error fetching treatment info: {str(e)}" + +# # # # st.info(treatment_info) + + +# # # # # ===================== TAB 2: SYMPTOM CHECKER ==================== +# # # # with tab2: +# # # # st.subheader("๐Ÿง  Enter Symptoms to Predict Possible Diseases") +# # # # symptoms_input = st.text_input("Enter symptoms separated by commas (e.g. itchy skin, redness, dry patches)") + +# # # # if symptoms_input: +# # # # symptoms = [s.strip() for s in symptoms_input.split(',') if s.strip()] +# # # # trie = SymptomTrie() + +# # # # # Sample symptom-disease mappings (can be expanded or loaded from CSV) +# # # # trie.insert("itchy skin", "Eczema") +# # # # trie.insert("redness", "Rosacea") +# # # # trie.insert("dry patches", "Psoriasis") +# # # # trie.insert("oozing blisters", "Impetigo") +# # # # trie.insert("scaly rash", "Ringworm") + +# # # # all_diseases = set() +# # # # for symptom in symptoms: +# # # # matched = trie.search(symptom) +# # # # all_diseases.update(matched) + +# # # # if all_diseases: +# # # # st.success("๐Ÿฉป Possible Diseases Based on Symptoms:") +# # # # for dis in sorted(all_diseases): +# # # # st.markdown(f"- **{dis}**") +# # # # st.markdown(f" ๐Ÿ’Š *{treatment_map.get_treatment(dis)}*") +# # # # else: +# # # # st.warning("No matches found. Try different or simpler symptom terms.") + + + +# # # import cv2 +# # # import numpy as np +# # # from PIL import Image +# # # import streamlit as st +# # # from core.feature_extraction.extractor import extract_features +# # # from core.feature_extraction.loading import load_kdtree, load_labels, load_label_map +# # # from core.severity_scoring.severity_minheap import SeverityScorer +# # # from core.symptom_checker.symptom_trie import SymptomTrie +# # # from core.treatment_suggester.treatment_map import TreatmentMap +# # # from core.severity_scoring.severity_minheap import load_severity_weights, SEVERITY_WEIGHTS + +# # # # Load weights at the beginning +# # # load_severity_weights("data/severity_weights.csv") + +# # # # Load model/data only once +# # # tree = load_kdtree() +# # # labels = load_labels() +# # # label_map = load_label_map() # label_map should map label_id (int) โ†’ disease_name (str) +# # # treatment_map = TreatmentMap('data/disease_info.csv') + +# # # st.set_page_config(page_title="Skin Disease Detector", layout="wide") +# # # st.title("๐Ÿฉบ Skin Disease Analyzer") + +# # # tab1, tab2 = st.tabs(["๐Ÿ“ท Disease Detection", "๐Ÿ“ Symptom Checker"]) + +# # # # ===================== TAB 1: IMAGE DIAGNOSIS ==================== +# # # with tab1: +# # # uploaded_file = st.file_uploader("Upload a skin image", type=['jpg', 'jpeg', 'png']) + +# # # if uploaded_file is None: +# # # st.warning("Please upload a valid image file.") + +# # # if uploaded_file: +# # # image = Image.open(uploaded_file) +# # # st.image(image, caption="Uploaded Image", use_container_width=True) + +# # # img_cv = np.array(image.convert('RGB'))[:, :, ::-1] +# # # feat = extract_features(img_cv) +# # # dist, idx = tree.query([feat], k=5) + +# # # st.subheader("๐Ÿ” Top Predictions:") +# # # diseases = [] +# # # scorer = SeverityScorer() + +# # # for i in range(len(idx[0])): +# # # label_id = labels[idx[0][i]] # Ensure label_id is int +# # # disease = label_map.get(label_id, f"Disease_{label_id}") # Use int directly + +# # # diseases.append(disease) +# # # score = round(1 / (dist[0][i] + 1e-6), 2) # Avoid division by zero +# # # scorer.add_raw_score(disease, score) +# # # st.markdown(f"{disease}** (Score: {score})") + +# # # # Correct unpacking: (disease, score) +# # # top_disease, top_score = scorer.get_most_severe() + +# # # # Display the most likely disease +# # # st.success(f"๐Ÿงช Most Likely: *{top_disease}*") + +# # # st.subheader("๐Ÿ“Š Severity Scoring") + +# # # with st.form("severity_form"): +# # # pain_level = st.slider("Pain Level", 0, 10, 5) +# # # itching_level = st.slider("Itching Level", 0, 10, 5) +# # # duration_days = st.number_input("Duration of Symptoms (days)", min_value=0, value=5) +# # # max_duration = st.number_input("Max Expected Duration (days)", min_value=1, value=10) +# # # area_factor = st.slider("Affected Area Percentage", 0.0, 1.0, 0.2) +# # # fever_present = st.checkbox("Fever Present?") +# # # bleeding = st.checkbox("Bleeding Observed?") +# # # spread_rate_factor = st.slider("Spread Rate (0.0 - stable to 1.0 - spreading fast)", 0.0, 1.0, 0.3) +# # # submitted = st.form_submit_button("Compute Severity") + +# # # if submitted and top_disease: +# # # def compute_weighted_severity(disease): +# # # weights = SEVERITY_WEIGHTS.get(disease, {}) +# # # score = ( +# # # weights.get("pain_level", 0) * (pain_level / 10) + +# # # weights.get("itching_level", 0) * (itching_level / 10) + +# # # weights.get("duration_days", 0) * (duration_days / max_duration) + +# # # weights.get("area_factor", 0) * area_factor + +# # # weights.get("fever_present", 0) * (1 if fever_present else 0) + +# # # weights.get("bleeding", 0) * (1 if bleeding else 0) + +# # # weights.get("spread_rate_factor", 0) * spread_rate_factor +# # # ) +# # # return max(round(score, 3), 0.01) # Ensure score isn't zero + +# # # severity_score = compute_weighted_severity(top_disease) +# # # st.metric(label=f"๐Ÿ”ฅ Severity Score for {top_disease}", value=severity_score) + +# # # st.subheader("๐Ÿ’Š Recommended Treatment:") +# # # try: +# # # treatment_info = treatment_map.get_treatment(top_disease) +# # # except Exception as e: +# # # treatment_info = f"Error fetching treatment info: {str(e)}" + +# # # st.info(treatment_info) + +# # # # ===================== TAB 2: SYMPTOM CHECKER ==================== +# # # with tab2: +# # # st.subheader("๐Ÿง  Enter Symptoms to Predict Possible Diseases") +# # # symptoms_input = st.text_input("Enter symptoms separated by commas (e.g. itchy skin, redness, dry patches)") + +# # # if symptoms_input: +# # # symptoms = [s.strip() for s in symptoms_input.split(',') if s.strip()] +# # # trie = SymptomTrie() + +# # # # Sample symptom-disease mappings (can be expanded or loaded from CSV) +# # # trie.insert("itchy skin", "Eczema") +# # # trie.insert("redness", "Rosacea") +# # # trie.insert("dry patches", "Psoriasis") +# # # trie.insert("oozing blisters", "Impetigo") +# # # trie.insert("scaly rash", "Ringworm") + +# # # all_diseases = set() +# # # for symptom in symptoms: +# # # matched = trie.search(symptom) +# # # all_diseases.update(matched) + +# # # if all_diseases: +# # # st.success("๐Ÿฉป Possible Diseases Based on Symptoms:") +# # # for dis in sorted(all_diseases): +# # # st.markdown(f"- *{dis}*") +# # # st.markdown(f" ๐Ÿ’Š {treatment_map.get_treatment(dis)}") +# # # else: +# # # st.warning("No matches found. Try different or simpler symptom terms.") + + +# # # # Load weights at the beginning +# # # load_severity_weights("data/severity_weights.csv") + +# # # # Load model/data only once +# # # tree = load_kdtree() +# # # labels = load_labels() +# # # label_map = load_label_map() # label_map should map label_id (int) โ†’ disease_name (str) +# # # treatment_map = TreatmentMap('data/disease_info.csv') + +# # # st.set_page_config(page_title="Skin Disease Detector", layout="wide") +# # # st.title("๐Ÿฉบ AI-Powered Skin Disease Analyzer") + +# # # tab1, tab2 = st.tabs(["๐Ÿ“ท Disease Detection", "๐Ÿ“ Symptom Checker"]) + +# # # # ===================== TAB 1: IMAGE DIAGNOSIS ==================== +# # # with tab1: +# # # uploaded_file = st.file_uploader("Upload a skin image", type=['jpg', 'jpeg', 'png']) + +# # # if uploaded_file is None: +# # # st.warning("Please upload a valid image file.") + +# # # if uploaded_file: +# # # image = Image.open(uploaded_file) +# # # st.image(image, caption="Uploaded Image", use_container_width=True) + +# # # img_cv = np.array(image.convert('RGB'))[:, :, ::-1] +# # # feat = extract_features(img_cv) +# # # dist, idx = tree.query([feat], k=5) + +# # # st.subheader("๐Ÿ” Top Predictions:") +# # # diseases = [] +# # # scorer = SeverityScorer() + +# # # for i in range(len(idx[0])): +# # # label_id = labels[idx[0][i]] # Ensure label_id is int +# # # disease = label_map.get(label_id, f"Disease_{label_id}") # Use int directly + +# # # diseases.append(disease) +# # # score = round(1 / (dist[0][i] + 1e-6), 2) # Avoid division by zero +# # # scorer.add_raw_score(disease, score) +# # # st.markdown(f"{disease}** (Score: {score})") + +# # # # Correct unpacking: (disease, score) +# # # top_disease, top_score = scorer.get_most_severe() + +# # # # Display the most likely disease +# # # st.success(f"๐Ÿงช Most Likely: *{top_disease}*") + +# # # st.subheader("๐Ÿ“Š Severity Scoring") + +# # # with st.form("severity_form"): +# # # pain_level = st.slider("Pain Level", 0, 10, 5) +# # # itching_level = st.slider("Itching Level", 0, 10, 5) +# # # duration_days = st.number_input("Duration of Symptoms (days)", min_value=0, value=5) +# # # max_duration = st.number_input("Max Expected Duration (days)", min_value=1, value=10) +# # # area_factor = st.slider("Affected Area Percentage", 0.0, 1.0, 0.2) +# # # fever_present = st.checkbox("Fever Present?") +# # # bleeding = st.checkbox("Bleeding Observed?") +# # # spread_rate_factor = st.slider("Spread Rate (0.0 - stable to 1.0 - spreading fast)", 0.0, 1.0, 0.3) +# # # submitted = st.form_submit_button("Compute Severity") + +# # # if submitted and top_disease: +# # # def compute_weighted_severity(disease): +# # # weights = SEVERITY_WEIGHTS.get(disease, {}) +# # # score = ( +# # # weights.get("pain_level", 0) * (pain_level / 10) + +# # # weights.get("itching_level", 0) * (itching_level / 10) + +# # # weights.get("duration_days", 0) * (duration_days / max_duration) + +# # # weights.get("area_factor", 0) * area_factor + +# # # weights.get("fever_present", 0) * (1 if fever_present else 0) + +# # # weights.get("bleeding", 0) * (1 if bleeding else 0) + +# # # weights.get("spread_rate_factor", 0) * spread_rate_factor +# # # ) +# # # return max(round(score, 3), 0.01) # Ensure score isn't zero + +# # # severity_score = compute_weighted_severity(top_disease) +# # # st.metric(label=f"๐Ÿ”ฅ Severity Score for {top_disease}", value=severity_score) + +# # # st.subheader("๐Ÿ’Š Recommended Treatment:") +# # # try: +# # # treatment_info = treatment_map.get_treatment(top_disease) +# # # except Exception as e: +# # # treatment_info = f"Error fetching treatment info: {str(e)}" + +# # # st.info(treatment_info) + +# # # # ===================== TAB 2: SYMPTOM CHECKER ==================== +# # # with tab2: +# # # st.subheader("๐Ÿง  Enter Symptoms to Predict Possible Diseases") +# # # symptoms_input = st.text_input("Enter symptoms separated by commas (e.g. itchy skin, redness, dry patches)") + +# # # if symptoms_input: +# # # symptoms = [s.strip() for s in symptoms_input.split(',') if s.strip()] +# # # trie = SymptomTrie() + +# # # # Sample symptom-disease mappings (can be expanded or loaded from CSV) +# # # trie.insert("itchy skin", "Eczema") +# # # trie.insert("redness", "Rosacea") +# # # trie.insert("dry patches", "Psoriasis") +# # # trie.insert("oozing blisters", "Impetigo") +# # # trie.insert("scaly rash", "Ringworm") + +# # # all_diseases = set() +# # # for symptom in symptoms: +# # # matched = trie.search(symptom) +# # # all_diseases.update(matched) + +# # # if all_diseases: +# # # st.success("๐Ÿฉป Possible Diseases Based on Symptoms:") +# # # for dis in sorted(all_diseases): +# # # st.markdown(f"- *{dis}*") +# # # st.markdown(f" ๐Ÿ’Š {treatment_map.get_treatment(dis)}") +# # # else: +# # # st.warning("No matches found. Try different or simpler symptom terms.") + +# import os +# import cv2 +# import numpy as np +# from skimage.feature import local_binary_pattern +# from sklearn.neighbors import KDTree +# import streamlit as st +# from PIL import Image +# import json +# import sys + +# # Adjust system path if needed +# sys.path.append('C:/Users/aryas/OneDrive/Desktop/skin_disease_detector') + +# # Constants +# DATASET_PATH = '/kaggle/input/skin-diseases-image-dataset/IMG_CLASSES' +# IMG_SIZE = (128, 128) + +# # Feature Extraction +# def extract_features(image): +# image = cv2.resize(image, IMG_SIZE) +# gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + +# hist = cv2.calcHist([image], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256]) +# hist = cv2.normalize(hist, hist).flatten() + +# lbp = local_binary_pattern(gray, P=8, R=1, method='uniform') +# lbp_hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, 10), range=(0, 9)) +# lbp_hist = lbp_hist.astype("float") +# lbp_hist /= (lbp_hist.sum() + 1e-7) + +# return np.hstack([hist, lbp_hist]) + +# # Load Resources +# def load_kdtree(): +# with open('kdtree.pkl', 'rb') as f: +# return pickle.load(f) + +# def load_labels(): +# return np.load('labels.npy') + +# def load_label_map(): +# with open('label_map.pkl', 'rb') as f: +# return pickle.load(f) + +# class SeverityScorer: +# def __init__(self): +# self.scores = [] + +# def add_raw_score(self, disease, score): +# self.scores.append((disease, score)) + +# def get_most_severe(self): +# return max(self.scores, key=lambda x: x[1]) if self.scores else (None, None) + +# class TreatmentMap: +# def __init__(self, csv_path): +# self.treatments = {} +# # Implement CSV loading here + +# def get_treatment(self, disease): +# return self.treatments.get(disease, "Treatment information not available") + +# class SymptomTrie: +# def __init__(self): +# self.root = {} + +# def insert(self, symptom, disease): +# node = self.root +# for char in symptom: +# node = node.setdefault(char, {}) +# node['DISEASE'] = disease + +# def search(self, symptom): +# node = self.root +# for char in symptom: +# if char not in node: +# return [] +# node = node[char] +# return [node.get('DISEASE', '')] + +# # Initialize components +# tree = load_kdtree() +# labels = load_labels() +# label_map = load_label_map() +# treatment_map = TreatmentMap(r'C:\Users\aryas\OneDrive\Desktop\skin_disease_detector\data\disease_info.csv') +# scorer = SeverityScorer() + +# # Streamlit UI +# st.set_page_config(page_title="Skin Disease Detector", layout="wide") +# st.title("๐Ÿฉบ AI-Powered Skin Disease Analyzer") + +# tab1, tab2 = st.tabs(["๐Ÿ“ท Disease Detection", "๐Ÿ“ Symptom Checker"]) + +# # ------------------ TAB 1 ------------------ +# with tab1: +# uploaded_file = st.file_uploader("Upload a skin image", type=['jpg', 'jpeg', 'png']) + +# if uploaded_file: +# image = Image.open(uploaded_file) +# st.image(image, caption="Uploaded Image", use_container_width=True) + +# img_cv = np.array(image.convert('RGB'))[:, :, ::-1] +# feat = extract_features(img_cv).reshape(1, -1).astype(np.float32) + +# dist, idx = tree.query(feat, k=5) + +# # Get top disease +# top_label_id = labels[idx[0][0]] +# top_disease = label_map.get(str(top_label_id), f"Disease_{top_label_id}") + +# st.subheader("๐Ÿ” Top Predictions:") +# diseases = [] +# for i in range(len(idx[0])): +# label_id = labels[idx[0][i]] +# disease = label_map.get(str(label_id), f"Disease_{label_id}") +# diseases.append(disease) +# score = round(1 / (dist[0][i] + 1e-6), 2) +# scorer.add_raw_score(disease, score) +# st.markdown(f"**{disease}** (Score: {score})") + +# st.success(f"๐Ÿงช Most Likely: **{top_disease}**") + +# st.subheader("๐Ÿ“Š Severity Scoring") +# with st.form("severity_form"): +# pain_level = st.slider("Pain Level", 0, 10, 5) +# itching_level = st.slider("Itching Level", 0, 10, 5) +# duration_days = st.number_input("Duration of Symptoms (days)", min_value=0, value=5) +# max_duration = st.number_input("Max Expected Duration (days)", min_value=1, value=10) +# area_factor = st.slider("Affected Area Percentage", 0.0, 1.0, 0.2) +# fever_present = st.checkbox("Fever Present?") +# bleeding = st.checkbox("Bleeding Observed?") +# spread_rate_factor = st.slider("Spread Rate (0.0 - stable to 1.0 - spreading fast)", 0.0, 1.0, 0.3) +# submitted = st.form_submit_button("Compute Severity") + +# if submitted: +# def compute_weighted_severity(disease): +# weights = SEVERITY_WEIGHTS.get(disease.lower().replace(' ', '_'), {}) +# score = ( +# weights.get("pain_level", 0) * (pain_level / 10) + +# weights.get("itching_level", 0) * (itching_level / 10) + +# weights.get("duration_days", 0) * (duration_days / max_duration) + +# weights.get("area_factor", 0) * area_factor + +# weights.get("fever_present", 0) * (1 if fever_present else 0) + +# weights.get("bleeding", 0) * (1 if bleeding else 0) + +# weights.get("spread_rate_factor", 0) * spread_rate_factor +# ) +# return max(round(score, 3), 0.01) + +# severity_score = compute_weighted_severity(top_disease) +# st.metric(label=f"๐Ÿ”ฅ Severity Score for {top_disease}", value=severity_score) diff --git a/Team 104- Skin Disease Analysis/readme.md b/Team 104- Skin Disease Analysis/readme.md new file mode 100644 index 00000000..e3787898 --- /dev/null +++ b/Team 104- Skin Disease Analysis/readme.md @@ -0,0 +1,77 @@ +๐Ÿง  **Skin Disease Analyzer & Severity Predictor using Custom Data Structures** +๐Ÿฉบ Overview: This project is a hybrid intelligence system for analyzing skin disease images, assessing severity, and recommending treatments. It is uniquely designed using custom-built data structures that integrate trees, graphs, tries, hash maps, and lists โ€” tailored to optimize medical image analysis, data retrieval, and adaptive decision-making. + +๐Ÿ” Key Features Multi-scale lesion detection via a hybrid Segment Tree and Quadtree. + +Adaptive image enhancement using Skip Lists. + +Fast feature similarity search with a KD-Tree. + +Disease correlation via a Symptom Graph. + +Severity scoring based on weighted CSV rules. + +Treatment recommendations via intelligent HashMaps. + +Symptom-to-disease prediction using Trie-Graph hybrids (future scope). + +๐Ÿ“Š Custom Data Structures and Their Roles + +Structure Purpose ๐Ÿ“ Segment Tree + Quadtree Region-based lesion segmentation and multi-scale localization ๐Ÿ“‹ Skip List Adaptive image filtering (contrast, denoising) ๐ŸŒฒ KD-Tree Feature-based nearest neighbor search (color, shape, texture) ๐Ÿ•ธ๏ธ Feature Correlation Graph Symptom co-occurrence mapping and analysis ๐Ÿงฎ HashMap (Disease/Treatment Info) Quick lookup of treatment protocol, severity scores, and symptom map ๐Ÿ”ค Trie (Planned Feature) Autocomplete and symptom-to-disease navigation ๐Ÿ” Process Flow + +Image Acquisition & Preprocessing The uploaded image is split using a hybrid Segment Tree + Quadtree. +Adaptive filters (denoising, sharpening, contrast normalization) applied using a Skip List. + +Feature Extraction & Disease Matching Features are extracted using custom functions (color histograms, edge maps). +Features are embedded into a KD-Tree. + +Nearest matches are queried to find likely diseases. + +A Feature Correlation Graph (Adjacency List + HashMap) identifies co-occurring symptoms. + +Disease Severity Scoring Disease-specific weights are loaded from severity_weights.csv. +A custom formula computes a numeric severity score. + +Treatment Recommendation Using the match from KD-Tree and severity index, treatment suggestions are retrieved from a HashMap. + +Symptom to Disease Prediction (planned) Input symptoms will be parsed via Trie and connected to diseases using a graph structure. + +๐Ÿงช File Structure bash Copy Edit ๐Ÿ“ skin-disease-analyzer/ โ”‚ โ”œโ”€โ”€ main.py # Core process pipeline โ”œโ”€โ”€ extract_and_build_kdtree.py # Feature extraction and KD-Tree building โ”œโ”€โ”€ test_kdtree_query.py # KD-Tree querying โ”œโ”€โ”€ disease_info.csv # Disease metadata and symptom/treatment mapping โ”œโ”€โ”€ severity_weights.csv # Severity weights per disease/symptom โ”œโ”€โ”€ requirements.txt # Python dependencies โš™๏ธ Installation bash Copy Edit + +Clone the repo +git clone https://github.com/yourname/skin-disease-analyzer.git cd skin-disease-analyzer + +Create virtual environment +python -m venv env source env/bin/activate # or env\Scripts\activate on Windows + +Install dependencies +pip install -r requirements.txt + +โ–ถ๏ธ Running the Project bash Copy Edit + +Build the KD-Tree +python extract_and_build_kdtree.py + +Query with test features +python test_kdtree_query.py + +Run the main analyzer +python main.py ๐Ÿš€ Use Cases Dermatology diagnostics + +Smart health monitoring kiosks + +Mobile skin disease detection tools + +Research on visual symptom correlation and severity classification + +โœ… Why Custom Data Structures? โœ”๏ธ Faster multi-scale segmentation โœ”๏ธ Scalable and real-time capable โœ”๏ธ Enables interpretable decision paths โœ”๏ธ Adaptive feature processing and matching โœ”๏ธ Promotes modularity and algorithmic experimentation + +๐Ÿงญ Future Enhancements Web interface (Streamlit or Flask UI) + +Integration with medical databases + +Graph-based progression tracking over time + +Real symptom-based chatbot navigation + +Video Drive link:https://drive.google.com/drive/folders/1EXuzwrOQUltTfpvK1yEGrofSK7g7Elp0?usp=sharing diff --git a/Team 104- Skin Disease Analysis/requirements.txt b/Team 104- Skin Disease Analysis/requirements.txt new file mode 100644 index 00000000..777492e5 --- /dev/null +++ b/Team 104- Skin Disease Analysis/requirements.txt @@ -0,0 +1,201 @@ +accelerate==1.5.2 +aiohappyeyeballs==2.4.6 +aiohttp==3.11.12 +aiohttp-retry==2.9.1 +aiosignal==1.3.2 +altair==5.5.0 +annotated-types==0.7.0 +anyio==4.7.0 +APScheduler==3.11.0 +attrs==25.1.0 +bitsandbytes==0.45.3 +bleach==6.2.0 +blinker==1.9.0 +CacheControl==0.14.2 +cachetools==5.5.1 +certifi==2024.12.14 +cffi==1.17.1 +charset-normalizer==3.4.1 +click==8.1.8 +cmake==3.31.6 +colorama==0.4.6 +contourpy==1.3.1 +cryptography==44.0.0 +cycler==0.12.1 +Cython==3.0.12 +dataclasses-json==0.6.7 +datasets==3.4.0 +defusedxml==0.7.1 +dill==0.3.8 +distro==1.9.0 +et_xmlfile==2.0.0 +eval_type_backport==0.2.2 +faiss-cpu==1.10.0 +fastapi==0.115.11 +filelock==3.17.0 +firebase-admin==6.6.0 +Flask==3.1.0 +Flask-Cors==5.0.0 +fonttools==4.55.3 +frozenlist==1.5.0 +fsspec==2024.12.0 +gitdb==4.0.12 +GitPython==3.1.44 +google-api-core==2.24.1 +google-api-python-client==2.160.0 +google-auth==2.38.0 +google-auth-httplib2==0.2.0 +google-cloud-core==2.4.1 +google-cloud-firestore==2.20.0 +google-cloud-storage==3.0.0 +google-crc32c==1.6.0 +google-resumable-media==2.7.2 +googleapis-common-protos==1.66.0 +greenlet==3.1.1 +grpcio==1.70.0 +grpcio-status==1.70.0 +h11==0.14.0 +httpcore==1.0.7 +httplib2==0.22.0 +httpx==0.28.1 +httpx-sse==0.4.0 +huggingface-hub==0.29.3 +idna==3.10 +imageio==2.37.0 +itsdangerous==2.2.0 +Jinja2==3.1.5 +jiter==0.8.2 +joblib==1.4.2 +jsonpatch==1.33 +jsonpath-python==1.0.6 +jsonpointer==3.0.0 +jsonschema==4.23.0 +jsonschema-specifications==2024.10.1 +kaggle==1.7.4.2 +kiwisolver==1.4.8 +langchain==0.3.18 +langchain-community==0.3.17 +langchain-core==0.3.35 +langchain-openai==0.3.5 +langchain-text-splitters==0.3.6 +langchain-together==0.3.0 +langsmith==0.3.8 +lazy_loader==0.4 +Levenshtein==0.27.1 +lxml==5.3.1 +markdown-it-py==3.0.0 +MarkupSafe==3.0.2 +marshmallow==3.26.1 +matplotlib==3.10.0 +mdurl==0.1.2 +mistralai==1.5.1 +mpmath==1.3.0 +msgpack==1.1.0 +multidict==6.1.0 +multiprocess==0.70.16 +mypy-extensions==1.0.0 +mysql-connector-python==9.2.0 +narwhals==1.26.0 +networkx==3.4.2 +nltk==3.9.1 +numpy==2.2.1 +openai==1.61.0 +opencv-python==4.11.0.86 +openpyxl==3.1.5 +orjson==3.10.15 +packaging==24.2 +pandas==2.2.3 +pdf2image==1.17.0 +pdfminer.six==20250327 +pdfplumber==0.11.6 +peft==0.14.0 +pillow==11.1.0 +plotly==6.0.1 +plyer==2.1.0 +propcache==0.2.1 +proto-plus==1.26.0 +protobuf==5.29.3 +psutil==7.0.0 +pyarrow==19.0.0 +pyasn1==0.6.1 +pyasn1_modules==0.4.1 +pycparser==2.22 +pydantic==2.10.6 +pydantic-settings==2.7.1 +pydantic_core==2.27.2 +pydeck==0.9.1 +pyfcm==2.0.7 +Pygments==2.19.1 +PyJWT==2.10.1 +PyMuPDF==1.25.5 +pyparsing==3.2.1 +pypdfium2==4.30.1 +pyTelegramBotAPI==4.25.0 +pytesseract==0.3.13 +python-dateutil==2.9.0.post0 +python-docx==1.1.2 +python-dotenv==1.0.1 +python-Levenshtein==0.27.1 +python-slugify==8.0.4 +python-telegram-bot==21.10 +pytube==15.0.0 +pytz==2024.2 +PyYAML==6.0.2 +RapidFuzz==3.13.0 +redis==5.2.1 +referencing==0.36.2 +regex==2024.11.6 +requests==2.32.3 +requests-toolbelt==1.0.0 +rich==13.9.4 +rpds-py==0.22.3 +rsa==4.9 +safetensors==0.5.3 +schedule==1.2.2 +scikit-image==0.25.2 +scikit-learn==1.6.0 +scipy==1.15.0 +seaborn==0.13.2 +sentencepiece==0.2.0 +setuptools==76.0.0 +shellingham==1.5.4 +six==1.17.0 +smmap==5.0.2 +sniffio==1.3.1 +spotipy==2.25.0 +SQLAlchemy==2.0.38 +starlette==0.46.1 +streamlit==1.42.0 +sympy==1.13.1 +tabulate==0.9.0 +tenacity==9.0.0 +text-unidecode==1.3 +textblob==0.19.0 +threadpoolctl==3.5.0 +tifffile==2025.3.30 +tiktoken==0.9.0 +together==1.4.1 +tokenizers==0.21.1 +toml==0.10.2 +torch==2.6.0 +tornado==6.4.2 +tqdm==4.67.1 +transformers==4.49.0 +twilio==9.4.5 +typer==0.15.1 +typing-inspect==0.9.0 +typing_extensions==4.12.2 +tzdata==2024.2 +tzlocal==5.2 +uritemplate==4.1.1 +urllib3==2.3.0 +uvicorn==0.34.0 +watchdog==6.0.0 +webencodings==0.5.1 +Werkzeug==3.1.3 +wheel==0.45.1 +xgboost==2.1.3 +xxhash==3.5.0 +yarl==1.18.3 +youtube-transcript-api==0.6.3 +zstandard==0.23.0 diff --git a/Team 104- Skin Disease Analysis/scripts/extract_and_build_kdtree.py b/Team 104- Skin Disease Analysis/scripts/extract_and_build_kdtree.py new file mode 100644 index 00000000..f3d24c8f --- /dev/null +++ b/Team 104- Skin Disease Analysis/scripts/extract_and_build_kdtree.py @@ -0,0 +1,194 @@ +### Filename: extract_and_build_kdtree.py +import sys +import os +import glob +import cv2 +import numpy as np +from skimage.feature import local_binary_pattern +from sklearn.neighbors import KDTree +import pickle +import pandas as pd + +DATASET_PATH = r'C:\Users\aryas\Downloads\IMG_CLASSES' +SAVE_PATH = '.' +IMG_SIZE = (128, 128) + +# Helper: Extract features from image +def extract_features(image): + image = cv2.resize(image, IMG_SIZE) + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + + hist = cv2.calcHist([image], [0, 1, 2], None, [8, 8, 8], + [0, 256, 0, 256, 0, 256]) + hist = cv2.normalize(hist, hist).flatten() + + lbp = local_binary_pattern(gray, 8, 1, method='uniform') + lbp_hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, 10), range=(0, 9)) + lbp_hist = lbp_hist.astype("float") + lbp_hist /= (lbp_hist.sum() + 1e-7) + + return np.hstack([hist, lbp_hist]) + +def load_and_extract_features(): + features_list = [] + labels_list = [] + label_map = {} + label_names = sorted(os.listdir(DATASET_PATH)) + + for idx, disease_folder in enumerate(label_names): + full_path = os.path.join(DATASET_PATH, disease_folder) + if not os.path.isdir(full_path): + continue + + label_clean = disease_folder.split(' ')[0].strip().lower().replace(' ', '_') + label_map[idx] = label_clean + + for ext in ('*.jpg', '*.jpeg', '*.png'): + for img_path in glob.glob(os.path.join(full_path, ext)): + try: + img = cv2.imread(img_path) + if img is None: + continue + feat = extract_features(img) + features_list.append(feat) + labels_list.append(idx) + except Exception as e: + print(f"Error with {img_path}: {e}") + + return np.array(features_list), np.array(labels_list), label_map + +def build_kdtree(features_array): + return KDTree(features_array) + +def main(): + features_array, labels_array, label_map = load_and_extract_features() + if len(features_array) > 0: + tree = build_kdtree(features_array) + + with open(os.path.join(SAVE_PATH, 'kdtree.pkl'), 'wb') as f: + pickle.dump(tree, f) + + np.save(os.path.join(SAVE_PATH, 'features.npy'), features_array) + np.save(os.path.join(SAVE_PATH, 'labels.npy'), labels_array) + + with open(os.path.join(SAVE_PATH, 'label_map.pkl'), 'wb') as f: + pickle.dump(label_map, f) + print("KD-Tree, features, and labels saved.") + else: + print("No features extracted.") + +if __name__ == "__main__": + main() + +# import sys +# import os +# import glob +# import cv2 +# import numpy as np +# from skimage.feature import local_binary_pattern +# from sklearn.neighbors import KDTree +# import pickle + +# # Make sure custom modules can be imported +# sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +# from core.feature_extraction.extractor import extract_features # Adjusted for new feature extraction + +# # Set paths for dataset and save directory +# DATASET_PATH = r'C:\Users\aryas\Downloads\IMG_CLASSES' +# SAVE_PATH = '.' # Or 'models/' if you want a separate folder + +# IMG_SIZE = (128, 128) # Resize images for uniformity + +# # 2. Helper Function to Extract Features +# # Ensure consistent feature vector size +# def extract_features(image): +# # Resize and grayscale +# image = cv2.resize(image, IMG_SIZE) +# gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + +# # Color Histogram (RGB) +# hist = cv2.calcHist([image], [0, 1, 2], None, [8, 8, 8], +# [0, 256, 0, 256, 0, 256]) +# hist = cv2.normalize(hist, hist).flatten() + +# # LBP Texture Features (Local Binary Pattern) +# lbp = local_binary_pattern(gray, P=8, R=1, method='uniform') +# lbp_hist, _ = np.histogram(lbp.ravel(), +# bins=np.arange(0, 10), +# range=(0, 9)) +# lbp_hist = lbp_hist.astype("float") +# lbp_hist /= (lbp_hist.sum() + 1e-7) + +# # Combine both histograms into a single feature vector (make sure this matches the training data shape) +# features = np.hstack([hist, lbp_hist]) # This should give 521 features + +# return features + + + +# # 3. Load Dataset and Extract Features +# def load_and_extract_features(): +# features_list = [] +# labels_list = [] +# label_map = {} +# label_names = sorted(os.listdir(DATASET_PATH)) + +# for idx, disease_folder in enumerate(label_names): +# full_path = os.path.join(DATASET_PATH, disease_folder) +# if not os.path.isdir(full_path): +# continue + +# label_clean = disease_folder.split(' ')[0].strip().lower().replace(' ', '_') +# label_map[idx] = label_clean + +# for ext in ('*.jpg', '*.jpeg', '*.png'): +# for img_path in glob.glob(os.path.join(full_path, ext)): +# try: +# img = cv2.imread(img_path) +# if img is None: +# continue +# feat = extract_features(img) +# features_list.append(feat) +# labels_list.append(idx) +# except Exception as e: +# print(f"Error with {img_path}: {e}") + +# features_array = np.array(features_list) +# labels_array = np.array(labels_list) + +# return features_array, labels_array, label_map + + +# # 4. Build KD-Tree for Feature Matching +# def build_kdtree(features_array): +# tree = KDTree(features_array) +# print(f"KD-Tree built with {features_array.shape[0]} feature vectors.") +# return tree + + +# # 5. Main Function for Extracting Features, Building KD-Tree, and Saving Models +# def main(): +# features_array, labels_array, label_map = load_and_extract_features() + +# if len(features_array) > 0: +# # Build KD-Tree +# tree = build_kdtree(features_array) + +# # Save KD-Tree and model data +# with open(os.path.join(SAVE_PATH, 'kdtree.pkl'), 'wb') as f: +# pickle.dump(tree, f) + +# np.save(os.path.join(SAVE_PATH, 'features.npy'), features_array) +# np.save(os.path.join(SAVE_PATH, 'labels.npy'), labels_array) + +# with open(os.path.join(SAVE_PATH, 'label_map.pkl'), 'wb') as f: +# pickle.dump(label_map, f) + +# print("๐Ÿ“ฆ KD-Tree, features, and labels saved successfully.") +# else: +# print("โš ๏ธ No features extracted. Please check your image folder paths and formats.") + + +# if __name__ == "__main__": +# main() + diff --git a/Team 104- Skin Disease Analysis/scripts/test_kdtree_query.py b/Team 104- Skin Disease Analysis/scripts/test_kdtree_query.py new file mode 100644 index 00000000..35d02af9 --- /dev/null +++ b/Team 104- Skin Disease Analysis/scripts/test_kdtree_query.py @@ -0,0 +1,65 @@ +import cv2 +import numpy as np +import pickle +import pandas as pd +from skimage.feature import local_binary_pattern + +# Constants +IMG_SIZE = (128, 128) + +# Feature Extraction +def extract_features(image): + image = cv2.resize(image, IMG_SIZE) + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + + # Color Histogram + hist = cv2.calcHist([image], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256]) + hist = cv2.normalize(hist, hist).flatten() + + # LBP Features + lbp = local_binary_pattern(gray, P=8, R=1, method='uniform') + lbp_hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, 10), range=(0, 9)) + lbp_hist = lbp_hist.astype("float") + lbp_hist /= (lbp_hist.sum() + 1e-7) + + return np.hstack([hist, lbp_hist]) + +# Load Resources +with open('kdtree.pkl', 'rb') as f: + tree = pickle.load(f) +features_array = np.load('features.npy') +labels_array = np.load('labels.npy') +with open('label_map.pkl', 'rb') as f: + label_map = pickle.load(f) + +# Load severity weights +severity_df = pd.read_csv('severity_weights.csv') +severity_weights = { + row['disease'].lower().replace(' ', '_'): row.drop('disease').to_dict() + for _, row in severity_df.iterrows() +} + +# Test Image Processing +img = cv2.imread(r'C:\Users\aryas\OneDrive\Desktop\skin_disease_detector\assets\test_images\BCC-test.jpg') +feat = extract_features(img).reshape(1, -1).astype(np.float32) + +# Dimension Check +if feat.shape[1] != features_array.shape[1]: + raise ValueError(f"Feature dimension mismatch: test={feat.shape[1]}, expected={features_array.shape[1]}") + +# Query KDTree +dist, idx = tree.query(feat, k=5) + +print("Top 5 Predictions:") +total_scores = {} + +for i in idx[0]: + label = labels_array[i] + disease = label_map.get(str(label), f"Disease_{label}") # Ensure string key lookup + weights = severity_weights.get(disease.lower().replace(' ', '_'), {}) + severity_score = sum(float(val) for val in weights.values()) + total_scores[disease] = severity_score + print(f"- {disease} | Severity Score: {severity_score:.2f}") + +most_likely = min(total_scores, key=total_scores.get) +print(f"\nMost Likely Disease: {most_likely.upper()} (Severity: {total_scores[most_likely]:.2f})")