Access all project assets below:
| π Resource | π Link |
|---|---|
| Full Project Files | Download from Google Drive |
| Dataset | Download Dataset |
| Pretrained Model | Download Model |
- The Full Project Files include code, configs, and supporting assets.
- The Dataset is required for training and evaluation.
- The Pretrained Model can be used directly for inference.
Demo.mp4
π§ Deep Learning Mini-Project
- π Abstract
- π Introduction
- π― Problem Statement
- π Literature Survey
- ποΈ Dataset
- π§ Data Pre-processing
- ποΈ Model Architecture
- βοΈ Model Training
- π» System Implementation
- π Results
- π Observations
- β Conclusion
- π Future Scope
- π Project Structure
- π οΈ Installation and Usage
- π References
Cataract, diabetic retinopathy and glaucoma are some of the most common causes of vision loss, and all three can be seen on a photograph of the back of the eye, called a fundus image. Reading these images needs an eye specialist, and there are not enough specialists for the number of patients who need screening.
Netra.AI is a web application that uses deep learning to classify a fundus image into one of four classes: Cataract, Diabetic Retinopathy, Glaucoma or Normal. The model is based on VGG19, a convolutional neural network pre-trained on ImageNet. Using transfer learning, the convolutional layers of VGG19 are kept frozen and only a small classification head (Flatten β Dense 128 β Dropout 0.5 β Dense 4) is trained. The dataset has 4,217 images in two sizes (256Γ256 and 512Γ512), all resized to 224Γ224 before training.
On the validation set of 841 images, the model achieves an overall accuracy of 73.96%. It detects diabetic retinopathy very well (F1-score 98.21%) and cataract well (F1-score 83.20%), but often confuses glaucoma with normal eyes. After prediction, the application uses the Google Gemini 3.5 Flash API to explain the result in simple language and a web scraping module to list nearby eye hospitals. The application is hosted on Google Cloud Run.
Keywords: Deep Learning, CNN, VGG19, Transfer Learning, Fundus Image, Diabetic Retinopathy, Glaucoma, Cataract, Gemini API, Cloud Run
The WHO estimates that more than 2.2 billion people have some form of visual impairment, and roughly half of these cases could have been avoided or are still untreated. Cataract remains the biggest single cause of blindness, diabetic retinopathy cases keep growing with the number of diabetics, and glaucoma patients are projected to cross 111 million by 2040.
All three diseases show visible signs on a fundus image. Taking such a photograph is cheap and quick, but reading it needs an ophthalmologist, who is often not available in smaller towns.
CNNs have shown very good results in medical image classification. Gulshan et al. showed that a CNN can detect diabetic retinopathy as accurately as eye doctors. This project builds a smaller version of such a system and applies the core topics of the Deep Learning subject β CNNs, transfer learning, activation functions, loss functions, optimizers, dropout and model evaluation β to a real problem.
- Build a CNN model that classifies fundus images into Cataract, Diabetic Retinopathy, Glaucoma and Normal.
- Use transfer learning with pre-trained VGG19, since the dataset is small.
- Pre-process images of different sizes into the 224Γ224 input required by VGG19.
- Evaluate the model using accuracy, precision, recall, F1-score and the confusion matrix.
- Give a simple explanation of the result using the Gemini API and show nearby eye hospitals.
- Deploy the complete application on Google Cloud Run.
Netra.AI is an educational prototype and not a certified medical device. It assists doctors and users but does not replace a proper eye examination. The model gives one label per image, so it cannot report two diseases in the same eye.
To develop a deep learning based system that takes a colour fundus image as input, classifies it as Cataract, Diabetic Retinopathy, Glaucoma or Normal using a VGG19 transfer learning model, and gives the user an easy explanation of the result along with nearby eye specialist details.
| Challenge | How Netra.AI Handles It |
|---|---|
| Disease signs are small and look similar to each other | A deep CNN (VGG19) learns these features automatically |
| Dataset is small (about 4,200 images) | Transfer learning with frozen VGG19 layers |
| Images come in two different sizes | All images are resized to 224Γ224 |
| Model may overfit the training data | Dropout layer and a separate validation set |
| Users cannot understand model output | Gemini API gives a simple explanation |
| User does not know where to go next | Doctor finder shows nearby eye hospitals |
| Paper | Method | Finding |
|---|---|---|
| Krizhevsky et al., 2012 | AlexNet | Deep CNNs work far better than older methods on ImageNet |
| Simonyan & Zisserman, 2015 | VGG16 / VGG19 | Deeper networks with 3Γ3 filters give better accuracy |
| He et al., 2016 | ResNet | Skip connections allow very deep networks |
| Yosinski et al., 2014 | Transfer learning study | Early CNN layers are general and can be reused |
| Gulshan et al., 2016 | Inception-v3 | DR detection at specialist level on a very large dataset |
| Ting et al., 2017 | CNN ensemble | Detection of DR, glaucoma and other eye diseases |
Most of these systems use very large private datasets. This project uses a small public dataset and a simple, well-known model (VGG19), and adds an explanation and doctor finder for the user.
The public Eye Diseases Classification dataset from Kaggle is used. It contains colour fundus images in four folders, one per class.
π Dataset Link: https://www.kaggle.com/datasets/gunavenkatdoddi/eye-diseases-classification
| Class | No. of Images | Image Size |
|---|---|---|
| Cataract | 1038 | 256 Γ 256 |
| Diabetic Retinopathy | 1098 | 512 Γ 512 |
| Glaucoma | 1007 | 256 Γ 256 |
| Normal | 1074 | 512 Γ 512 |
| Total | 4217 | β |
The classes are almost balanced: the largest class (DR) has only about 9% more images than the smallest class (Glaucoma). All images are RGB colour images in JPG or PNG format.
Figure 1: Sample images from each class
| Class | Features Seen in the Fundus Image |
|---|---|
| Cataract | Whole image looks hazy and blurred, blood vessels are not clear |
| Diabetic Retinopathy | Small red spots (haemorrhages), yellow spots (exudates), abnormal blood vessels |
| Glaucoma | Larger and paler cup inside the optic disc (high cup-to-disc ratio) |
| Normal | Clear blood vessels, sharp optic disc and darker macula |
The data is split using ImageDataGenerator(validation_split=0.2), which splits every class folder separately (80% training, 20% validation).
| Class | Total | Training | Validation |
|---|---|---|---|
| Cataract | 1038 | 831 | 207 |
| Diabetic Retinopathy | 1098 | 879 | 219 |
| Glaucoma | 1007 | 806 | 201 |
| Normal | 1074 | 860 | 214 |
| Total | 4217 | 3376 | 841 |
The same steps are applied during training and in the web application, so the model always receives input in the same form.
- Resize β the image is resized to 224Γ224 pixels.
- Convert β the image is converted to an array of RGB pixel values.
- Normalize β each pixel value is divided by 255 so it lies between 0 and 1.
- Batch β images are grouped into batches of 32 for training. For a single upload, the input shape becomes
(1, 224, 224, 3).
- During training:
flow_from_directory(target_size=(224, 224)) - During prediction:
image.load_img(path, target_size=(224, 224))
Keras uses nearest-neighbour interpolation by default. Since all images are square, nothing is stretched or cropped and the full eye stays visible.
| Original Size | Classes | Scale Factor | Effect |
|---|---|---|---|
| 256 Γ 256 | Cataract, Glaucoma | 1.14 | Small reduction, most detail is kept |
| 512 Γ 512 | DR, Normal | 2.29 | Large reduction, some fine detail is lost |
Figure 2: Resizing images of two sizes to 224Γ224
- VGG19 was trained on ImageNet images of size 224Γ224, so its filters work best at this size.
- VGG19 has 5 pooling layers: 224 β 112 β 56 β 28 β 14 β 7, giving a final feature map of 7Γ7Γ512, which the Flatten and Dense layers are built for.
- It keeps memory and computation small enough for training and cloud deployment.
Pixel values (0β255) are divided by 255 using rescale=1./255. Small input values make training more stable. No data augmentation was used in this project.
| Layer | Function |
|---|---|
| Convolution | A 3Γ3 filter slides over the image and produces a feature map; each filter detects one pattern (edge, colour change) |
| ReLU | ReLU(x) = max(0, x); adds non-linearity |
| Max Pooling | Takes the largest value in each 2Γ2 block; halves the feature map size |
| Dense (Fully Connected) | Uses all extracted features to make the final decision |
| Softmax | Converts outputs into probabilities that add up to 1 |
Figure 3: Example of convolution, ReLU and max pooling
- Simple structure β only 3Γ3 convolutions and 2Γ2 pooling, repeated in 5 blocks.
- Good pre-trained features β trained on over 1 million ImageNet images.
- Works with small datasets β only the small head needs training.
- Deeper than VGG16 β blocks 3, 4 and 5 have 4 convolution layers instead of 3.
- Easy to use β available directly in Keras with pre-trained weights.
| Model | Size (MB) | Parameters | Top-1 Acc. | Depth |
|---|---|---|---|---|
| VGG16 | 528 | 138.4 M | 71.3% | 16 |
| VGG19 (used) | 549 | 143.7 M | 71.3% | 19 |
| ResNet50 | 98 | 25.6 M | 74.9% | 107 |
| InceptionV3 | 92 | 23.9 M | 77.9% | 189 |
| MobileNetV2 | 14 | 3.5 M | 71.3% | 105 |
| EfficientNetB0 | 29 | 5.3 M | 77.1% | 132 |
Values from Keras Applications. Most of VGG19's parameters are in its original fully connected layers, which are not used (include_top=False). The part used has about 20 million parameters.
Figure 4: VGG19 architecture with the custom classification head
| Block | Layers | Output Size | Parameters |
|---|---|---|---|
| Input | RGB image | 224Γ224Γ3 | 0 |
| Block 1 | 2 Conv (64 filters) + MaxPool | 112Γ112Γ64 | 38,720 |
| Block 2 | 2 Conv (128 filters) + MaxPool | 56Γ56Γ128 | 221,440 |
| Block 3 | 4 Conv (256 filters) + MaxPool | 28Γ28Γ256 | 2,065,408 |
| Block 4 | 4 Conv (512 filters) + MaxPool | 14Γ14Γ512 | 8,259,584 |
| Block 5 | 4 Conv (512 filters) + MaxPool | 7Γ7Γ512 | 9,439,232 |
| Flatten | Converts to 1-D vector | 25,088 | 0 |
| Dense | 128 neurons, ReLU | 128 | 3,211,392 |
| Dropout | Rate 0.5 | 128 | 0 |
| Dense (Output) | 4 neurons, Softmax | 4 | 516 |
| Total parameters | 23,236,292 | ||
| Frozen (VGG19 layers) | 20,024,384 | ||
| Trainable (custom head) | 3,211,908 |
| Stage | What It Learns |
|---|---|
| Block 1 | Simple features: edges, borders of blood vessels, colour changes |
| Block 2 | Small textures and thin vessel lines; small red and yellow spots |
| Block 3 | Larger patterns: vessel branches, groups of spots, hazy look of cataract |
| Block 4 | Bigger structures: optic disc, areas with many lesions |
| Block 5 | Overall appearance of the eye |
| Flatten + Dense | Maps the 25,088 features to the 4 classes; Dropout turns off 50% of neurons during training to reduce overfitting |
VGG19 is loaded with ImageNet weights and all its layers are frozen, so it acts only as a feature extractor. Only the new head (β3.2 million parameters) is trained.
base_model = VGG19(weights="imagenet", include_top=False, input_shape=(224, 224, 3))
for layer in base_model.layers:
layer.trainable = False # Freeze pretrained layers
x = Flatten()(base_model.output)
x = Dense(128, activation='relu')(x)
x = Dropout(0.5)(x)
output = Dense(len(CATEGORIES), activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=output)
Figure 5: Model training pipeline
| Parameter | Value |
|---|---|
| Base model | VGG19 (ImageNet weights, frozen) |
| Input size | 224 Γ 224 Γ 3 |
| Optimizer | Adam (learning rate 0.001) |
| Loss function | Categorical Cross-Entropy |
| Epochs | 6 |
| Batch size | 32 |
| Steps per epoch | 106 |
| Train / Validation split | 80% / 20% |
| Data augmentation | Not used |
| Saved model | models/eye_disease_model.h5 |
Categorical Cross-Entropy is used because this is a multi-class problem with one-hot labels:
Loss = β log(p_correct_class)
The loss is small when the model gives a high probability to the correct class and large when it does not.
Adam updates each weight using the average of recent gradients and adjusts the step size for each weight automatically, so it usually trains faster and more smoothly than plain gradient descent.
- Load images with
ImageDataGenerator(rescale and 80/20 split). - Load VGG19 without its top layers and freeze all its layers.
- Add the head: Flatten β Dense(128, ReLU) β Dropout(0.5) β Dense(4, Softmax).
- Compile with Adam and categorical cross-entropy.
- Train for 6 epochs with batch size 32, checking validation accuracy after every epoch.
- Save the model as
eye_disease_model.h5.
datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)
train_data = datagen.flow_from_directory(DATASET_PATH, target_size=IMG_SIZE,
batch_size=BATCH_SIZE, class_mode='categorical', subset="training")
val_data = datagen.flow_from_directory(DATASET_PATH, target_size=IMG_SIZE,
batch_size=BATCH_SIZE, class_mode='categorical', subset="validation")
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
history = model.fit(train_data, validation_data=val_data, epochs=EPOCHS)
model.save("models/eye_disease_model.h5")The user uploads a fundus photo from the browser. The Flask server pre-processes it the same way as during training and passes it to the VGG19 model. The predicted disease and confidence are sent to the Gemini API, which returns a short explanation. Both are shown on the result page, from where the user can open the doctor finder.
Figure 6: System architecture of Netra.AI
The saved model is loaded into memory once when the server starts. For every uploaded image, the server:
- Resizes the image to 224Γ224 and divides pixel values by 255.
- Adds a batch dimension β input shape
(1, 224, 224, 3). - Runs the model, which returns four probabilities (one per class).
- Picks the class with the highest probability and shows it as the confidence in percent.
The probabilities of all four classes are also displayed as bars.
The disease name and confidence are passed to Gemini 3.5 Flash through the google-genai Python library. The model is asked to answer in a fixed JSON format with five parts:
| Field | Content |
|---|---|
description |
Short description of the disease |
symptoms |
Common symptoms |
risk_factors |
Risk factors |
next_steps |
Recommended next steps |
lifestyle_tips |
Lifestyle tips |
If the API is busy, the request is retried a few times. If it still fails, a ready-made text stored in the code is shown instead.
web_scraper.py takes a city name and returns up to 15 eye hospitals near it.
| Source | Use |
|---|---|
| City coordinate list | Stored latitude and longitude of 54 Indian cities |
| Nominatim (OpenStreetMap) | Location of cities not in the list |
| Google Places API | Hospitals with ratings and phone numbers (only if a key is given) |
| Overpass API (OpenStreetMap) | Eye hospitals and clinics within 25 km |
| Curated list | Verified eye hospitals for 14 large cities |
| DuckDuckGo search | Official website link of a hospital |
Duplicate hospitals are removed, the distance from the city centre is calculated, and results are sorted closest first. They are shown as cards and as markers on a Leaflet map.
| Technology | Purpose |
|---|---|
| Python 3.10 | Main programming language |
| TensorFlow / Keras 2.15 | Building, training and running the model |
| NumPy, scikit-learn | Array handling and evaluation metrics |
| Matplotlib, Seaborn | Graphs and confusion matrix |
| Flask | Web server |
| Google Gemini 3.5 Flash | Explanation of the result |
| Requests, BeautifulSoup | Web scraping for the doctor finder |
| HTML, CSS, JavaScript, Leaflet.js | User interface and map |
| Docker, Google Cloud Run | Containerization and hosting |
The application, together with the trained model, is packed into a Docker container and hosted on Google Cloud Run, so it can be opened from any browser through a public link.
The model was evaluated on the 841 validation images using evaluate_model.py.
| Term | Meaning |
|---|---|
| TP (True Positive) | Images of the class predicted correctly |
| FP (False Positive) | Images of other classes wrongly predicted as this class |
| FN (False Negative) | Images of this class predicted as another class |
| TN (True Negative) | Images of other classes correctly not predicted as this class |
Accuracy = Correct Predictions / Total Predictions
Error Rate = 1 β Accuracy
Precision = TP / (TP + FP)
Recall = TP / (TP + FN)
F1-Score = 2 Γ (Precision Γ Recall) / (Precision + Recall)
| Metric | Value |
|---|---|
| Accuracy | 73.96% |
| Error Rate | 26.04% |
| Weighted Precision | 77.40% |
| Weighted Recall | 73.96% |
| Weighted F1-Score | 72.39% |
The model predicted 622 out of 841 validation images correctly.
| Class | Precision (%) | Recall (%) | F1-Score (%) |
|---|---|---|---|
| Cataract | 92.86 | 75.36 | 83.20 |
| Diabetic Retinopathy | 96.48 | 100.00 | 98.21 |
| Glaucoma | 67.06 | 28.36 | 39.86 |
| Normal | 52.63 | 88.79 | 66.09 |
Rows = actual class, columns = predicted class.
| Cataract | DR | Glaucoma | Normal | |
|---|---|---|---|---|
| Cataract | 156 | 2 | 11 | 38 |
| DR | 0 | 219 | 0 | 0 |
| Glaucoma | 5 | 6 | 57 | 133 |
| Normal | 7 | 0 | 17 | 190 |
Figure 7: Confusion matrix heatmap
| Class | TP | FP | FN | TN |
|---|---|---|---|---|
| Cataract | 156 | 12 | 51 | 622 |
| Diabetic Retinopathy | 219 | 8 | 0 | 614 |
| Glaucoma | 57 | 28 | 144 | 612 |
| Normal | 190 | 171 | 24 | 456 |
Figure 8: Class-wise metrics and overall performance
- Diabetic Retinopathy (F1: 98.21%) β all 219 DR validation images were identified. DR leaves many red and yellow marks across the retina, which VGG19 filters respond to easily.
- Cataract (F1: 83.20%) β precision of 92.86% means the model is rarely wrong when it predicts cataract. The 38 cataract images marked Normal are probably early cases where the haze is very faint.
- Glaucoma (Recall: 28.36%) β of 201 glaucoma images, 133 were labelled Normal. This is the most serious error, because a glaucoma patient would be told the eye is fine.
- Normal (Precision: 52.63%) β the model predicted "Normal" 361 times when only 214 images were really normal; most of the extra predictions were glaucoma images.
An accuracy of 73.96% is far better than random guessing (25% for four classes), but lower than desired. The main reasons are:
- Glaucoma pulls the average down β excluding glaucoma, the model gets 565 of 640 images right (about 88%).
- VGG19 layers were frozen β features learned from ImageNet were never adjusted for retinal images.
- The glaucoma sign is very small β it mainly changes the cup inside the optic disc, so the image as a whole looks close to normal.
- Detail lost while resizing β 512Γ512 images lose fine detail such as thin vessels and tiny spots.
- Short training β 6 epochs were enough for DR and cataract, but not for the harder glaucomaβnormal distinction.
- No data augmentation β the model saw less variety.
- Different input scaling β VGG19 was trained with its own preprocessing (mean subtraction), while only division by 255 was used here.
The number of images is not the reason, since all four classes have almost the same count (1007 to 1098).
| Class | F1-Score | Remark |
|---|---|---|
| Diabetic Retinopathy | 98.21% | Excellent, no DR case missed |
| Cataract | 83.20% | Good, a few mild cases called Normal |
| Normal | 66.09% | Over-predicted, many glaucoma images end up here |
| Glaucoma | 39.86% | Weak, needs improvement |
Netra.AI classifies fundus images into Cataract, Diabetic Retinopathy, Glaucoma and Normal using transfer learning with a frozen VGG19 model, training only a small classification head on 3,376 images. The model achieved 73.96% accuracy on 841 validation images, performing very well on diabetic retinopathy (F1 98.21%) and well on cataract (F1 83.20%), while glaucoma detection needs improvement.
The model is part of a complete web application that explains results using the Gemini 3.5 Flash API, helps users find nearby eye hospitals, and is hosted on Google Cloud Run. The project provided practical understanding of CNNs, transfer learning, model training and evaluation, and deployment.
| Area | Improvement |
|---|---|
| Fine-tuning | Unfreeze the last VGG19 block and train it with a small learning rate |
| Pre-processing | Use VGG19's own preprocess_input and a smoother resizing method |
| Longer training | Train for more epochs with early stopping |
| Data augmentation | Use flipping, rotation and brightness changes |
| Glaucoma detection | Crop the optic disc area and train a separate model for it |
| Other models | Try ResNet50, EfficientNet and Vision Transformers |
| Explainability | Show Grad-CAM heatmaps of the area the model looked at |
| More data | Add more datasets and test on images from other hospitals |
| Mobile app | Convert the model to TensorFlow Lite for offline use |
| Languages | Show the explanation in Hindi, Marathi and other languages |
Mini-Project/
βββ app.py # Flask app, model loading, prediction, Gemini
βββ web_scraper.py # Doctor finder
βββ model_training.py # VGG19 training script
βββ evaluate_model.py # Evaluation and graphs
βββ model_evaluation_metrics.csv # Saved metrics
βββ requirements.txt # Python libraries
βββ Dockerfile # Container for Cloud Run
βββ .dockerignore
βββ .env # API keys (not uploaded)
βββ README.md
β
βββ models/
β βββ eye_disease_model.h5 # Trained model
β
βββ dataset/
β βββ cataract/ # 1038 images
β βββ diabetic_retinopathy/ # 1098 images
β βββ glaucoma/ # 1007 images
β βββ normal/ # 1074 images
β
βββ templates/
β βββ index.html # Upload page
β βββ loading.html # Processing page
β βββ result.html # Prediction and explanation
β βββ doctors.html # Doctor finder with map
β
βββ static/
βββ styles.css
βββ script.js
βββ assets/ # Diagrams and charts used in this README
βββ favicon/
βββ uploads/ # User-uploaded images
- Python 3.10
- pip
- A Google Gemini API key (ai.google.dev)
# 1. Clone the repository
git clone <repository-url>
cd Mini-Project
# 2. Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # Linux / macOS
venv\Scripts\activate # Windows
# 3. Install dependencies
pip install -r requirements.txt
# 4. Place the trained model (from the Pretrained Model link above)
# models/eye_disease_model.h5
# 5. Add your API key to a .env file
GEMINI_API_KEY=your-api-key-here
# 6. (Optional) Train and evaluate the model from scratch
python model_training.py
python evaluate_model.py
# 7. Run the application
python app.pyOpen http://127.0.0.1:5000 in the browser.
docker build -t netra-ai .
docker run -p 5000:5000 --env-file .env netra-ai- World Health Organization, World Report on Vision, Geneva, 2019.
- Y.-C. Tham et al., "Global prevalence of glaucoma and projections of glaucoma burden through 2040," Ophthalmology, vol. 121, no. 11, pp. 2081β2090, 2014.
- V. Gulshan et al., "Development and validation of a deep learning algorithm for detection of diabetic retinopathy in retinal fundus photographs," JAMA, vol. 316, no. 22, pp. 2402β2410, 2016.
- D. S. W. Ting et al., "Development and validation of a deep learning system for diabetic retinopathy and related eye diseases using retinal images from multiethnic populations with diabetes," JAMA, vol. 318, no. 22, pp. 2211β2223, 2017.
- A. Krizhevsky, I. Sutskever and G. E. Hinton, "ImageNet classification with deep convolutional neural networks," NeurIPS, 2012, pp. 1097β1105.
- K. Simonyan and A. Zisserman, "Very deep convolutional networks for large-scale image recognition," Proc. ICLR, 2015.
- K. He, X. Zhang, S. Ren and J. Sun, "Deep residual learning for image recognition," Proc. IEEE CVPR, 2016, pp. 770β778.
- J. Yosinski, J. Clune, Y. Bengio and H. Lipson, "How transferable are features in deep neural networks?" NeurIPS, 2014, pp. 3320β3328.
- R. R. Selvaraju et al., "Grad-CAM: Visual explanations from deep networks via gradient-based localization," Proc. IEEE ICCV, 2017, pp. 618β626.
- Keras, "Keras Applications," https://keras.io/api/applications/
- G. V. Doddi, "Eye Diseases Classification," Kaggle, https://www.kaggle.com/datasets/gunavenkatdoddi/eye-diseases-classification
- Google, "Gemini API Documentation," https://ai.google.dev/gemini-api/docs
- Google Cloud, "Cloud Run Documentation," https://cloud.google.com/run/docs
- OpenStreetMap Wiki, "Overpass API," https://wiki.openstreetmap.org/wiki/Overpass_API
Netra.AI is a student project made for educational purposes only. It is not a certified medical device and its results should not be used in place of a proper diagnosis. Please consult a qualified eye specialist for any eye-related problem.