├── Attrition prediction └── Attrition prediction.ipynb ├── CV-Mask-detection ├── LICENSE ├── README.md ├── app │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-310.pyc │ │ └── config.cpython-310.pyc │ ├── config.py │ ├── errors │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-310.pyc │ │ │ ├── __init__.cpython-37.pyc │ │ │ ├── routes.cpython-310.pyc │ │ │ └── routes.cpython-37.pyc │ │ └── routes.py │ ├── main │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-310.pyc │ │ │ ├── camera.cpython-310.pyc │ │ │ └── routes.cpython-310.pyc │ │ ├── camera.py │ │ └── routes.py │ ├── static │ │ └── images │ │ │ ├── mask.jpg │ │ │ └── stay-safe.jpg │ └── templates │ │ ├── error.html │ │ ├── home_page.html │ │ ├── image_detector.html │ │ └── template.html ├── environment.yml ├── mask_detection_live.gif ├── models │ ├── mask_mobilenet.h5 │ └── training_plot.png ├── requirements.txt ├── source │ ├── __pycache__ │ │ └── test_new_images.cpython-310.pyc │ ├── test_new_images.py │ ├── train_model.py │ ├── utils.py │ └── video_detector.py └── wsgi.py ├── Cartoonify-Image ├── Cartoonification │ ├── Assets │ │ ├── Threshold.jpg │ │ ├── Title .png │ │ ├── abe_toon.png │ │ ├── boy.png │ │ ├── cwoc.jpeg │ │ ├── edge.png │ │ ├── filters_tutorial_02.png │ │ ├── gssoc.png │ │ ├── preview-removebg.png │ │ ├── result (2).jpg │ │ ├── uaceit.jpeg │ │ └── vishal.txt │ ├── Readme.md │ └── cartoonify_without_GUI.py ├── Cartoonify using KMeans │ ├── README.md │ ├── Resources │ │ ├── cartoon.jpg │ │ └── original2.jpg │ ├── Script │ │ ├── cartoonize.py │ │ └── vid.py │ └── images │ │ └── readme.md ├── Cartoonify-GUI │ ├── GUI.png │ ├── Readme.md │ ├── Updated GUI.png │ ├── background.png │ ├── cartoonified.jpg │ ├── cartoonify-gui.py │ ├── dicaprio.jpg │ ├── mq2.jpg │ └── wp2030093.jpg ├── Cartoonify_face_image │ ├── Cartoonify-face_image.py │ ├── Images │ │ ├── after_face.png │ │ ├── face.jpg │ │ ├── readme.md │ │ └── recof.gif │ └── readme.md ├── Cartoonifying using OpenCV │ ├── Cartoonify.py │ └── Readme.md ├── Cartoonized-Image │ ├── Cartoonify.ipynb │ ├── images │ │ ├── cry_baby.jfif │ │ ├── smile.jpg │ │ └── virat.jfif │ └── readme.md ├── Differentiate between Human and Cartoon Faces │ ├── Assets │ │ ├── cartoon.jpeg │ │ └── image.webp │ ├── Media │ │ ├── blurred_hsv.jpeg │ │ ├── image.webp │ │ ├── img_hsv.jpeg │ │ └── new.jpeg │ ├── README.md │ ├── cartoon.py │ └── requirements.txt ├── Glitter Cartoon Filter │ ├── Glitter Cartoon Filter.py │ ├── Images │ │ ├── Final_Output.jpg │ │ └── Original_image.jpg │ └── README.md ├── Images │ └── readme.md ├── facex.jpeg ├── logo │ ├── Face-X.png │ ├── FaceX.svg │ ├── cartoonified.png │ └── original.jpeg └── readme.md ├── Chronic-Kidney-Disease-main.zip ├── Color-Detection-Project ├── Covid ├── Data Representation └── DataRepresentationBasics.ipynb ├── Face Emotion new.ipynb ├── Fake_news_prediction.ipynb ├── IPl visualization └── IPL_data_visualization.ipynb ├── Iris_Flower_classification_HK.ipynb ├── README.md ├── Recommendation System.ipynb ├── Sales Visualization .ipynb ├── Sentiment Analysis ├── SenAnal.py ├── app.py └── init - Copy.py ├── Streamlit-Stock-Prediction-main.zip ├── TITANIC SURVIVAL PREDICTION ├── test.csv ├── titanic.ipynb └── train.csv ├── bark-texture-classification-with-resnet50.ipynb ├── brain-tumor-detection-v1-0-cnn-vgg-16.ipynb ├── house-prediction.ipynb ├── notebook86c26b4f17-checkpoint.ipynb ├── tensorflow-pneumonia-classification-on-x-rays.ipynb ├── tmdb_5000_movies.csv └── wcwp-climate-master.zip /CV-Mask-detection/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 GalileoParise 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CV-Mask-detection/README.md: -------------------------------------------------------------------------------- 1 | # CV-Mask-detection 2 | Face Mask Detection web applicaion built with Flask, Keras-TensorFlow, OpenCV. 3 | It can be used to detect face masks both in images and in real-time video. 4 | 5 | ## Demo 6 | 7 | 8 | ## Goal 9 | The goal is to create a masks detection system, able to recognize face masks both in images, both in real-time video, drawing bounding box around faces. In order to do so, I finetuned MobilenetV2 pretrained on Imagenet, in conjunction with the OpenCV face detection algorithm: that allows me to turn a classifier model into an object detection system. 10 | 11 | ## Technologies 12 | - Keras/Tensorflow 13 | - OpenCV 14 | - Flask 15 | - MobilenetV2 16 | 17 | ## Usage 18 | You have to install the required packages, you can do it: 19 | - via pip 20 | ```pip install -r requirements.txt``` 21 | - or via conda 22 | ```conda env create -f environment.yml``` 23 | 24 | Once you installed all the required packages you can type in the command line from the root folder: 25 | 26 | ``` 27 | python wsgi.py 28 | ``` 29 | and click on the link that the you will see on the prompt. 30 | 31 | ## Data 32 | The dataset used for training the model is available here. 33 | 34 | -------------------------------------------------------------------------------- /CV-Mask-detection/app/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | from app.errors.routes import error_404, error_403, error_401, error_500 4 | 5 | 6 | def create_app(): 7 | app = Flask(__name__) 8 | 9 | # Retrieve configuration information 10 | app.config.from_object('app.config.Config') 11 | 12 | # Initialization of blueprints 13 | from app.main import main_bp 14 | 15 | # Error handlers 16 | app.register_error_handler(404, error_404) 17 | app.register_error_handler(403, error_403) 18 | app.register_error_handler(401, error_401) 19 | app.register_error_handler(500, error_500) 20 | 21 | app.register_blueprint(main_bp) 22 | return app 23 | 24 | 25 | if __name__ == '__main__': 26 | app = create_app() 27 | app.run(debug=True) 28 | -------------------------------------------------------------------------------- /CV-Mask-detection/app/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/__pycache__/config.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/__pycache__/config.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | APP_ROOT = os.path.abspath(os.path.dirname(os.path.realpath(__file__))) 3 | 4 | 5 | class Config(object): 6 | root_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")) 7 | SECRET_KEY = os.environ.get("secret_key") 8 | USER_APP_NAME = "Mask-detector-App" -------------------------------------------------------------------------------- /CV-Mask-detection/app/errors/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | errors_bp = Blueprint("errors", __name__) 4 | 5 | import app.errors.routes 6 | -------------------------------------------------------------------------------- /CV-Mask-detection/app/errors/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/errors/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/errors/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/errors/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/errors/__pycache__/routes.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/errors/__pycache__/routes.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/errors/__pycache__/routes.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/errors/__pycache__/routes.cpython-37.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/errors/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | from . import errors_bp 3 | 4 | 5 | @errors_bp.errorhandler(404) 6 | def error_404(e): 7 | return render_template("error.html", error="404"), 404 8 | 9 | 10 | @errors_bp.errorhandler(500) 11 | def error_500(e): 12 | return render_template("error.html", error="500"), 500 13 | 14 | 15 | @errors_bp.errorhandler(403) 16 | def error_403(e): 17 | return render_template("error.html", error="403"), 403 18 | 19 | 20 | @errors_bp.errorhandler(401) 21 | def error_401(e): 22 | return render_template("error.html", error="401"), 401 23 | -------------------------------------------------------------------------------- /CV-Mask-detection/app/main/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | main_bp = Blueprint("main", __name__) 4 | 5 | import app.main.routes 6 | -------------------------------------------------------------------------------- /CV-Mask-detection/app/main/__pycache__/__init__.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/main/__pycache__/__init__.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/main/__pycache__/camera.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/main/__pycache__/camera.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/main/__pycache__/routes.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/main/__pycache__/routes.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/app/main/camera.py: -------------------------------------------------------------------------------- 1 | import time 2 | import threading 3 | import cv2 4 | 5 | try: 6 | from greenlet import getcurrent as get_ident 7 | except ImportError: 8 | try: 9 | from thread import get_ident 10 | except ImportError: 11 | from _thread import get_ident 12 | 13 | 14 | class CameraEvent(object): 15 | """An Event-like class that signals all active clients when a new frame is 16 | available. 17 | """ 18 | 19 | def __init__(self): 20 | self.events = {} 21 | 22 | def wait(self): 23 | """Invoked from each client's thread to wait for the next frame.""" 24 | ident = get_ident() 25 | if ident not in self.events: 26 | # this is a new client 27 | # add an entry for it in the self.events dict 28 | # each entry has two elements, a threading.Event() and a timestamp 29 | self.events[ident] = [threading.Event(), time.time()] 30 | return self.events[ident][0].wait() 31 | 32 | def set(self): 33 | """Invoked by the camera thread when a new frame is available.""" 34 | now = time.time() 35 | remove = None 36 | for ident, event in self.events.items(): 37 | if not event[0].isSet(): 38 | # if this client's event is not set, then set it 39 | # also update the last set timestamp to now 40 | event[0].set() 41 | event[1] = now 42 | else: 43 | # if the client's event is already set, it means the client 44 | # did not process a previous frame 45 | # if the event stays set for more than 5 seconds, then assume 46 | # the client is gone and remove it 47 | if now - event[1] > 5: 48 | remove = ident 49 | if remove: 50 | del self.events[remove] 51 | 52 | def clear(self): 53 | """Invoked from each client's thread after a frame was processed.""" 54 | self.events[get_ident()][0].clear() 55 | 56 | 57 | class BaseCamera(object): 58 | thread = None # background thread that reads frames from camera 59 | frame = None # current frame is stored here by background thread 60 | last_access = 0 # time of last client access to the camera 61 | event = CameraEvent() 62 | 63 | def __init__(self): 64 | """Start the background camera thread if it isn't running yet.""" 65 | if BaseCamera.thread is None: 66 | BaseCamera.last_access = time.time() 67 | 68 | # start background frame thread 69 | BaseCamera.thread = threading.Thread(target=self._thread, daemon=True) 70 | BaseCamera.thread.start() 71 | 72 | # wait until frames are available 73 | while self.get_frame() is None: 74 | time.sleep(0) 75 | 76 | def get_frame(self): 77 | """Return the current camera frame.""" 78 | BaseCamera.last_access = time.time() 79 | # wait for a signal from the camera thread 80 | BaseCamera.event.wait() 81 | BaseCamera.event.clear() 82 | 83 | return BaseCamera.frame 84 | 85 | @staticmethod 86 | def frames(): 87 | """"Generator that returns frames from the camera.""" 88 | raise RuntimeError('Must be implemented by subclasses.') 89 | 90 | @classmethod 91 | def _thread(cls): 92 | """Camera background thread.""" 93 | print('Starting camera thread.') 94 | frames_iterator = cls.frames() 95 | for frame in frames_iterator: 96 | BaseCamera.frame = frame 97 | BaseCamera.event.set() # send signal to clients 98 | time.sleep(0) 99 | 100 | # if there hasn't been any clients asking for frames in 101 | # the last 5 seconds then stop the thread 102 | if time.time() - BaseCamera.last_access > 5: 103 | frames_iterator.close() 104 | print('Stopping camera thread due to inactivity.') 105 | break 106 | BaseCamera.thread = None 107 | 108 | 109 | class Camera(BaseCamera): 110 | video_source = 0 111 | 112 | def __init__(self): 113 | # if os.environ.get('OPENCV_CAMERA_SOURCE'): 114 | # Camera.set_video_source(int(os.environ['OPENCV_CAMERA_SOURCE'])) 115 | super(Camera, self).__init__() 116 | 117 | @staticmethod 118 | def set_video_source(source): 119 | Camera.video_source = source 120 | 121 | @staticmethod 122 | def frames(): 123 | camera = cv2.VideoCapture(Camera.video_source) 124 | if not camera.isOpened(): 125 | raise RuntimeError('Could not start camera.') 126 | 127 | while True: 128 | # read current frame 129 | _, img = camera.read() 130 | 131 | # encode as a jpeg image and return it 132 | yield img 133 | -------------------------------------------------------------------------------- /CV-Mask-detection/app/main/routes.py: -------------------------------------------------------------------------------- 1 | from base64 import b64encode 2 | from io import BytesIO 3 | 4 | import cv2 5 | import numpy as np 6 | from PIL import Image 7 | from flask import render_template, Response, flash 8 | from flask_wtf import FlaskForm 9 | from flask_wtf.file import FileAllowed 10 | from werkzeug.exceptions import abort 11 | from wtforms import FileField, SubmitField 12 | from app.main import main_bp 13 | from app.main.camera import Camera 14 | 15 | from source.test_new_images import detect_mask_in_image 16 | from source.video_detector import detect_mask_in_frame 17 | 18 | 19 | @main_bp.route("/") 20 | def home_page(): 21 | return render_template("home_page.html") 22 | 23 | 24 | def gen(camera): 25 | 26 | while True: 27 | frame = camera.get_frame() 28 | frame_processed = detect_mask_in_frame(frame) 29 | frame_processed = cv2.imencode('.jpg', frame_processed)[1].tobytes() 30 | yield (b'--frame\r\n' 31 | b'Content-Type: image/jpeg\r\n\r\n' + frame_processed + b'\r\n') 32 | 33 | 34 | @main_bp.route('/video_feed') 35 | def video_feed(): 36 | return Response(gen( 37 | Camera() 38 | ), 39 | mimetype='multipart/x-mixed-replace; boundary=frame') 40 | 41 | 42 | def allowed_file(filename): 43 | ext = filename.split(".")[-1] 44 | is_good = ext in ["jpg", "jpeg", "png"] 45 | return is_good 46 | 47 | 48 | @main_bp.route("/image-mask-detector", methods=["GET", "POST"]) 49 | def image_mask_detection(): 50 | return render_template("image_detector.html", 51 | form=PhotoMaskForm()) 52 | 53 | 54 | @main_bp.route("/image-processing", methods=["POST"]) 55 | def image_processing(): 56 | form = PhotoMaskForm() 57 | 58 | if not form.validate_on_submit(): 59 | flash("An error occurred", "danger") 60 | abort(Response("Error", 400)) 61 | 62 | pil_image = Image.open(form.image.data) 63 | image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR) 64 | array_image = detect_mask_in_image(image) 65 | rgb_image = cv2.cvtColor(array_image, cv2.COLOR_BGR2RGB) 66 | image_detected = Image.fromarray(rgb_image, 'RGB') 67 | 68 | with BytesIO() as img_io: 69 | image_detected.save(img_io, 'PNG') 70 | img_io.seek(0) 71 | base64img = "data:image/png;base64," + b64encode(img_io.getvalue()).decode('ascii') 72 | return base64img 73 | 74 | 75 | # form 76 | class PhotoMaskForm(FlaskForm): 77 | image = FileField('Choose image:', 78 | validators=[ 79 | FileAllowed(['jpg', 'jpeg', 'png'], 'The allowed extensions are: .jpg, .jpeg and .png')]) 80 | 81 | submit = SubmitField('Detect mask') 82 | -------------------------------------------------------------------------------- /CV-Mask-detection/app/static/images/mask.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/static/images/mask.jpg -------------------------------------------------------------------------------- /CV-Mask-detection/app/static/images/stay-safe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/app/static/images/stay-safe.jpg -------------------------------------------------------------------------------- /CV-Mask-detection/app/templates/error.html: -------------------------------------------------------------------------------- 1 | {% extends "template.html" %} 2 | {% block content %} 3 |
4 |
5 |

Error {{error}}

6 |

An errror occurred, please try again

7 |
8 | Home page 9 |
10 |
11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /CV-Mask-detection/app/templates/home_page.html: -------------------------------------------------------------------------------- 1 | {% extends "template.html" %} 2 | {% block content %} 3 |
4 |
5 |
6 |

Welcome to the mask detector live

7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 16 |
17 |
18 |
19 |
20 | 23 |
24 |
25 | 28 |
29 |
30 |
31 |
32 |

What is this?

33 |
34 |
35 |

This is a mask detector, an algorithm based on deep neural networks that detects people through your 36 | camera and write a bounding box around faces, 37 | looking if they were masks or not. This is not for security purpose.

38 |

If you are interested in more details, check this post I wrote!

39 |
40 |
41 |

Who I am

42 |
43 |
44 |

I'm Galileo Parise, data scientist and matematician, and I've developed what you see during Italy's 45 | second lockdown in November, in which I had lots of free time. If you are interested in this and ohter 46 | stories, 47 | you can follow me on Linkedin and on Medium. 48 | Hoping to get soon over this situation, 49 | I hope you all good health:

50 |

please, stay safe and wear a mask.

51 |

52 |
53 |
54 |
55 | {% endblock %} 56 | {% block custom_js %} 57 | 77 | 78 | {% endblock %} -------------------------------------------------------------------------------- /CV-Mask-detection/app/templates/image_detector.html: -------------------------------------------------------------------------------- 1 | {% extends "template.html" %} 2 | {% block content %} 3 |
4 |
5 |
6 |

Try the mask detector on custom images

7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 16 |
17 |
18 |
19 |
20 | 21 |
22 |
23 |
24 | {{ form.csrf_token() }} 25 | 26 | {{ form.image.label(class="custom-file-label") }} 27 | {% if form.image.errors %} 28 |
29 | {% for error in form.image.errors %} 30 | {{ error }} 31 | {% endfor %} 32 |
33 | {% else %} 34 |
35 | {{ form.image(class="custom-file-input", 36 | id="new-image", onchange="previewImage(event)") }} 37 |
38 | {% endif %} 39 |
40 |
41 | 42 |
43 |
44 | {{ form.submit(class="btn btn-primary", id ="submit", disabled=True)}} 45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |

What is this?

53 |
54 |
55 |

This is a mask detector, an algorithm based on deep neural networks that detects people in images and 56 | write a bounding box around faces, looking if they were masks or not. This is not for security 57 | purpose.

58 |

If you are interested in more details, check this post I wrote!

59 |
60 |
61 |

Who I am

62 |
63 |
64 |

I'm Galileo Parise, data scientist and matematician, and I've developed what you see during Italy's 65 | second lockdown in November, in which I had lots of free time. If you are interested in this and ohter 66 | stories, 67 | you can follow me on Linkedin and on Medium. 68 | Hoping to get soon over this situation, 69 | I hope you all good health:

70 |

please, stay safe and wear a mask.

71 |

72 |
73 |
74 |
75 | {% endblock %} 76 | {% block custom_js %} 77 | 132 | 133 | {% endblock %} -------------------------------------------------------------------------------- /CV-Mask-detection/app/templates/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 14 | 15 | Mask detector live 16 | 33 | 34 | 35 |
36 |
37 | 38 | 39 | 56 | 57 | 58 | 75 | 76 |
77 |
78 | {% with messages = get_flashed_messages() %} 79 | {% if messages %} 80 | {% for message in messages %} 81 | {{ message }} 82 | {% endfor %} 83 | {% endif %} 84 | {% endwith %} 85 | 86 | 87 | {% block content %} 88 | {% endblock %} 89 |
90 | 118 |
119 | 120 | 121 | 124 | 127 | {% block custom_js %} 128 | {% endblock %} 129 | 130 | -------------------------------------------------------------------------------- /CV-Mask-detection/environment.yml: -------------------------------------------------------------------------------- 1 | name: CV_playground 2 | channels: 3 | - defaults 4 | dependencies: 5 | - ca-certificates=2020.10.14=0 6 | - certifi=2020.6.20=pyhd3eb1b0_3 7 | - click=7.1.2=py_0 8 | - flask=1.1.2=py_0 9 | - itsdangerous=1.1.0=py37_0 10 | - jinja2=2.11.2=py_0 11 | - markupsafe=1.1.1=py37hfa6e2cd_1 12 | - openssl=1.1.1h=he774522_0 13 | - pip=20.2.3=py37_0 14 | - python=3.7.9=h60c2a47_0 15 | - setuptools=50.3.0=py37h9490d1a_1 16 | - sqlite=3.33.0=h2a8f88b_0 17 | - vc=14.1=h0510ff6_4 18 | - vs2015_runtime=14.16.27012=hf0eaf9b_3 19 | - werkzeug=1.0.1=py_0 20 | - wheel=0.35.1=py_0 21 | - wincertstore=0.2=py37_0 22 | - zlib=1.2.11=h62dcd97_4 23 | - pip: 24 | - absl-py==0.10.0 25 | - appdirs==1.4.4 26 | - argon2-cffi==20.1.0 27 | - astunparse==1.6.3 28 | - async-generator==1.10 29 | - attrs==20.2.0 30 | - backcall==0.2.0 31 | - bleach==3.2.1 32 | - cachetools==4.1.1 33 | - cffi==1.14.3 34 | - chardet==3.0.4 35 | - colorama==0.4.3 36 | - cycler==0.10.0 37 | - decorator==4.4.2 38 | - defusedxml==0.6.0 39 | - distlib==0.3.1 40 | - entrypoints==0.3 41 | - filelock==3.0.12 42 | - flask-socketio==4.3.1 43 | - flask-wtf==0.14.3 44 | - gast==0.3.3 45 | - google-auth==1.22.1 46 | - google-auth-oauthlib==0.4.1 47 | - google-pasta==0.2.0 48 | - grpcio==1.32.0 49 | - gunicorn==20.0.4 50 | - h5py==2.10.0 51 | - idna==2.10 52 | - importlib-metadata==2.0.0 53 | - imutils==0.5.3 54 | - ipykernel==5.3.4 55 | - ipython==7.18.1 56 | - ipython-genutils==0.2.0 57 | - ipywidgets==7.5.1 58 | - jedi==0.17.2 59 | - joblib==0.17.0 60 | - jsonschema==3.2.0 61 | - jupyter==1.0.0 62 | - jupyter-client==6.1.7 63 | - jupyter-console==6.2.0 64 | - jupyter-core==4.6.3 65 | - jupyterlab-pygments==0.1.2 66 | - keras==2.4.3 67 | - keras-preprocessing==1.1.2 68 | - kiwisolver==1.2.0 69 | - markdown==3.3 70 | - matplotlib==3.3.2 71 | - mistune==0.8.4 72 | - nbclient==0.5.0 73 | - nbconvert==6.0.7 74 | - nbformat==5.0.7 75 | - nest-asyncio==1.4.1 76 | - notebook==6.1.4 77 | - numpy==1.18.5 78 | - oauthlib==3.1.0 79 | - opencv-contrib-python==4.4.0.46 80 | - opencv-python==4.4.0.44 81 | - opt-einsum==3.3.0 82 | - packaging==20.4 83 | - pandas==1.1.3 84 | - pandocfilters==1.4.2 85 | - parso==0.7.1 86 | - pickleshare==0.7.5 87 | - pillow==7.2.0 88 | - prometheus-client==0.8.0 89 | - prompt-toolkit==3.0.7 90 | - protobuf==3.13.0 91 | - pyasn1==0.4.8 92 | - pyasn1-modules==0.2.8 93 | - pycparser==2.20 94 | - pygments==2.7.1 95 | - pyparsing==2.4.7 96 | - pyrsistent==0.17.3 97 | - python-dateutil==2.8.1 98 | - python-engineio==3.13.2 99 | - python-socketio==4.6.0 100 | - pytz==2020.1 101 | - pywin32==228 102 | - pywinpty==0.5.7 103 | - pyyaml==5.3.1 104 | - pyzmq==19.0.2 105 | - qtconsole==4.7.7 106 | - qtpy==1.9.0 107 | - requests==2.24.0 108 | - requests-oauthlib==1.3.0 109 | - rsa==4.6 110 | - scikit-learn==0.23.2 111 | - scipy==1.5.2 112 | - send2trash==1.5.0 113 | - six==1.15.0 114 | - sklearn==0.0 115 | - tensorboard==2.3.0 116 | - tensorboard-plugin-wit==1.7.0 117 | - tensorflow==2.3.1 118 | - tensorflow-estimator==2.3.0 119 | - termcolor==1.1.0 120 | - terminado==0.9.1 121 | - testpath==0.4.4 122 | - threadpoolctl==2.1.0 123 | - tornado==6.0.4 124 | - traitlets==5.0.4 125 | - urllib3==1.25.10 126 | - virtualenv==20.2.1 127 | - waitress==1.4.4 128 | - wcwidth==0.2.5 129 | - webencodings==0.5.1 130 | - widgetsnbextension==3.5.1 131 | - wrapt==1.12.1 132 | - wtforms==2.3.3 133 | - zipp==3.3.0 134 | 135 | -------------------------------------------------------------------------------- /CV-Mask-detection/mask_detection_live.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/mask_detection_live.gif -------------------------------------------------------------------------------- /CV-Mask-detection/models/mask_mobilenet.h5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/models/mask_mobilenet.h5 -------------------------------------------------------------------------------- /CV-Mask-detection/models/training_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/models/training_plot.png -------------------------------------------------------------------------------- /CV-Mask-detection/requirements.txt: -------------------------------------------------------------------------------- 1 | absl-py==0.10.0 2 | argon2-cffi==20.1.0 3 | astunparse==1.6.3 4 | async-generator==1.10 5 | attrs==20.2.0 6 | backcall==0.2.0 7 | bleach==3.2.1 8 | cachetools==4.1.1 9 | certifi==2020.6.20 10 | cffi==1.14.3 11 | chardet==3.0.4 12 | click==7.1.2 13 | colorama==0.4.3 14 | cycler==0.10.0 15 | decorator==4.4.2 16 | defusedxml==0.6.0 17 | entrypoints==0.3 18 | Flask==1.1.2 19 | Flask-SocketIO==4.3.1 20 | Flask-WTF==0.14.3 21 | gast==0.3.3 22 | google-auth==1.22.1 23 | google-auth-oauthlib==0.4.1 24 | google-pasta==0.2.0 25 | grpcio==1.32.0 26 | gunicorn==20.0.4 27 | h5py==2.10.0 28 | idna==2.10 29 | importlib-metadata==2.0.0 30 | imutils==0.5.3 31 | ipykernel==5.3.4 32 | ipython-genutils==0.2.0 33 | itsdangerous==1.1.0 34 | jedi==0.17.2 35 | Jinja2==2.11.2 36 | joblib==0.17.0 37 | jsonschema==3.2.0 38 | Keras==2.4.3 39 | Keras-Preprocessing==1.1.2 40 | kiwisolver==1.2.0 41 | Markdown==3.3 42 | matplotlib==3.3.2 43 | mistune==0.8.4 44 | mtcnn==0.1.0 45 | nbclient==0.5.0 46 | nbconvert==6.0.7 47 | nbformat==5.0.7 48 | nest-asyncio==1.4.1 49 | notebook==6.1.4 50 | numpy==1.18.5 51 | oauthlib==3.1.0 52 | opencv-contrib-python-headless==4.4.0.46 53 | opt-einsum==3.3.0 54 | packaging==20.4 55 | pandas==1.1.3 56 | pandocfilters==1.4.2 57 | parso==0.7.1 58 | pickleshare==0.7.5 59 | Pillow==7.2.0 60 | prometheus-client==0.8.0 61 | prompt-toolkit==3.0.7 62 | protobuf==3.13.0 63 | pyasn1==0.4.8 64 | pyasn1-modules==0.2.8 65 | pycparser==2.20 66 | Pygments==2.7.1 67 | pyparsing==2.4.7 68 | pyrsistent==0.17.3 69 | python-dateutil==2.8.1 70 | python-engineio==3.13.2 71 | python-socketio==4.6.0 72 | pytz==2020.1 73 | pywinpty==0.5.7 74 | PyYAML==5.3.1 75 | pyzmq==19.0.2 76 | qtconsole==4.7.7 77 | QtPy==1.9.0 78 | requests==2.24.0 79 | requests-oauthlib==1.3.0 80 | rsa==4.6 81 | scikit-learn==0.23.2 82 | scipy==1.5.2 83 | Send2Trash==1.5.0 84 | six==1.15.0 85 | sklearn==0.0 86 | statsmodels==0.11.0 87 | tabula-py==1.4.3 88 | tensorboard==2.3.0 89 | tensorboard-plugin-wit==1.7.0 90 | tensorflow-cpu==2.3.1 91 | tensorflow-estimator==2.3.0 92 | termcolor==1.1.0 93 | terminado==0.9.1 94 | testpath==0.4.4 95 | threadpoolctl==2.1.0 96 | tornado==6.0.4 97 | urllib3==1.25.10 98 | waitress==1.4.4 99 | wcwidth==0.2.5 100 | webencodings==0.5.1 101 | Werkzeug==1.0.1 102 | widgetsnbextension==3.5.1 103 | wincertstore==0.2 104 | wrapt==1.12.1 105 | WTForms==2.3.3 106 | XlsxWriter==1.2.6 107 | zipp==3.3.0 108 | -------------------------------------------------------------------------------- /CV-Mask-detection/source/__pycache__/test_new_images.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/CV-Mask-detection/source/__pycache__/test_new_images.cpython-310.pyc -------------------------------------------------------------------------------- /CV-Mask-detection/source/test_new_images.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import imutils 4 | from tensorflow import keras 5 | import cv2 6 | import numpy as np 7 | from tensorflow.python.keras.applications.mobilenet_v2 import preprocess_input 8 | 9 | from source.utils import load_cascade_detector, preprocess_face_frame, decode_prediction, write_bb 10 | 11 | POSSIBLE_EXT = [".png", ".jpg", ".jpeg"] 12 | model = keras.models.load_model('models/mask_mobilenet.h5') 13 | face_detector_model = load_cascade_detector() 14 | 15 | 16 | def detect_mask_in_image(image): 17 | image = imutils.resize(image, width=600) 18 | 19 | # convert an image from one color space to another 20 | # (to grayscale) 21 | gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 22 | faces = face_detector_model.detectMultiScale(gray, 23 | scaleFactor=1.05, 24 | minNeighbors=4, 25 | minSize=(40, 40), 26 | flags=cv2.CASCADE_SCALE_IMAGE, 27 | ) 28 | clone_image = image.copy() 29 | 30 | faces_dict = {"faces_list": [], 31 | "faces_rect": [] 32 | } 33 | 34 | for rect in faces: 35 | (x, y, w, h) = rect 36 | face_frame = clone_image[y:y + h, x:x + w] 37 | # preprocess image 38 | face_frame_array = preprocess_face_frame(face_frame) 39 | 40 | faces_dict["faces_list"].append(face_frame_array) 41 | faces_dict["faces_rect"].append(rect) 42 | 43 | if faces_dict["faces_list"]: 44 | faces_preprocessed = preprocess_input(np.array(faces_dict["faces_list"])) 45 | preds = model.predict(faces_preprocessed) 46 | for i, pred in enumerate(preds): 47 | mask_or_not, confidence = decode_prediction(pred) 48 | write_bb(mask_or_not, confidence, faces_dict["faces_rect"][i], clone_image) 49 | 50 | return clone_image 51 | 52 | 53 | def test_on_custom_image(path): 54 | filename, file_extension = os.path.splitext(path) 55 | if file_extension not in POSSIBLE_EXT: 56 | raise Exception("possible file extensions are .png, .jpg, .jpeg") 57 | if not os.path.exists(path): 58 | raise FileNotFoundError("file not found") 59 | image = cv2.imread(path) 60 | image_masked = detect_mask_in_image(image) 61 | cv2.imwrite(filename + "_mask_detected.png", image_masked) 62 | return 63 | 64 | 65 | if __name__ == '__main__': 66 | path = input("please enter your image filepath:") 67 | test_on_custom_image(path) 68 | -------------------------------------------------------------------------------- /CV-Mask-detection/source/train_model.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from imutils import paths 3 | import os 4 | import numpy as np 5 | from tensorflow.keras import callbacks, Sequential 6 | import pandas as pd 7 | from tensorflow.keras.preprocessing.image import load_img, img_to_array 8 | from tensorflow.keras.applications.mobilenet_v2 import preprocess_input 9 | from tensorflow.keras.preprocessing.image import ImageDataGenerator 10 | from tensorflow.keras.utils import to_categorical 11 | 12 | from tensorflow.keras.applications import MobileNetV2 13 | from tensorflow.keras.layers import Input, Dense, Dropout, Flatten, AveragePooling2D 14 | from tensorflow.keras.models import Model 15 | from sklearn.preprocessing import LabelBinarizer 16 | from sklearn.model_selection import train_test_split 17 | from tensorflow.keras.optimizers import Adam 18 | import matplotlib.pyplot as plt 19 | from sklearn.metrics import classification_report 20 | 21 | sys.path.append("../") 22 | 23 | PATH_TO_IMAGE = "../data/mask_dataset" 24 | MODELS_PATH = "../models" 25 | # initialize the initial learning rate, number of epochs to train for, 26 | # and batch size 27 | INIT_LR = 1e-4 28 | EPOCHS = 100 29 | BS = 32 30 | 31 | 32 | def collect_images_and_labels(path_to_images): 33 | # in seguito, usare https://keras.io/api/preprocessing/image/ 34 | """ 35 | :param path_to_images should be the root folder, in which there is a folder for each label, and the folder's name is 36 | the label itself 37 | :return: a list with images and a list with labels 38 | """ 39 | data = [] 40 | labels = [] 41 | 42 | for img_path in list(paths.list_images(path_to_images)): 43 | # extract the class label from the filename 44 | label = img_path.split(os.path.sep)[-2] 45 | 46 | # load the input image as (224x224) and preprocess it 47 | image = load_img(img_path, target_size=(224, 224)) 48 | image = img_to_array(image) 49 | image = preprocess_input(image) 50 | 51 | # update the data and labels lists, respectively 52 | data.append(image) 53 | labels.append(label) 54 | 55 | return data, labels 56 | 57 | 58 | def preprocess_labels(labels): 59 | """ 60 | :param labels: list of string 61 | :return: np array of 0/1 62 | """ 63 | lb = LabelBinarizer() 64 | labels = lb.fit_transform(labels) 65 | labels = to_categorical(labels) 66 | return labels 67 | 68 | 69 | def tts_split(data, labels): 70 | (x_train, x_test, y_train, y_test) = train_test_split(data, labels, test_size=0.10, stratify=labels, 71 | random_state=42) 72 | (x_train, x_test, y_train, y_test) = (np.array(x_train), np.array(x_test), np.array(y_train), np.array(y_test)) 73 | return x_train, x_test, y_train, y_test 74 | 75 | 76 | def load_base_mobilenetv2(): 77 | # load the MobileNetV2 network, left off the head FC layer sets 78 | baseModel = MobileNetV2(weights="imagenet", include_top=False, input_tensor=Input(shape=(224, 224, 3))) 79 | 80 | # construct the head of the model that will be placed on top of the 81 | # the base model 82 | headModel = Sequential(baseModel) 83 | headModel.add(AveragePooling2D(pool_size=(7, 7))) 84 | headModel.add(Flatten(name="flatten")) 85 | headModel.add(Dense(128, activation="relu")) 86 | headModel.add(Dropout(0.5)) 87 | headModel.add(Dense(2, activation="softmax")) 88 | 89 | # place the head FC model on top of the base model 90 | model = headModel # Model(inputs=baseModel.input, outputs=headModel) 91 | print(model.summary()) 92 | 93 | # freeze layers of base models so they will 94 | # *not* be updated during the first training process 95 | for layer in baseModel.layers: 96 | layer.trainable = False 97 | 98 | return model 99 | 100 | 101 | def plot_train_history(H): 102 | # plot the training loss and accuracy 103 | N = len(H.epoch) 104 | plt.style.use("ggplot") 105 | plt.figure() 106 | plt.plot(np.arange(0, N), H.history["loss"], label="train_loss") 107 | plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss") 108 | plt.plot(np.arange(0, N), H.history["accuracy"], label="train_acc") 109 | plt.plot(np.arange(0, N), H.history["val_accuracy"], label="val_acc") 110 | plt.title("Training Loss and Accuracy") 111 | plt.xlabel("Epoch #") 112 | plt.ylabel("Loss/Accuracy") 113 | plt.legend(loc="lower left") 114 | plt.savefig(os.path.join(MODELS_PATH, "training_plot.png")) 115 | report_df = pd.DataFrame({ 116 | "loss": H.history["loss"], 117 | "val_accuracy": H.history["val_accuracy"], 118 | "val_loss": H.history["val_loss"], 119 | "accuracy": H.history["accuracy"] 120 | }) 121 | report_df.to_csv(os.path.join(MODELS_PATH, "model_report.csv")) 122 | 123 | 124 | def fine_tune_model(): 125 | data, labels = collect_images_and_labels(PATH_TO_IMAGE) 126 | labels = preprocess_labels(labels) 127 | x_train, x_test, y_train, y_test = tts_split(data, labels) 128 | 129 | model = load_base_mobilenetv2() 130 | 131 | # construct the training image generator for data augmentation 132 | aug = ImageDataGenerator(rotation_range=20, 133 | zoom_range=0.15, 134 | width_shift_range=0.2, 135 | height_shift_range=0.2, 136 | shear_range=0.15, 137 | horizontal_flip=True, 138 | fill_mode="nearest", 139 | validation_split=0.2) 140 | 141 | train_generator = aug.flow(x_train, y_train, batch_size=BS, subset="training") 142 | val_generator = aug.flow(x_train, y_train, batch_size=BS, subset="validation") 143 | 144 | # compile our model 145 | opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS) 146 | model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["accuracy"]) 147 | 148 | # add callbacks 149 | model_callbacks = [callbacks.EarlyStopping(monitor='loss', min_delta=0, patience=2, verbose=0, mode='auto'), 150 | callbacks.ModelCheckpoint( 151 | filepath=os.path.join(MODELS_PATH, 'weights-{epoch:02d}-{accuracy:.2f}.hdf5'), 152 | save_weights_only=True, 153 | monitor='accuracy', 154 | mode='max', 155 | save_best_only=True)] 156 | 157 | # train the head of the network 158 | H = model.fit( 159 | train_generator, 160 | steps_per_epoch=int(np.ceil(train_generator.n / float(BS))), 161 | validation_data=val_generator, 162 | validation_steps=int(np.ceil(val_generator.n / float(BS))), # int(np.ceil(len(x_test) / BS)), 163 | epochs=EPOCHS, 164 | callbacks=model_callbacks 165 | ) 166 | 167 | # make predictions on the testing set 168 | id_pred = model.predict(x_test, batch_size=BS) 169 | 170 | # for each image in the testing set we need to find the index of the 171 | # label with corresponding largest predicted probability 172 | id_pred = np.argmax(id_pred, axis=1) 173 | 174 | # show a nicely formatted classification report 175 | print(classification_report(y_test.argmax(axis=1), id_pred, 176 | target_names=["without_mask", "with_mask"])) 177 | 178 | plot_train_history(H) 179 | # serialize the model to disk 180 | model.save(os.path.join(MODELS_PATH, "mask_mobilenet.h5"), save_format="h5") 181 | 182 | 183 | if __name__ == '__main__': 184 | fine_tune_model() 185 | -------------------------------------------------------------------------------- /CV-Mask-detection/source/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | from keras_preprocessing.image import img_to_array 4 | 5 | 6 | def preprocess_face_frame(face_frame): 7 | # convert to RGB 8 | face_frame = cv2.cvtColor(face_frame, cv2.COLOR_BGR2RGB) 9 | # preprocess input image for mobilenet 10 | face_frame_resized = cv2.resize(face_frame, (224, 224)) 11 | face_frame_array = img_to_array(face_frame_resized) 12 | return face_frame_array 13 | 14 | 15 | def decode_prediction(pred): 16 | (mask, no_mask) = pred 17 | mask_or_not = "Mask" if mask > no_mask else "No mask" 18 | confidence = f"{(max(mask, no_mask) * 100):.2f}" 19 | return mask_or_not, confidence 20 | 21 | 22 | def write_bb(mask_or_not, confidence, box, frame): 23 | (x, y, w, h) = box 24 | color = (0, 255, 0) if mask_or_not == "Mask" else (0, 0, 255) 25 | label = f"{mask_or_not}: {confidence}%" 26 | 27 | cv2.putText(frame, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2) 28 | cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) 29 | 30 | 31 | def load_cascade_detector(): 32 | cascade_path = os.path.dirname(cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml" 33 | face_detector = cv2.CascadeClassifier(cascade_path) 34 | return face_detector 35 | -------------------------------------------------------------------------------- /CV-Mask-detection/source/video_detector.py: -------------------------------------------------------------------------------- 1 | import time 2 | import numpy as np 3 | import cv2 4 | import imutils 5 | from imutils.video import VideoStream 6 | from tensorflow import keras 7 | from tensorflow.python.keras.applications.mobilenet_v2 import preprocess_input 8 | 9 | from source.utils import preprocess_face_frame, decode_prediction, write_bb, load_cascade_detector 10 | 11 | model = keras.models.load_model('models/mask_mobilenet.h5') 12 | face_detector = load_cascade_detector() 13 | 14 | 15 | def video_mask_detector(): 16 | video = VideoStream(src=0).start() 17 | time.sleep(1.0) 18 | while True: 19 | # Capture frame-by-frame 20 | frame = video.read() 21 | 22 | frame = detect_mask_in_frame(frame) 23 | # Display the resulting frame 24 | # show the output frame 25 | cv2.imshow("Mask detector", frame) 26 | 27 | key = cv2.waitKey(1) & 0xFF 28 | # if the `q` key was pressed, break from the loop 29 | if key == ord("q"): 30 | break 31 | # cleanup 32 | cv2.destroyAllWindows() 33 | video.stop() 34 | 35 | 36 | def detect_mask_in_frame(frame): 37 | frame = imutils.resize(frame, width=500) 38 | 39 | # convert an image from one color space to another 40 | # (to grayscale) 41 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 42 | 43 | faces = face_detector.detectMultiScale(gray, 44 | scaleFactor=1.1, 45 | minNeighbors=5, 46 | minSize=(40, 40), 47 | flags=cv2.CASCADE_SCALE_IMAGE, 48 | ) 49 | 50 | faces_dict = {"faces_list": [], 51 | "faces_rect": [] 52 | } 53 | 54 | for rect in faces: 55 | (x, y, w, h) = rect 56 | face_frame = frame[y:y + h, x:x + w] 57 | # preprocess image 58 | face_frame_prepared = preprocess_face_frame(face_frame) 59 | 60 | faces_dict["faces_list"].append(face_frame_prepared) 61 | faces_dict["faces_rect"].append(rect) 62 | 63 | if faces_dict["faces_list"]: 64 | faces_preprocessed = preprocess_input(np.array(faces_dict["faces_list"])) 65 | preds = model.predict(faces_preprocessed) 66 | 67 | for i, pred in enumerate(preds): 68 | mask_or_not, confidence = decode_prediction(pred) 69 | write_bb(mask_or_not, confidence, faces_dict["faces_rect"][i], frame) 70 | 71 | return frame 72 | 73 | 74 | if __name__ == '__main__': 75 | video_mask_detector() 76 | -------------------------------------------------------------------------------- /CV-Mask-detection/wsgi.py: -------------------------------------------------------------------------------- 1 | from app import create_app 2 | 3 | app = create_app() 4 | 5 | if __name__ == '__main__': 6 | from waitress import serve 7 | serve(app) 8 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/Threshold.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/Threshold.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/Title .png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/Title .png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/abe_toon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/abe_toon.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/boy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/boy.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/cwoc.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/cwoc.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/edge.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/filters_tutorial_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/filters_tutorial_02.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/gssoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/gssoc.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/preview-removebg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/preview-removebg.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/result (2).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/result (2).jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/uaceit.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonification/Assets/uaceit.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Assets/vishal.txt: -------------------------------------------------------------------------------- 1 | ``` 2 | helllo world 3 | 4 | ``` 5 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/Readme.md: -------------------------------------------------------------------------------- 1 | # Cartoonify an Image with OpenCV in Python 2 | 3 | 4 | ## Process of converting an image to a cartoon 5 | 6 | - To convert an image to a cartoon, multiple transformations are done. 7 | - Convert the image to a Grayscale image. Yes, similar to the old day’s pictures.! 8 | - The Grayscale image is smoothened 9 | - Extract the edges in the image 10 | - Form a colour image and mask it with edges. 11 | - This creates a beautiful cartoon image with edges and lightened colour of the original image. 12 | 13 | ## How to start 14 | 15 | - Fork and Clone the repository using- 16 | ``` 17 | git clone https://github.com/akshitagupta15june/Face-X.git 18 | ``` 19 | - Create virtual environment- 20 | ``` 21 | - python -m venv env 22 | - source env/bin/activate (Linux) 23 | - env\Scripts\activate (Windows) 24 | ``` 25 | - Install dependencies 26 | - Go to project directory 27 | ``` 28 | - cd Cartoonify Image 29 | ``` 30 | - Open Terminal 31 | ``` 32 | python cartoonify_without_GUI.py --image IMAGE_PATH 33 | ``` 34 | ### 1. Detecting and emphasizing edges 35 | - Convert the original color image into grayscale 36 | - Using adaptive`thresholding` to detect and `emphasize` the edges in an edge mask. 37 | - Apply a median blur to reduce image noise. 38 | - `-->` To produce accurate carton effects, as the first step, we need to understand the difference between a common digital image and a cartoon image.At the first glance we can clearly see two major differences. 39 | - The first difference is that the colors in the cartoon image are more homogeneous as compared to the normal image. 40 | - The second difference is noticeable within the edges that are much sharper and more pronounced in the cartoon. 41 | - Let’s begin by importing the necessary libraries and loading the input image. 42 | ``` 43 | import cv2 44 | import numpy as np 45 | ``` 46 | - Now, we are going to load the image. 47 | ``` 48 | img = cv2.imread("Superman.jpeg") 49 | cv2_imshow(img) 50 | ``` 51 | - The next step is to detect the edges. For that task, we need to choose the most suitable method. Remember, our goal is to detect clear edges. There are several edge detectors that we can pick. Our first choice will be one of the most common detectors, and that is the `Canny edge detector`. But unfortunately, if we apply this detector we will not be able to achieve desirable results. We can proceed with Canny, and yet you can see that there are too many details captured. This can be changed if we play around with Canny’s input parameters (numbers 100 and 200). 52 | - Although Canny is an excellent edge detector that we can use in many cases in our code we will use a threshold method that gives us more satisfying results. It uses a threshold pixel value to convert a grayscale image into a binary image. For instance, if a pixel value in the original image is above the threshold, it will be assigned to 255. Otherwise, it will be assigned to 0 as we can see in the following image. 53 | - 54 | 55 | #### The next step is to apply `cv2.adaptiveThreshold()function`. As the parameters for this function we need to define: 56 | 57 | - max value which will be set to 255 58 | - `cv2.ADAPTIVE_THRESH_MEAN_C `: a threshold value is the mean of the neighbourhood area. 59 | - `cv2.ADAPTIVE_THRESH_GAUSSIAN_C` : a threshold value is the weighted sum of neighbourhood values where weights are a gaussian window. 60 | - `Block Size` – It determents the size of the neighbourhood area. 61 | - `C `– It is just a constant which is subtracted from the calculated mean (or the weighted mean). 62 | ``` 63 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 64 | edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 5) 65 | ``` 66 | ``` 67 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 68 | gray_1 = cv2.medianBlur(gray, 5) 69 | edges = cv2.adaptiveThreshold(gray_1, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 5) 70 | ``` 71 | - 72 | ### 2. Image filtering 73 | - Apply a bilateral filter to create homogeneous colors on the image. 74 | ### 3. Creating a cartoon effect 75 | - Use a bitwise operation to combine the processed color image with the edge mask image. 76 | - Our final step is to combine the previous two: We will use `cv2.bitwise_and()` the function to mix edges and the color image into a single one 77 | ``` 78 | cartoon = cv2.bitwise_and(color, color, mask=edges) 79 | cv2_imshow(cartoon) 80 | ``` 81 | ### 4. Creating a cartoon effect using color quantization 82 | - Another interesting way to create a cartoon effect is by using the color quantization method. This method will reduce the number of colors in the image and that will create a cartoon-like effect. We will perform color quantization by using the K-means clustering algorithm for displaying output with a limited number of colors. First, we need to define `color_quantization()` function. 83 | ``` 84 | def color_quantization(img, k): 85 | # Defining input data for clustering 86 | data = np.float32(img).reshape((-1, 3)) 87 | # Defining criteria 88 | criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0) 89 | # Applying cv2.kmeans function 90 | ret, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) 91 | center = np.uint8(center) 92 | result = center[label.flatten()] 93 | result = result.reshape(img.shape) 94 | return result 95 | ``` 96 | - Different values for K will determine the number of colors in the output picture. So, for our goal, we will reduce the number of colors to 7. Let’s look at our results. 97 | ``` 98 | img_1 = color_quantization(img, 7) 99 | cv2_imshow(img_1) 100 | ``` 101 | 102 | ## Steps to develop Image Cartoonifier 103 | 104 | - Step 1: Importing the required modules 105 | ``` 106 | import cv2 107 | import argparse 108 | ``` 109 | - Step 2: Transforming an image to grayscale 110 | ``` 111 | #converting an image to grayscale 112 | grayScaleImage = cv2.cvtColor(originalmage, cv2.COLOR_BGR2GRAY) 113 | ReSized2 = cv2.resize(grayScaleImage, (960, 540)) 114 | #plt.imshow(ReSized2, cmap='gray') 115 | ``` 116 | - Transforming an image to grayscale 117 | - `cvtColor(image, flag)` is a method in cv2 which is used to transform an image into the colour-space mentioned as ‘flag’. Here, our first step is to convert the image into grayscale. Thus, we use the `BGR2GRAY` flag. This returns the image in grayscale. A grayscale image is stored as `grayScaleImage`. 118 | - After each transformation, we resize the resultant image using the resize() method in cv2 and display it using imshow() method. This is done to get more clear insights into every single transformation step. 119 | - Step 3: Smoothening a grayscale image 120 | ``` 121 | #applying median blur to smoothen an image 122 | smoothGrayScale = cv2.medianBlur(grayScaleImage, 5) 123 | ReSized3 = cv2.resize(smoothGrayScale, (960, 540)) 124 | #plt.imshow(ReSized3, cmap='gray') 125 | ``` 126 | - Smoothening a grayscale image 127 | - To smoothen an image, we simply apply a blur effect. This is done using medianBlur() function. Here, the center pixel is assigned a mean value of all the pixels which fall under the kernel. In turn, creating a blur effect. 128 | - Step 4: Retrieving the edges of an image 129 | ``` 130 | #retrieving the edges for cartoon effect 131 | #by using thresholding technique 132 | getEdge = cv2.adaptiveThreshold(smoothGrayScale, 255, 133 | cv2.ADAPTIVE_THRESH_MEAN_C, 134 | cv2.THRESH_BINARY, 9, 9) 135 | ReSized4 = cv2.resize(getEdge, (960, 540)) 136 | #plt.imshow(ReSized4, cmap='gray') 137 | ``` 138 | - Cartoon effect has two specialties: 139 | - Highlighted Edges 140 | - Smooth color 141 | - In this step, we will work on the first specialty. Here, we will try to retrieve the edges and highlight them. This is attained by the adaptive thresholding technique. The threshold value is the mean of the neighborhood pixel values area minus the constant C. C is a constant that is subtracted from the mean or weighted sum of the neighborhood pixels. Thresh_binary is the type of threshold applied, and the remaining parameters determine the block size. 142 | - Step 5: Giving a Cartoon Effect 143 | ``` 144 | #masking edged image with our "BEAUTIFY" image 145 | cartoonImage = cv2.bitwise_and(colorImage, colorImage, mask=getEdge) 146 | ReSized6 = cv2.resize(cartoonImage, (960, 540)) 147 | #plt.imshow(ReSized6, cmap='gray') 148 | 149 | ``` 150 | ### Results Obtained 151 | 152 | 153 | 154 |

155 |

Community and Contributing

156 |

Please do! Contributions, updates, and pull requests are welcome. This project is community-built and welcomes collaboration. Contributors are expected to adhere to the GOSSC Code of Conduct. 157 |

158 |

159 | Jump into our Discord! Our projects are community-built and welcome collaboration. 👍Be sure to see the Face-X Community Welcome Guide for a tour of resources available to you. 160 |

161 |

162 | Not sure where to start? Grab an open issue with the help-wanted label 163 |

164 | 165 | **Open Source First** 166 | 167 | best practices for managing all aspects of distributed services. Our shared commitment to the open-source spirit push the Face-X community and its projects forward.

168 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonification/cartoonify_without_GUI.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import argparse 3 | 4 | video_capture = cv2.VideoCapture(0) 5 | fourcc = cv2.VideoWriter_fourcc(*'XVID') 6 | out = cv2.VideoWriter('cartoonised.avi', fourcc, 20.0, (1200, 600)) 7 | 8 | while (video_capture.isOpened()): 9 | ret, frame = video_capture.read() 10 | 11 | if ret == True: 12 | 13 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 14 | resized_image= cv2.resize(gray, (1200, 600)) 15 | blurred = cv2.medianBlur(resized_image, 9) 16 | 17 | thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, 18 | cv2.THRESH_MASK, 11,11) 19 | 20 | 21 | original_image = cv2.bilateralFilter(frame,9, 300, 300) 22 | 23 | cartoon = cv2.bitwise_and(original_image, original_image, mask= thresh) 24 | 25 | out.write(cartoon) 26 | 27 | 28 | 29 | cv2.imshow('Cartoon_image', cartoon) 30 | cv2.imshow('Original Image', frame) 31 | 32 | if cv2.waitKey(1) & 0xFF ==27: 33 | break 34 | 35 | else: 36 | print("Camera not available, Please upload a photo") 37 | 38 | 39 | if(video_capture.isOpened() == False): 40 | arg_parse = argparse.ArgumentParser() 41 | arg_parse.add_argument("-i", "--image", required=True, help= "Image Path") 42 | 43 | args= vars(arg_parse.parse_args()) 44 | image = cv2.imread(args['image']) 45 | filename = 'Cartoonified_image.jpg' 46 | resized_image = cv2.resize(image, (600, 450)) 47 | gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 48 | 49 | blurred = cv2.medianBlur(gray_image, 9) 50 | thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11,11) 51 | 52 | original_image = cv2.bilateralFilter(image, 9, 300, 300) 53 | 54 | cartoon = cv2.bitwise_and(original_image, original_image, mask=thresh) 55 | cartoon_resize= cv2.resize(cartoon, (600,450)) 56 | 57 | cv2.imshow("Cartoonified", cartoon_resize) 58 | cv2.imwrite(filename, cartoon) 59 | cv2.imshow("Main Image", resized_image) 60 | 61 | cv2.waitKey(0) 62 | 63 | out.release() 64 | video_capture.release() 65 | cv2.destroyAllWindows() 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify using KMeans/README.md: -------------------------------------------------------------------------------- 1 | [![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/) 2 | 3 | [![Python 3.6](https://img.shields.io/badge/python-3.6-green.svg)](https://www.python.org/downloads/release/python-360/) 4 | # Cartoonify_reality 5 | 6 | Even the basics of image processing if done properly can be handy which otherwise would require a machine learning model.This project is one of such inspiration which **cartoonizes** images and videos using only core **opencv filters** and functions.It also uses K-means clustering algorithm to compress the image. This clustering gives it the basic cartoonish tinge it requires. 7 | 8 | **Algorithm**- K_Means Clustering 9 | 10 | **Filters**-Bialateral Filter, Contours, erode, Canny(edge detection) 11 | 12 | 13 | ### Prerequisites 14 | 15 | What things you need to install the software and how to install them 16 | 17 | ``` 18 | scipy 19 | numpy 20 | cv2 21 | ``` 22 | 23 | ## Getting Started 24 | Download a python interpeter preferable a version beyond 3.0. Install the prerequisute libraries given above. Run vid.py file to cartonify your webcamp feed. Uncomment the last 2 lines of cartoonize.py and run to cartoonify an image. 25 | 26 | ``` 27 | $vid.py 28 | 29 | $cartoonize.py 30 | ``` 31 | ## Original Image 32 | ![original2](https://user-images.githubusercontent.com/65017645/117474063-3b413e80-af78-11eb-8e60-a981f37e2de7.jpg) 33 | 34 | 35 | ## Cartoon Output 36 | ![cartoon](https://user-images.githubusercontent.com/65017645/117474086-41cfb600-af78-11eb-90ec-50cb99d011f3.jpg) 37 | 38 | ## Built With 39 | * [python](https://www.python.org/) - The software used 40 | 41 | ## Documentation 42 | The entire documentation and explanation of code as well as concepts can be found in this article: https://iot4beginners.com/cartoonize-reality-with-opencv-and-raspberry-pi/ 43 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify using KMeans/Resources/cartoon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify using KMeans/Resources/cartoon.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify using KMeans/Resources/original2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify using KMeans/Resources/original2.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify using KMeans/Script/cartoonize.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import scipy 3 | from scipy import stats 4 | import numpy as np 5 | from collections import defaultdict 6 | 7 | 8 | def update_c(C,hist): 9 | while True: 10 | groups=defaultdict(list) 11 | 12 | for i in range(len(hist)): 13 | if(hist[i] == 0): 14 | continue 15 | d=np.abs(C-i) 16 | index=np.argmin(d) 17 | groups[index].append(i) 18 | 19 | new_C=np.array(C) 20 | for i,indice in groups.items(): 21 | if(np.sum(hist[indice])==0): 22 | continue 23 | new_C[i]=int(np.sum(indice*hist[indice])/np.sum(hist[indice])) 24 | 25 | if(np.sum(new_C-C)==0): 26 | break 27 | C=new_C 28 | 29 | return C,groups 30 | 31 | # Calculates K Means clustering 32 | def K_histogram(hist): 33 | 34 | alpha=0.001 35 | N=80 36 | C=np.array([128]) 37 | 38 | while True: 39 | C,groups=update_c(C,hist) 40 | 41 | new_C=set() 42 | for i,indice in groups.items(): 43 | if(len(indice)=3): 53 | c1=(C[i]+left)/2 54 | c2=(C[i]+right)/2 55 | new_C.add(c1) 56 | new_C.add(c2) 57 | else: 58 | new_C.add(C[i]) 59 | else: 60 | new_C.add(C[i]) 61 | if(len(new_C)==len(C)): 62 | break 63 | else: 64 | C=np.array(sorted(new_C)) 65 | return C 66 | 67 | # The main controlling function 68 | def caart(img): 69 | 70 | kernel=np.ones((2,2), np.uint8) 71 | output=np.array(img) 72 | x,y,c=output.shape 73 | for i in range(c): 74 | output[:,:,i]=cv2.bilateralFilter(output[:,:,i],5,150,150) 75 | 76 | edge=cv2.Canny(output, 100, 200) 77 | output=cv2.cvtColor(output,cv2.COLOR_RGB2HSV) 78 | 79 | hists = [] 80 | 81 | hist,_=np.histogram(output[:,:,0],bins =np.arange(180+1)) 82 | hists.append(hist) 83 | hist,_=np.histogram(output[:,:,1],bins =np.arange(256+1)) 84 | hists.append(hist) 85 | hist,_=np.histogram(output[:,:,2],bins =np.arange(256+1)) 86 | hists.append(hist) 87 | 88 | 89 | C=[] 90 | for h in hists: 91 | C.append(K_histogram(h)) 92 | #print("centroids: {0}".format(C)) 93 | 94 | output=output.reshape((-1,c)) 95 | for i in range(c): 96 | channel=output[:,i] 97 | index=np.argmin(np.abs(channel[:, np.newaxis] - C[i]), axis=1) 98 | output[:,i]=C[i][index] 99 | output=output.reshape((x,y,c)) 100 | output=cv2.cvtColor(output, cv2.COLOR_HSV2RGB) 101 | 102 | contours,_=cv2.findContours(edge,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 103 | cv2.drawContours(output,contours,-1,0,thickness=1) 104 | #cartoon = cv2.bitwise_and(output, output, mask=contours) 105 | for i in range(3): 106 | output[:,:,i]=cv2.erode(output[:,:,i], kernel, iterations=1) 107 | #Laplacian = cv2.Laplacian(output,cv2.CV_8U, ksize=11) 108 | #output=output-Laplacian 109 | return output 110 | 111 | #output=caart(cv2.imread("original.jpg")) 112 | #cv2.imwrite("cartoon.jpg", output) 113 | 114 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify using KMeans/Script/vid.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | from caartoonize import caart 4 | 5 | 6 | 7 | videoCaptureObject = cv2.VideoCapture(0) 8 | 9 | out = cv2.VideoWriter('out.mp4', cv2.VideoWriter_fourcc(*'MP4V'), 24, (720, 1280)) 10 | result = True 11 | while(result): 12 | ret,img = videoCaptureObject.read() 13 | img=caart(img) 14 | cv2.imshow("original",np.array(img)) 15 | out.write(img) 16 | if(cv2.waitKey(1) & 0xFF==ord('q')): 17 | break 18 | videoCaptureObject.release() 19 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify using KMeans/images/readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/GUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify-GUI/GUI.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/Readme.md: -------------------------------------------------------------------------------- 1 | ## Cartoonify Image and save it 2 | ### This is a very baisc GUI for cartoonifying iage and save it 3 | ## How to start 4 | 5 | 6 | - Fork the repository 7 | 8 | - Git clone your forked repository 9 | - Create virtual environment- 10 | ``` 11 | - python -m venv env 12 | - source env/bin/activate (Linux) 13 | - env\Scripts\activate (Windows) 14 | ``` 15 | - Install dependencies 16 | - Go to project directory 17 | ``` 18 | - cd Cartoonify Image 19 | ``` 20 | - install these requirements 21 | 22 | ``` 23 | - pip install opencv-python 24 | - pip install tkinter 25 | - pip install easygui 26 | - pip install pillow 27 | ``` 28 | - Open Terminal 29 | ``` 30 | python cartoonify_GUI.py 31 | ``` 32 | 33 | ### Video recording of the process 34 | 35 | [![YouTube link](mq2.jpg)](https://youtu.be/VDqEv6_FDt4 "Cartoonify GUI") 36 | 37 | 38 | ### Screenshots: 39 | 40 | 41 | ### GUI Interface 42 | 43 | 44 | ### Cartoonified Image 45 | 46 | 47 | ### Original Image 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/Updated GUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify-GUI/Updated GUI.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify-GUI/background.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/cartoonified.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify-GUI/cartoonified.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/cartoonify-gui.py: -------------------------------------------------------------------------------- 1 | #Importing the necessary libraries 2 | import tkinter as tk 3 | import numpy as np 4 | from tkinter import * 5 | from tkinter import messagebox 6 | from PIL import Image,ImageTk 7 | import cv2 8 | import easygui 9 | import sys 10 | import os 11 | 12 | #Function Defined for Uploading function: 13 | def upload(): 14 | imagepath = easygui.fileopenbox() 15 | cartoon(imagepath) 16 | 17 | #Function to convert image to cartoon 18 | def cartoon(imagepath): 19 | #Image variable takes image using imagepath 20 | image = cv2.imread(imagepath) 21 | 22 | if image is None: 23 | print('Choose another file') 24 | sys.exit() 25 | height, width, channels = image.shape 26 | print(width, height, channels) 27 | 28 | #Image_resize 29 | if height >=900 and width >=1200: 30 | resized_image = cv2.resize(image, (800, int(700*0.8))) 31 | else: 32 | resized_image = cv2.resize(image, (width, int(width*0.8))) 33 | #sharpen image 34 | 35 | #Putting a filter using numpy array 36 | filter = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]]) 37 | #Sharpening Image using Open CV filter2D function 38 | sharpen_image = cv2.filter2D(resized_image, -1, filter) 39 | #Converting to Fray Image Scale 40 | gray_image = cv2.cvtColor(sharpen_image, cv2.COLOR_BGR2GRAY) 41 | #Blurring the Image 42 | blurred = cv2.medianBlur(gray_image, 9) 43 | # For every pixel, the same threshold value is applied. If the pixel value is smaller than the threshold, it is set to 0, otherwise it is set to a maximum value 44 | thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 11) 45 | #Original Image 46 | original_image = cv2.bilateralFilter(resized_image, 13, 150, 150) 47 | 48 | cartoon = cv2.bitwise_and(original_image, original_image, mask=thresh) 49 | if cartoon.shape[0] >=900 and cartoon.shape[1] >=1200: 50 | cartoon_resize = cv2.resize(cartoon, (800, int(700*0.8))) 51 | else: 52 | cartoon_resize = cv2.resize(cartoon, (cartoon.shape[1], int(cartoon.shape[0]*0.8))) 53 | #cartoon_resize = cv2.resize(cartoon, (width, int(width*0.8))) 54 | 55 | #Displaying the Main,Cartoonified and Sharpened Image 56 | cv2.imshow("Cartoonified", cartoon_resize) 57 | cv2.imshow("Main Image", image) 58 | cv2.imshow("Sharped Image", sharpen_image) 59 | save1 = Button(GUI, text="Save cartoon image", command=lambda: save_image(cartoon_resize, imagepath ), padx=30, pady=5) 60 | save1.configure(background='black', foreground='white', font=('calibri', 12, 'bold')) 61 | save1.pack(side=TOP, pady=50) 62 | 63 | #Saving Image 64 | def save_image(cartoon_resize, imagepath): 65 | name= "CartooniFied" 66 | file = os.path.dirname(os.path.realpath(imagepath)) 67 | last_name = os.path.splitext(imagepath)[1] 68 | path = os.path.join(file, name + last_name ) 69 | cv2.imwrite(path, cartoon_resize) 70 | full_name = "Image " + name + "saved at" + path 71 | 72 | tk.messagebox.showinfo(message=full_name) 73 | 74 | 75 | #create GUI Interface: 76 | 77 | #Defining the basic structure of the application 78 | GUI = tk.Tk() 79 | GUI.geometry('650x500') 80 | GUI.title("Cartoonify Image") 81 | GUI.configure(background='skyblue') 82 | #Loading the Background Image for the Application 83 | load=Image.open("D:\\GitRepo\\Face-X\\Cartoonify Image\\Cartoonify-GUI\\background.png") 84 | render=ImageTk.PhotoImage(load) 85 | img=Label(GUI,image=render) 86 | img.place(x=0,y=0) 87 | 88 | #Defining Buttons 89 | label=Label(GUI, background='black', font=('calibri',20,'bold')) 90 | upload=Button(GUI, text="Cartoonify Image",command=upload, padx=30,pady=5) 91 | upload.configure(background='black', foreground='white',font=('calibri',12,'bold')) 92 | upload.pack(side=TOP,pady=50) 93 | 94 | GUI.mainloop() 95 | 96 | 97 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/dicaprio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify-GUI/dicaprio.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/mq2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify-GUI/mq2.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify-GUI/wp2030093.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify-GUI/wp2030093.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify_face_image/Cartoonify-face_image.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | frame_cap = cv2.VideoCapture(0) #Capturing each Frames from the Camera 3 | while(True): 4 | ret, frame = frame_cap.read() #Reading the Captured Frames 5 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #Applying gray filter 6 | blur_img = cv2.medianBlur(gray_img, 5) #Applying Median Blur 7 | edges = cv2.adaptiveThreshold(blur_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) 8 | color = cv2.bilateralFilter(frame, 9, 250, 250) #Applying Bilateral Filter 9 | cartoon_img = cv2.bitwise_and(color, color, mask=edges) # Bit wise And operation on color and edges images 10 | cv2.imshow("Cartoon Image", cartoon_img) #Displaying the cartoonified Image 11 | if cv2.waitKey(1) & 0xFF == ord(' '): #Press space bar to exit 12 | break 13 | frame_cap.release() 14 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify_face_image/Images/after_face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify_face_image/Images/after_face.png -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify_face_image/Images/face.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify_face_image/Images/face.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify_face_image/Images/readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify_face_image/Images/recof.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonify_face_image/Images/recof.gif -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonify_face_image/readme.md: -------------------------------------------------------------------------------- 1 | # Cartoonifying a face image. 2 | 3 | - To Cartoonify the image we have used Computer vision, Where we apply various filters to the input image to produce a Cartoonified image. To accomplish this we have used Python programming language and opencv a Computer Vision library.
4 | 5 | ## Dependencies: 6 | The Dependencies used are: 7 | - Opencv :It provides the tool for applying computer vison techniques on the image. 8 | - Numpy :Images are stored and processed as numbers, These are taken as arrays. 9 | 10 | ## How to Run: 11 | - Download the directory. 12 | - You can use any Editor, Notebook Or IDE's to open the Cartoonify-face_image.py file. 13 | - Run Cartoonify-face_image.py file. 14 | - Press Space bar to exit. 15 | 16 | ## Steps of its working: 17 | 18 | - We have imported the cv2 and numpy library. 19 | - We are capturing the image frames using cv2.VideoCapture(). 20 | - We are reading the image frames by using frame_cap.read(). 21 | - We are applying Gray scale filter to the image frames using cv2.cvtcolor() and the by passing second parameter as cv2.COLOR_BGR2GRAY. 22 | - We are using MedianBlur on the gray scale image obtained above by setting the kernal size as 5 to blur the image using cv2.medianBlur(). 23 | - We are using adaptive threshold on the image obtained after applying Medianblur, we are using a threshold value of 255 to filter out the pixel and we are using the adaptive method cv2.ADAPTIVE_THRESH_MEAN_C with a threshold type as cv2.THRESH_BINARY and block size 9. 24 | - We are applying a Bilateral filter on the original image frames using cv2.bilateralFilter() with kernal size 9 and the threshold as 250 to remove the Noise in the image. 25 | - We are then applying Bitwise and operation on the Bilateral image and the image obtained after using Adaptive threshold which gives the resulting cartoonified image. 26 | 27 | ## Result: 28 | ### Input Video 29 | ![Actual Video](https://user-images.githubusercontent.com/62636670/111106310-e1755700-857a-11eb-8ac7-3452d3430592.gif) 30 | 31 | ### Output Video 32 | ![Cartoonified Video](https://user-images.githubusercontent.com/62636670/111105513-26988980-8579-11eb-849a-c4babf925260.gif) 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonifying using OpenCV/Cartoonify.py: -------------------------------------------------------------------------------- 1 | #step 1 2 | #Use bilateral filter for edge-aware smoothing. 3 | import cv2 4 | 5 | num_down = 2 # number of downsampling steps 6 | num_bilateral = 7 # number of bilateral filtering steps 7 | 8 | img_rgb = cv2.imread("myCat.jpg") 9 | 10 | # downsample image using Gaussian pyramid 11 | img_color = img_rgb 12 | for _ in range(num_down): 13 | img_color = cv2.pyrDown(img_color) 14 | 15 | # repeatedly apply small bilateral filter instead of 16 | # applying one large filter 17 | for _ in range(num_bilateral): 18 | img_color = cv2.bilateralFilter(img_color, d=9, sigmaColor=9, sigmaSpace=7) 19 | 20 | # upsample image to original size 21 | for _ in range(num_down): 22 | img_color = cv2.pyrUp(img_color) 23 | 24 | #STEP 2 & 3 25 | #Use median filter to reduce noise 26 | # convert to grayscale and apply median blur 27 | img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY) 28 | img_blur = cv2.medianBlur(img_gray, 7) 29 | 30 | #STEP 4 31 | #Use adaptive thresholding to create an edge mask 32 | # detect and enhance edges 33 | img_edge = cv2.adaptiveThreshold(img_blur, 255, 34 | cv2.ADAPTIVE_THRESH_MEAN_C, 35 | cv2.THRESH_BINARY, 36 | blockSize=9, 37 | C=2) 38 | 39 | # Step 5 40 | # Combine color image with edge mask & display picture 41 | # convert back to color, bit-AND with color image 42 | img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB) 43 | img_cartoon = cv2.bitwise_and(img_color, img_edge) 44 | 45 | # display 46 | cv2.imshow("myCat_cartoon", img_cartoon) 47 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonifying using OpenCV/Readme.md: -------------------------------------------------------------------------------- 1 | Currently there are lots of professional cartoonizer applications available in the market but most of the them are not freeware. In order to get the basic cartoon effect, we just need the bilateral filter and some edge dectection mechanism. The bilateral filter will reduce the color palette, which is essential for the cartoon look and edge detection is to produce bold silhouettes. 2 | 3 | We are going to use openCV python library to convert an RGB color image to a cartoon image. 4 | 5 | Steps to develop Image Cartoonifier 6 | Download Image Cartoonifies Code 7 | Please download source code of Image Cartoonfier Project: Cartoonify an Image in Python 8 | 9 | Step 1: Importing the required modules 10 | We will import the following modules: 11 | 12 | CV2: Imported to use OpenCV for image processing 13 | easygui: Imported to open a file box. It allows us to select any file from our system. 14 | Numpy: Images are stored and processed as numbers. These are taken as arrays. We use NumPy to deal with arrays. 15 | Imageio: Used to read the file which is chosen by file box using a path. 16 | Matplotlib: This library is used for visualization and plotting. Thus, it is imported to form the plot of images. 17 | OS: For OS interaction. Here, to read the path and save images to that path. 18 | 19 | Step 2: Building a File Box to choose a particular file 20 | In this step, we will build the main window of our application, where the buttons, labels, and images will reside. We also give it a title by title() function. 21 | 22 | 23 | Code: 24 | 25 | """ fileopenbox opens the box to choose file 26 | and help us store file path as string """ 27 | def upload(): 28 | ImagePath=easygui.fileopenbox() 29 | cartoonify(ImagePath) 30 | 31 | 32 | Explanation: 33 | The above code opens the file box, i.e the pop-up box to choose the file from the device, which opens every time you run the code. fileopenbox() is the method in easyGUI module which returns the path of the chosen file as a string. 34 | 35 | Step 3: How is an image stored? 36 | Now, just think, how will a program read an image? For a computer, everything is just numbers. Thus, in the below code, we will convert our image into a numpy array. 37 | 38 | Beginning with image transformations: 39 | 40 | To convert an image to a cartoon, multiple transformations are done. Firstly, an image is converted to a Grayscale image. Yes, similar to the old day’s pictures.! Then, the Grayscale image is smoothened, and we try to extract the edges in the image. Finally, we form a color image and mask it with edges. This creates a beautiful cartoon image with edges and lightened color of the original image. 41 | 42 | Let’s start with these transformations to convert an image to its cartoon image. 43 | 44 | Step 4: Transforming an image to grayscale 45 | Code: 46 | 47 | #converting an image to grayscale 48 | grayScaleImage = cv2.cvtColor(originalmage, cv2.COLOR_BGR2GRAY) 49 | ReSized2 = cv2.resize(grayScaleImage, (960, 540)) 50 | #plt.imshow(ReSized2, cmap='gray') 51 | Explanation: 52 | 53 | cvtColor(image, flag) is a method in cv2 which is used to transform an image into the colour-space mentioned as ‘flag’. Here, our first step is to convert the image into grayscale. Thus, we use the BGR2GRAY flag. This returns the image in grayscale. A grayscale image is stored as grayScaleImage. 54 | 55 | After each transformation, we resize the resultant image using the resize() method in cv2 and display it using imshow() method. This is done to get more clear insights into every single transformation step. 56 | 57 | The above code will generate the following output: 58 | 59 |

60 | 61 |

62 | 63 | 64 | Step 5: Smoothening a grayscale image 65 | Code: 66 | 67 | #applying median blur to smoothen an image 68 | smoothGrayScale = cv2.medianBlur(grayScaleImage, 5) 69 | ReSized3 = cv2.resize(smoothGrayScale, (960, 540)) 70 | #plt.imshow(ReSized3, cmap='gray') 71 | Explanation: 72 | 73 | 74 | To smoothen an image, we simply apply a blur effect. This is done using medianBlur() function. Here, the center pixel is assigned a mean value of all the pixels which fall under the kernel. In turn, creating a blur effect. 75 | 76 | The above code generates the following output: 77 |

78 | 79 |

80 | 81 | Step 6: Retrieving the edges of an image 82 | Code: 83 | 84 | #retrieving the edges for cartoon effect 85 | #by using thresholding technique 86 | getEdge = cv2.adaptiveThreshold(smoothGrayScale, 255, 87 | cv2.ADAPTIVE_THRESH_MEAN_C, 88 | cv2.THRESH_BINARY, 9, 9) 89 | ReSized4 = cv2.resize(getEdge, (960, 540)) 90 | #plt.imshow(ReSized4, cmap='gray') 91 | Explanation: 92 | 93 | Cartoon effect has two specialties: 94 | 95 | Highlighted Edges 96 | Smooth colors 97 | In this step, we will work on the first specialty. Here, we will try to retrieve the edges and highlight them. This is attained by the adaptive thresholding technique. The threshold value is the mean of the neighborhood pixel values area minus the constant C. C is a constant that is subtracted from the mean or weighted sum of the neighborhood pixels. Thresh_binary is the type of threshold applied, and the remaining parameters determine the block size. 98 | 99 | The above code will generate output like below: 100 | 101 |

102 | 103 |

104 | 105 | 106 | Step 7: Preparing a Mask Image 107 | Code: 108 | 109 | #applying bilateral filter to remove noise 110 | #and keep edge sharp as required 111 | colorImage = cv2.bilateralFilter(originalmage, 9, 300, 300) 112 | ReSized5 = cv2.resize(colorImage, (960, 540)) 113 | #plt.imshow(ReSized5, cmap='gray') 114 | Explanation: 115 | 116 | In the above code, we finally work on the second specialty. We prepare a lightened color image that we mask with edges at the end to produce a cartoon image. We use bilateralFilter which removes the noise. It can be taken as smoothening of an image to an extent. 117 | 118 | The third parameter is the diameter of the pixel neighborhood, i.e, the number of pixels around a certain pixel which will determine its value. The fourth and Fifth parameter defines signmaColor and sigmaSpace. These parameters are used to give a sigma effect, i.e make an image look vicious and like water paint, removing the roughness in colors. 119 | 120 | Yes, it’s similar to BEAUTIFY or AI effect in cameras of modern mobile phones. 121 | 122 | The above code generates the following output: 123 | 124 | 125 |

126 | 127 |

128 | 129 | Step 8: Giving a Cartoon Effect 130 | Code: 131 | 132 | 133 | #masking edged image with our "BEAUTIFY" image 134 | cartoonImage = cv2.bitwise_and(colorImage, colorImage, mask=getEdge) 135 | ReSized6 = cv2.resize(cartoonImage, (960, 540)) 136 | #plt.imshow(ReSized6, cmap='gray') 137 | Explanation: 138 | 139 | So, let’s combine the two specialties. This will be done using MASKING. We perform bitwise and on two images to mask them. Remember, images are just numbers? 140 | 141 | Yes, so that’s how we mask edged image on our “BEAUTIFY” image. 142 | 143 | This finally CARTOONIFY our image! 144 | 145 | The above code will generate output like below: 146 | 147 | 148 |

149 | 150 |

151 | 152 | Step 9: Plotting all the transitions together 153 | Code: 154 | 155 | # Plotting the whole transition 156 | images=[ReSized1, ReSized2, ReSized3, ReSized4, ReSized5, ReSized6] 157 | fig, axes = plt.subplots(3,2, figsize=(8,8), subplot_kw={'xticks':[], 'yticks':[]}, gridspec_kw=dict(hspace=0.1, wspace=0.1)) 158 | for i, ax in enumerate(axes.flat): 159 | ax.imshow(images[i], cmap='gray') 160 | //save button code 161 | plt.show() 162 | Explanation: 163 | 164 | To plot all the images, we first make a list of all the images. The list here is named “images” and contains all the resized images. Now, we create axes like subl=plots in a plot and display one-one images in each block on the axis using imshow() method. 165 | 166 | plt.show() plots the whole plot at once after we plot on each subplot. 167 | 168 | The above code will generate output like below: 169 | 170 |

171 | 172 |

173 | 174 | 175 | Step 10: Functionally of save button 176 | def save(ReSized6, ImagePath): 177 | #saving an image using imwrite() 178 | newName="cartoonified_Image" 179 | path1 = os.path.dirname(ImagePath) 180 | extension=os.path.splitext(ImagePath)[1] 181 | path = os.path.join(path1, newName+extension) 182 | cv2.imwrite(path, cv2.cvtColor(ReSized6, cv2.COLOR_RGB2BGR)) 183 | I = "Image saved by name " + newName +" at "+ path 184 | tk.messagebox.showinfo(title=None, message=I) 185 | Explanation: 186 | 187 | Here, the idea is to save the resultant image. For this, we take the old path, and just change the tail (name of the old file) to a new name and store the cartoonified image with a new name in the same folder by appending the new name to the head part of the file. 188 | 189 | 190 | For this, we extract the head part of the file path by os.path.dirname() method. Similarly, os.path.splitext(ImagePath)[1] is used to extract the extension of the file from the path. 191 | 192 | Here, newName stores “Cartoonified_Image” as the name of a new file. os.path.join(path1, newName + extension) joins the head of path to the newname and extension. This forms the complete path for the new file. 193 | 194 | imwrite() method of cv2 is used to save the file at the path mentioned. cv2.cvtColor(ReSized6, cv2.COLOR_RGB2BGR) is used to assure that no color get extracted or highlighted while we save our image. Thus, at last, the user is given confirmation that the image is saved with the name and path of the file. 195 | 196 | 197 | Step 11: Making the main window 198 | top=tk.Tk() 199 | top.geometry('400x400') 200 | top.title('Cartoonify Your Image !') 201 | top.configure(background='white') 202 | label=Label(top,background='#CDCDCD', font=('calibri',20,'bold')) 203 | Step 12: Making the Cartoonify button in the main window 204 | upload=Button(top,text="Cartoonify an Image",command=upload,padx=10,pady=5) 205 | upload.configure(background='#364156', foreground='white',font=('calibri',10,'bold')) 206 | upload.pack(side=TOP,pady=50) 207 | box 208 | 209 | Step 13: Making a Save button in the main window 210 | save1=Button(top,text="Save cartoon image",command=lambda: save(ImagePath, ReSized6),padx=30,pady=5) 211 | save1.configure(background='#364156', foreground='white',font=('calibri',10,'bold')) 212 | save1.pack(side=TOP,pady=50) 213 | The above code makes a button as soon as the image transformation is done. It gives an option to the user to save cartoonified image. 214 | 215 | save 216 | 217 | Step 14: Main function to build the tkinter window 218 | top.mainloop() 219 | The Final Result: 220 |

221 | 222 |

223 | 224 | 225 | Summary 226 | Yes, now you have a reason to tease your sibling by saying “You look like a cartoon”. Just cartoonify his/ her image, and show it! 227 | 228 | We have successfully developed Image Cartoonifier with OpenCV in Python. This is the magic of openCV which let us do miracles. We suggest you make a photo editor of your own and try different effects. 229 | -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonized-Image/images/cry_baby.jfif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonized-Image/images/cry_baby.jfif -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonized-Image/images/smile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonized-Image/images/smile.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonized-Image/images/virat.jfif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Cartoonized-Image/images/virat.jfif -------------------------------------------------------------------------------- /Cartoonify-Image/Cartoonized-Image/readme.md: -------------------------------------------------------------------------------- 1 | This application uses openCV to create cartoonish filter for any image with the help of Gaussian Filter 2 | 3 | Gaussian Filter- Uses a blurring function, adaptive thresholding and dilation to expose the main features of an image. -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/Assets/cartoon.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Differentiate between Human and Cartoon Faces/Assets/cartoon.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/Assets/image.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Differentiate between Human and Cartoon Faces/Assets/image.webp -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/blurred_hsv.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/blurred_hsv.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/image.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/image.webp -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/img_hsv.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/img_hsv.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/new.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Differentiate between Human and Cartoon Faces/Media/new.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/README.md: -------------------------------------------------------------------------------- 1 | # Differentiate between Cartoon and Human Faces 2 | 3 | One way to discriminate between cartoon and natural scene images is to compare a given image to its "smoothed" self. The motivation behind this is that a "smoothed" cartoon image statistically will not change much, where as a natural scene image will. In other words, take an image, cartoonify (i.e. smooth) it and subtract the result from the original. 4 | 5 | This difference (i.e. taking its mean value) will give the level of change caused by the smoothing. The index should be high for non-smooth original (natural scene) images and low for smooth original (cartoony) images. 6 | 7 | Smoothing/Cartoonifying is done with bilateral filtering. 8 | 9 |

10 | 11 | accessibility text 12 |

13 | 14 | 15 | As for subtracting the cartoonyfied image from the original, it is done with the Hue channel of the HSV images. This means, first the images are converted from BGR to HSV and then subtracted. 16 | 17 |

18 | 19 | accessibility text 20 |

21 | 22 | ## Dependencies 23 | 24 | - OpenCV - This is used to perform different operations like blurring on the given image. 25 | - Numpy - This is used for calculating the mean of subtraction. 26 | 27 | ## Setup 28 | 29 | - Fork the repository - Creates a copy of this project in your github. 30 | 31 | - Clone the repository to your local machine using 32 | ``` 33 | git clone https://github.com/akshitagupta15june/Face-X.git 34 | ``` 35 | - Use a virtual environment to keep the all dependencies in a separate enviroment for example - conda, virtualenv, pipenv, etc. 36 | 37 | - Navigate to the Differentiate between Human and Cartoon Faces inside Cartoonify Image Folder using 38 | ``` 39 | cd Cartoonify-Image/Differentiate\ between\ Human\ and\ Cartoon\ Faces 40 | ``` 41 | 42 | - Install the dependencies either by using the below pip commands or by using the requirements.txt file given. 43 | 44 | - By using pip commands 45 | ``` 46 | pip install numpy 47 | ``` 48 | ``` 49 | pip install opencv-python 50 | ``` 51 | 52 | - By using requirements.txt 53 | ``` 54 | pip install -r requirements.txt 55 | ``` 56 | 57 | - Run the cartoon.py script using 58 | ``` 59 | python3 cartoon.py 60 | ``` 61 | 62 | ## Want to Contribute? 63 | 64 | - Follow the steps for Setup 65 | 66 | - Make a new branch 67 | ``` 68 | git branch < YOUR_USERNAME > 69 | ``` 70 | 71 | - Switch to Development Branch 72 | ``` 73 | git checkout < YOURUSERNAME > 74 | ``` 75 | 76 | - Make a folder and add your code file and a readme file with screenshots. 77 | 78 | - Add your files or changes to staging area 79 | ``` 80 | git add. 81 | ``` 82 | 83 | - Commit Message 84 | ``` 85 | git commit -m "Enter message" 86 | ``` 87 | 88 | - Push your code 89 | ``` 90 | git push 91 | ``` 92 | 93 | - Make Pull request with the Master branch of akshitagupta15june/Face-X repo. 94 | 95 | - Wait for reviewers to review your PR 96 | -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/cartoon.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | 4 | 5 | def check(image_path): 6 | # Reading the image 7 | img = cv2.imread(image_path) 8 | 9 | # Parameters for Bilateral Filter 10 | 11 | # Diameter of the pixel neighborhood — the larger this diameter is, 12 | # the more pixels will be included in the blurring computation. 13 | diameter = 11 14 | 15 | # SigmaColor is the number of colors in the neighborhood 16 | # that will be considered when computing the blur. 17 | sigmaColor = 61 18 | 19 | # The value of SigmaSpace indicates pixels farther out 20 | # from the central pixel diameter will influence the blurring calculation. 21 | sigmaSpace = 39 22 | 23 | # Applying Bilateral Filter 24 | blurred = cv2.bilateralFilter(img, diameter, sigmaColor, sigmaSpace) 25 | 26 | # Converting original image to HSV 27 | img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 28 | 29 | # Converting blurred image to hsv 30 | blurred_hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV) 31 | 32 | # Subtracting blurred from original and storing value 33 | isNotACartoonIndex = np.mean( img_hsv - blurred_hsv ) 34 | 35 | if isNotACartoonIndex >= 55: 36 | print("Human Face") 37 | else: 38 | print("Cartoon Face") 39 | 40 | 41 | check("/Assets/cartoon.jpeg") 42 | check("/Assets/image.webp") -------------------------------------------------------------------------------- /Cartoonify-Image/Differentiate between Human and Cartoon Faces/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.21.0 2 | opencv-python==4.5.5.62 -------------------------------------------------------------------------------- /Cartoonify-Image/Glitter Cartoon Filter/Glitter Cartoon Filter.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import os.path 4 | 5 | 6 | img_path = input("Enter the path here:") #example -> C:\Users\xyz\OneDrive\Desktop\project\image.jpg 7 | 8 | img = cv2.imread(img_path) 9 | 10 | from matplotlib import pyplot as plt 11 | #plt.imshow(img) 12 | #plt.show() 13 | 14 | image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 15 | 16 | plt.figure(figsize= (10,10)) 17 | #plt.imshow(image) 18 | #plt.show() 19 | 20 | img_small = cv2.pyrDown(image) 21 | num_iter = 5 22 | for _ in range(num_iter): 23 | img_small= cv2.bilateralFilter(img_small, d=9, sigmaColor=9, sigmaSpace=7) 24 | 25 | img_rgb = cv2.pyrUp(img_small) 26 | 27 | #plt.imshow(img_rgb) 28 | #plt.show() 29 | 30 | img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY) 31 | img_blur = cv2.medianBlur(img_gray, 7) 32 | img_edge = cv2.adaptiveThreshold(img_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 7, 2) 33 | 34 | #plt.imshow(img_edge) 35 | #plt.show() 36 | 37 | img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB) 38 | #plt.imshow(img_edge) 39 | #plt.show() 40 | 41 | 42 | 43 | array = cv2.bitwise_or(image, img_rgb) 44 | final_img = cv2.bitwise_and(array, img_edge) 45 | 46 | 47 | # set up side-by-side image display 48 | fig = plt.figure() 49 | fig.set_figheight(15) 50 | fig.set_figwidth(15) 51 | 52 | # display the real image 53 | fig.add_subplot(1,2,1) 54 | plt.imshow(image, cmap='gray') 55 | plt.title("Original Image") 56 | 57 | # display the new image 58 | fig.add_subplot(1,2,2) 59 | plt.imshow(final_img, cmap='gray') 60 | plt.title("Glitter Cartoon Filtered Image") 61 | 62 | 63 | plt.show() 64 | -------------------------------------------------------------------------------- /Cartoonify-Image/Glitter Cartoon Filter/Images/Final_Output.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Glitter Cartoon Filter/Images/Final_Output.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Glitter Cartoon Filter/Images/Original_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/Glitter Cartoon Filter/Images/Original_image.jpg -------------------------------------------------------------------------------- /Cartoonify-Image/Glitter Cartoon Filter/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Applying "Glitter Cartoon Filter" on an image. 3 | 4 | Converting an image into a glitter cartoon filtered image using OpenCv, Os, Matplotlib and Numpy. 5 | 6 | ## Steps: 7 | * Firstly imported the required libraries which are Numpy, Os, Matplotlib and Cv2. 8 | * Taking path of the image/Real image as input using os and finally reading it using cv2 9 | 10 | ## Methods Used 11 | * Used Bilateral Filter 12 | * Followed by Median Blur 13 | * Followed by Adaptive Threshold 14 | * Followed by Bitwise "or" between original image and image_rgb 15 | * And at last used Bitwise "and" between image_edge and output of the above "bitwise or image" 16 | * Finally converted the image into "Glitter Cartoon Filtered" image 17 | 18 | 19 | 20 | 21 | ## Comparision between the "Original" and "Glitter Cartoon Filtered" Image 22 | 23 | 24 | -------------------------------------------------------------------------------- /Cartoonify-Image/Images/readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Cartoonify-Image/facex.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/facex.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/logo/Face-X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/logo/Face-X.png -------------------------------------------------------------------------------- /Cartoonify-Image/logo/FaceX.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /Cartoonify-Image/logo/cartoonified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/logo/cartoonified.png -------------------------------------------------------------------------------- /Cartoonify-Image/logo/original.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Cartoonify-Image/logo/original.jpeg -------------------------------------------------------------------------------- /Cartoonify-Image/readme.md: -------------------------------------------------------------------------------- 1 | # Cartoonify Image 2 | Currently many of us wants to have our photo to be cartoonify, and we try to use the professional cartoonizer application available in market and most of them are not freeware. In order to have basic cartoonifying effects, we just need the bilateral filter, some edge detection mechanism and some filters. 3 | 4 | The bilateral filter is use to reduce the color palettle, which is the most important task for cartoonifying the image and have a look like cartoon.And then comes the edge detection to produce the bold silhouettes. 5 | 6 |

7 | 8 | accessibility text 9 |

10 | 11 | ## Dependencies: 12 | 13 | The Dependencies used are: 14 | 15 | - Opencv :It provides the tool for applying computer vison techniques on the image. 16 | - Numpy :Images are stored and processed as numbers, These are taken as arrays. 17 | 18 | ## How to create a Cortoonify Image? 19 | - Cartoonify Images can be created using the opencv library. 20 | - OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library. It is mainly aimed at real-time computer vision and image processing. It is used to perform different operations on images which transform them using different techniques. Majorly supports all lannguages like Python, C++,Android, Java, etc. 21 | - In Opencv there are various functions like bilateral filters, median blur, adaptive thresholding which help in cartoonify the image. 22 | 23 | ## Algorithm 24 | - Firstly importing the cv2 and numpy library. 25 | - Now applying the bilateral filter to reduce the color palette of the image. 26 | - Covert the actual image to grayscale. 27 | - Apply the median blur to reduce the image noise in the grayscale image. 28 | - reate an edge mask from the grayscale image using adaptive thresholding. 29 | - Finally combine the color image produced from step 1 with edge mask produced from step 4. 30 | 31 | 32 | ## Want to contribute in Cartoonify Images? 33 | You can refer to CONTRIBUTING.md (`https://github.com/akshitagupta15june/Face-X/blob/master/CONTRIBUTING.md`) 34 | #### Or follow the below steps - 35 | - Fork this repository `https://github.com/akshitagupta15june/Face-X`. 36 | - Clone the forked repository 37 | ``` 38 | git clone https://github.com// 39 | ``` 40 | - Create a Virtual Environment(that can fulfill the required dependencies) 41 | ``` 42 | - python -m venv env 43 | - source env/bin/activate (Linux) 44 | - env\Scripts\activate (Windows) 45 | ``` 46 | - Install dependencies 47 | - Go to project directory 48 | ``` 49 | cd Cartoonify Image 50 | ``` 51 | - Make a new branch 52 | ``` 53 | git branch < YOUR_USERNAME > 54 | ``` 55 | - Switch to Development Branch 56 | ``` 57 | git checkout < YOURUSERNAME > 58 | ``` 59 | - Make a folder and add your code file and a readme file with screenshots. 60 | - Add your files or changes to staging area 61 | ``` 62 | git add . 63 | ``` 64 | - Commit message 65 | ``` 66 | git commit -m "Enter message" 67 | ``` 68 | - Push your code 69 | ``` 70 | git push 71 | ``` 72 | - Make Pull request with the Master branch of `akshitagupta15june/Face-X` repo. 73 | - Wait for reviewers to review your PR -------------------------------------------------------------------------------- /Chronic-Kidney-Disease-main.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Chronic-Kidney-Disease-main.zip -------------------------------------------------------------------------------- /Color-Detection-Project: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import pandas as pd 4 | import argparse 5 | 6 | #Creating argument parser to take image path from command line 7 | ap = argparse.ArgumentParser() 8 | ap.add_argument('-i', '--image', required=True, help="Image Path") 9 | args = vars(ap.parse_args()) 10 | img_path = args['image'] 11 | 12 | #Reading the image with opencv 13 | img = cv2.imread(img_path) 14 | 15 | #declaring global variables (are used later on) 16 | clicked = False 17 | r = g = b = xpos = ypos = 0 18 | 19 | #Reading csv file with pandas and giving names to each column 20 | index=["color","color_name","hex","R","G","B"] 21 | csv = pd.read_csv('colors.csv', names=index, header=None) 22 | 23 | #function to calculate minimum distance from all colors and get the most matching color 24 | def getColorName(R,G,B): 25 | minimum = 10000 26 | for i in range(len(csv)): 27 | d = abs(R- int(csv.loc[i,"R"])) + abs(G- int(csv.loc[i,"G"]))+ abs(B- int(csv.loc[i,"B"])) 28 | if(d<=minimum): 29 | minimum = d 30 | cname = csv.loc[i,"color_name"] 31 | return cname 32 | 33 | #function to get x,y coordinates of mouse double click 34 | def draw_function(event, x,y,flags,param): 35 | if event == cv2.EVENT_LBUTTONDBLCLK: 36 | global b,g,r,xpos,ypos, clicked 37 | clicked = True 38 | xpos = x 39 | ypos = y 40 | b,g,r = img[y,x] 41 | b = int(b) 42 | g = int(g) 43 | r = int(r) 44 | 45 | cv2.namedWindow('image') 46 | cv2.setMouseCallback('image',draw_function) 47 | 48 | while(1): 49 | 50 | cv2.imshow("image",img) 51 | if (clicked): 52 | 53 | #cv2.rectangle(image, startpoint, endpoint, color, thickness)-1 fills entire rectangle 54 | cv2.rectangle(img,(20,20), (750,60), (b,g,r), -1) 55 | 56 | #Creating text string to display( Color name and RGB values ) 57 | text = getColorName(r,g,b) + ' R='+ str(r) + ' G='+ str(g) + ' B='+ str(b) 58 | 59 | #cv2.putText(img,text,start,font(0-7),fontScale,color,thickness,lineType ) 60 | cv2.putText(img, text,(50,50),2,0.8,(255,255,255),2,cv2.LINE_AA) 61 | 62 | #For very light colours we will display text in black colour 63 | if(r+g+b>=600): 64 | cv2.putText(img, text,(50,50),2,0.8,(0,0,0),2,cv2.LINE_AA) 65 | 66 | clicked=False 67 | 68 | #Break the loop when user hits 'esc' key 69 | if cv2.waitKey(20) & 0xFF ==27: 70 | break 71 | 72 | cv2.destroyAllWindows() 73 | -------------------------------------------------------------------------------- /Covid: -------------------------------------------------------------------------------- 1 | /* 2 | Covid 19 Data Exploration 3 | */ 4 | 5 | Select * 6 | From PortfolioProject..CovidDeaths 7 | Where continent is not null 8 | order by 3,4 9 | 10 | 11 | -- Select Data that we are going to be starting with 12 | 13 | Select Location, date, total_cases, new_cases, total_deaths, population 14 | From PortfolioProject..CovidDeaths 15 | Where continent is not null 16 | order by 1,2 17 | 18 | 19 | -- Total Cases vs Total Deaths 20 | -- Shows likelihood of dying if you contract covid in your country 21 | 22 | Select Location, date, total_cases,total_deaths, (total_deaths/total_cases)*100 as DeathPercentage 23 | From PortfolioProject..CovidDeaths 24 | Where location like '%states%' 25 | and continent is not null 26 | order by 1,2 27 | 28 | 29 | -- Total Cases vs Population 30 | -- Shows what percentage of population infected with Covid 31 | 32 | Select Location, date, Population, total_cases, (total_cases/population)*100 as PercentPopulationInfected 33 | From PortfolioProject..CovidDeaths 34 | --Where location like '%states%' 35 | order by 1,2 36 | 37 | 38 | -- Countries with Highest Infection Rate compared to Population 39 | 40 | Select Location, Population, MAX(total_cases) as HighestInfectionCount, Max((total_cases/population))*100 as PercentPopulationInfected 41 | From PortfolioProject..CovidDeaths 42 | --Where location like '%states%' 43 | Group by Location, Population 44 | order by PercentPopulationInfected desc 45 | 46 | 47 | -- Countries with Highest Death Count per Population 48 | 49 | Select Location, MAX(cast(Total_deaths as int)) as TotalDeathCount 50 | From PortfolioProject..CovidDeaths 51 | --Where location like '%states%' 52 | Where continent is not null 53 | Group by Location 54 | order by TotalDeathCount desc 55 | 56 | 57 | 58 | -- BREAKING THINGS DOWN BY CONTINENT 59 | 60 | -- Showing contintents with the highest death count per population 61 | 62 | Select continent, MAX(cast(Total_deaths as int)) as TotalDeathCount 63 | From PortfolioProject..CovidDeaths 64 | --Where location like '%states%' 65 | Where continent is not null 66 | Group by continent 67 | order by TotalDeathCount desc 68 | 69 | 70 | 71 | -- GLOBAL NUMBERS 72 | 73 | Select SUM(new_cases) as total_cases, SUM(cast(new_deaths as int)) as total_deaths, SUM(cast(new_deaths as int))/SUM(New_Cases)*100 as DeathPercentage 74 | From PortfolioProject..CovidDeaths 75 | --Where location like '%states%' 76 | where continent is not null 77 | --Group By date 78 | order by 1,2 79 | 80 | 81 | 82 | -- Total Population vs Vaccinations 83 | -- Shows Percentage of Population that has recieved at least one Covid Vaccine 84 | 85 | Select dea.continent, dea.location, dea.date, dea.population, vac.new_vaccinations 86 | , SUM(CONVERT(int,vac.new_vaccinations)) OVER (Partition by dea.Location Order by dea.location, dea.Date) as RollingPeopleVaccinated 87 | --, (RollingPeopleVaccinated/population)*100 88 | From PortfolioProject..CovidDeaths dea 89 | Join PortfolioProject..CovidVaccinations vac 90 | On dea.location = vac.location 91 | and dea.date = vac.date 92 | where dea.continent is not null 93 | order by 2,3 94 | 95 | 96 | -- Using CTE to perform Calculation on Partition By in previous query 97 | 98 | With PopvsVac (Continent, Location, Date, Population, New_Vaccinations, RollingPeopleVaccinated) 99 | as 100 | ( 101 | Select dea.continent, dea.location, dea.date, dea.population, vac.new_vaccinations 102 | , SUM(CONVERT(int,vac.new_vaccinations)) OVER (Partition by dea.Location Order by dea.location, dea.Date) as RollingPeopleVaccinated 103 | --, (RollingPeopleVaccinated/population)*100 104 | From PortfolioProject..CovidDeaths dea 105 | Join PortfolioProject..CovidVaccinations vac 106 | On dea.location = vac.location 107 | and dea.date = vac.date 108 | where dea.continent is not null 109 | --order by 2,3 110 | ) 111 | Select *, (RollingPeopleVaccinated/Population)*100 112 | From PopvsVac 113 | 114 | 115 | 116 | -- Using Temp Table to perform Calculation on Partition By in previous query 117 | 118 | DROP Table if exists #PercentPopulationVaccinated 119 | Create Table #PercentPopulationVaccinated 120 | ( 121 | Continent nvarchar(255), 122 | Location nvarchar(255), 123 | Date datetime, 124 | Population numeric, 125 | New_vaccinations numeric, 126 | RollingPeopleVaccinated numeric 127 | ) 128 | 129 | Insert into #PercentPopulationVaccinated 130 | Select dea.continent, dea.location, dea.date, dea.population, vac.new_vaccinations 131 | , SUM(CONVERT(int,vac.new_vaccinations)) OVER (Partition by dea.Location Order by dea.location, dea.Date) as RollingPeopleVaccinated 132 | --, (RollingPeopleVaccinated/population)*100 133 | From PortfolioProject..CovidDeaths dea 134 | Join PortfolioProject..CovidVaccinations vac 135 | On dea.location = vac.location 136 | and dea.date = vac.date 137 | --where dea.continent is not null 138 | --order by 2,3 139 | 140 | Select *, (RollingPeopleVaccinated/Population)*100 141 | From #PercentPopulationVaccinated 142 | 143 | 144 | 145 | 146 | -- Creating View to store data for later visualizations 147 | 148 | Create View PercentPopulationVaccinated as 149 | Select dea.continent, dea.location, dea.date, dea.population, vac.new_vaccinations 150 | , SUM(CONVERT(int,vac.new_vaccinations)) OVER (Partition by dea.Location Order by dea.location, dea.Date) as RollingPeopleVaccinated 151 | --, (RollingPeopleVaccinated/population)*100 152 | From PortfolioProject..CovidDeaths dea 153 | Join PortfolioProject..CovidVaccinations vac 154 | On dea.location = vac.location 155 | and dea.date = vac.date 156 | where dea.continent is not null 157 | 158 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data-Science-Projects 2 | Add your data analysis/Artifical Intelligence/Machine Learning projects in this repo for the welfare of data science community 3 | 4 | 5 | ![ Data Science](https://images.unsplash.com/photo-1488229297570-58520851e868?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=869&q=80) 6 | 7 | ## Rules to contribute to this Repo 8 | 9 | - Use any programming language 10 | - Use any data science tools and techniques and create data projects. 11 | - Projects should be different from the uploaded ones or it should be optimized version of existing ones 12 | 13 | 14 | ## Steps for Contributing 15 | 16 | ## Getting started 17 | 18 | - Fork this repository (Click the Fork button in the top right of this page, click your Profile Image) 19 | - Clone your fork down to your local machine 20 | 21 | ```markdown 22 | git clone https://github.com/SARTHAK2511/Data-Analysis-Projects-for-Hacktoberfest.git 23 | ``` 24 | 25 | - Create a branch 26 | 27 | ```markdown 28 | git checkout -b branch-name 29 | ``` 30 | 31 | - Make your changes (choose from any task below) 32 | - Commit and push 33 | 34 | ```markdown 35 | git add . 36 | git commit -m 'Commit message' 37 | git push origin branch-name 38 | ``` 39 | 40 | - Create a new pull request from your forked repository (Click the `New Pull Request` button located at the top of your repo) 41 | - Wait for your PR review and merge approval! 42 | - **Star this repository** if you had fun! 43 | -------------------------------------------------------------------------------- /Sentiment Analysis/SenAnal.py: -------------------------------------------------------------------------------- 1 | from init import * 2 | import streamlit as st 3 | 4 | def SentimentAnalysis(sq): 5 | tweets = tp.Cursor(api.search_tweets, 6 | q = sq+'-filter:retweets', 7 | lang = "en", 8 | tweet_mode = "extended").items(500) 9 | data = [] 10 | for tweet in tweets: 11 | try: 12 | content = tweet.full_text 13 | sentiment = sentiment_analysis(content) 14 | data.append([content, sentiment[0]['label']]) 15 | except: 16 | pass 17 | columns = ['Tweet', 'Sentiment'] 18 | df = pd.DataFrame(data, columns=columns) 19 | f = df.to_csv().encode('utf-8') 20 | return f -------------------------------------------------------------------------------- /Sentiment Analysis/app.py: -------------------------------------------------------------------------------- 1 | import SenAnal 2 | import streamlit as st 3 | 4 | st.image('twitter.png', width=80) 5 | st.title("Twitter Sentiment Analysis") 6 | search_query = st.text_input('Twitter Keywords') 7 | if len(search_query) != 0: 8 | st.download_button(label='Download', data=SenAnal.SentimentAnalysis(search_query), file_name='data.csv') -------------------------------------------------------------------------------- /Sentiment Analysis/init - Copy.py: -------------------------------------------------------------------------------- 1 | import os 2 | from transformers import pipeline 3 | import tweepy as tp 4 | import configparser as cp 5 | import numpy as np 6 | import csv 7 | import pandas as pd 8 | import streamlit as st 9 | 10 | config = cp.ConfigParser() 11 | config.read('config.ini') 12 | 13 | api_key = "" 14 | api_secret = "" 15 | 16 | access_token = "" 17 | access_token_secret = "" 18 | 19 | auth = tp.OAuthHandler(api_key, api_secret) 20 | auth.set_access_token(access_token, access_token_secret) 21 | 22 | api = tp.API(auth) 23 | 24 | sentiment_analysis = pipeline(model="finiteautomata/bertweet-base-sentiment-analysis") -------------------------------------------------------------------------------- /Streamlit-Stock-Prediction-main.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/Streamlit-Stock-Prediction-main.zip -------------------------------------------------------------------------------- /bark-texture-classification-with-resnet50.ipynb: -------------------------------------------------------------------------------- 1 | {"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Changes\n### Most changes between versions are small. All experiments should have only one small change each, so it would be easy to understand how changes affect the result. \n\n**v1**: Made a functional CNN with 94% accuracy.\n\n**v2**: Resizing to 256 px before cropping. This way we can retain more of the image after the crop, and this helps us too as most of the images are actually focused and centered on the trees. Accuracy boosted to 96%.\n\n**v3**: 30 epochs has been overfitting the model over the validation data. Reduced to 15 epochs. Retains the original 96-97% accuracy as compared to 30 epochs\n\n**v4**: Added L2 regularization while training and used updated model weights for ResNet50 using new API\n\n**v5**: Increased number of epochs to 45 due to new lr decay\n\n**v6**: Moved from ResNet50 to ResNet34, with 1% performance change in testing, but considerable reduction in model execution (training, testing) time. \n\n**v7**: Added AutoAugment and moved back to Resnet50. Creates marginal performance improvement.\n\n**Accuracies**:\n\n - *ResNet50* - 97%\n\n - *ResNet34* - 96%\n \n We can choose ResNet50 for accuracy ResNet34 for speed","metadata":{}},{"cell_type":"markdown","source":"### Transfer Learning\n\nHere I decided to use a transfer learning model, as using a base model did not quite meet my personal expectations on the accuracy of the model.\n\nTransfer Learning allows us to apply features already learned from other datasets to our dataset, leading to lower training times and higher accuracies. Here we use models trained on the IMAGENET dataset, which work very well for most CNN image classification tasks.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nfrom glob import glob\nimport os\nimport torch\nimport torchvision.models as models\nimport torchvision.transforms as transforms\nfrom torchvision import datasets\nfrom PIL import ImageFile\nfrom torch.utils.data.sampler import SubsetRandomSampler\nimport matplotlib.pyplot as plt\nimport torch.optim as optim\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Creating our transforms**:\n- Cropping to 224 x 224 px for transfer learning model input param. This reduction of the size of the images also helps decrease processing time\n- We augumented the dataset to add more training variations by horizontal flipping and slight rotation. \n- **v2**: Resizing to 256 px before cropping. This way we can retain more of the image after the crop, and this helps us too as most of the images are actually focused and centered on the trees. Accuracy boosted to 96%.\n- **v7**: Added AutoAugment, a data augmentation strategy based on the paper [AutoAugment: Learning Augmentation Strategies from Data](https://arxiv.org/pdf/1805.09501.pdf)","metadata":{}},{"cell_type":"code","source":"import torchvision.transforms as transforms\n\n# Declare the transforms for train, valid and test sets.\n# Convert to Tensor\n# Normalize images because the values of images should be loaded between [0 - 1]\ntransforms = {\n \n # RandomHorizontalFlip() & RandomRotation() to augement data in train transformation\n 'train' : transforms.Compose([transforms.Resize(256),\n transforms.AutoAugment(transforms.AutoAugmentPolicy.IMAGENET),\n transforms.RandomHorizontalFlip(),\n transforms.RandomRotation(30),\n transforms.CenterCrop(224),\n transforms.ToTensor(),\n transforms.Normalize(mean=[0.485, 0.456, 0.406],\n std=[0.229, 0.224, 0.225])]),\n \n 'valid' : transforms.Compose([transforms.Resize(256),\n transforms.CenterCrop(224),\n transforms.ToTensor(),\n transforms.Normalize(mean=[0.485, 0.456, 0.406],\n std=[0.229, 0.224, 0.225])]),\n \n 'test' : transforms.Compose([transforms.Resize(256),\n transforms.CenterCrop(224),\n transforms.ToTensor(),\n transforms.Normalize(mean=[0.485, 0.456, 0.406],\n std=[0.229, 0.224, 0.225])])\n}\n\n# number of subprocesses to use for data loading\nnum_workers = 2\n# how many samples per batch to load\nbatch_size = 20\n# where our data is stored\ndata_dir = \"./BarkVN-50_mendeley\"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Data Exploration\n\nWe plot our data distribution and observe that our data has 50 classes/directories with roughly 100 images in each directory.","metadata":{}},{"cell_type":"code","source":"x_plt = []\ny_plt = []\nfor directory in os.listdir(data_dir):\n x_plt.append(directory)\n y_plt.append(len(os.listdir(os.path.join(data_dir, directory))))\n\n# creating the bar plot\nfig, ax = plt.subplots(figsize =(16, 16))\nplt.barh(x_plt, y_plt, color ='maroon')\n# Remove x, y Ticks\nax.xaxis.set_ticks_position('none')\nax.yaxis.set_ticks_position('none')\n \n# Add padding between axes and labels\nax.xaxis.set_tick_params(pad = 5)\nax.yaxis.set_tick_params(pad = 10)\n \n# Show top values\nax.invert_yaxis()\n\n\nplt.ylabel(\"Bark Type\")\nplt.xlabel(\"No. of images\")\nplt.title(\"Bark Texture Dataset\")\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Based on this, we allocated 10% testing, 9% to validation and 81% to training.\n\nWe need to be careful of overfitting since this is a small dataset and hence during training, we will save the model only when the validation accuracy goes down. ","metadata":{}},{"cell_type":"code","source":"# how much % we want to allocate for testing\ntest_size=0.1\n# how much % of the remaining train data we want to allocate for validation\nvalid_size=0.1\n\n# load the dataset\ntrain_dataset = datasets.ImageFolder(\n root=data_dir, transform=transforms[\"train\"],\n)\n\nvalid_dataset = datasets.ImageFolder(\n root=data_dir, transform=transforms[\"valid\"],\n)\n\ntest_dataset = datasets.ImageFolder(\n root=data_dir, transform=transforms[\"test\"],\n)\n\nnum_train = len(train_dataset)\nindices = list(range(num_train))\n\n# Splitting test into test and train\nsplit = int(np.floor(test_size * num_train))\n\nnp.random.shuffle(indices)\n\ntrain_idx, test_idx = indices[split:], indices[:split]\ntrain_sampler = SubsetRandomSampler(train_idx)\ntest_sampler = SubsetRandomSampler(test_idx)\n\n# Splitting remaining test into test and validation\nsplit = int(np.floor(valid_size * num_train))\n\nnp.random.shuffle(indices)\n\ntrain_idx, valid_idx = indices[split:], indices[:split]\ntrain_sampler = SubsetRandomSampler(train_idx)\nvalid_sampler = SubsetRandomSampler(valid_idx)\n\n# Creating dataloaders\ntrain_loader = torch.utils.data.DataLoader(\n train_dataset, batch_size=batch_size, sampler=train_sampler,num_workers=num_workers\n)\nvalid_loader = torch.utils.data.DataLoader(\n valid_dataset, batch_size=batch_size, sampler=valid_sampler, num_workers=num_workers\n)\ntest_loader = torch.utils.data.DataLoader(\n test_dataset, batch_size=batch_size, sampler=test_sampler, num_workers=num_workers\n)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Here we can group the dataloaders into a single object to pass it into our train/test functions as a single object","metadata":{}},{"cell_type":"code","source":"dataloaders = {\n \"train\": train_loader,\n \"valid\": valid_loader,\n \"test\": test_loader\n}","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the all labels\nclass_names = train_dataset.classes\nprint(class_names)\nlen(class_names)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Testing to see if the dataloaders work correctly","metadata":{}},{"cell_type":"code","source":"from torchvision import utils\n\ndef visualize_sample_images(inp):\n inp = inp.numpy().transpose((1, 2, 0))\n inp = inp * np.array((0.229, 0.224, 0.225)) + np.array((0.485, 0.456, 0.406))\n inp = np.clip(inp, 0, 1)\n \n fig = plt.figure(figsize=(60, 25))\n plt.axis('off')\n plt.imshow(inp)\n plt.pause(0.001)\n \n# Get a batch of training data. \ninputs, classes = next(iter(train_loader))\n\n# Convert the batch to a grid.\ngrid = utils.make_grid(inputs, nrow=5)\n\n# Display!\nvisualize_sample_images(grid)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Model Architecture\n\nThe ResNet model had been chosen as in all first tests, resnet performed better compared to candidates like efficientnet, alexnet and a custom neural network\n\nSmaller datasets tend to do well with less complex networks and it shows here. Resnet50 works better than ResNet101 or ResNet152\n\n**v4**: Used updated model weights for ResNet50 using new API\n\n**v6**: Moved from ResNet50 to ResNet34, with 1% performance change in testing, but considerable reduction in model execution (training, testing) time. ","metadata":{}},{"cell_type":"code","source":"import torchvision.models as models\nfrom torchvision.models import resnet34, ResNet34_Weights\nfrom torchvision.models import resnet50, ResNet50_Weights\nimport torch.nn as nn\n\n## TODO: Specify model architecture \n#model_transfer = models.resnet34(weights=ResNet34_Weights.DEFAULT)\nmodel_transfer = models.resnet50(weights=ResNet50_Weights.DEFAULT)\n\n# Freeze parameters so we don't backprop through them\nfor param in model_transfer.parameters():\n param.requires_grad = False\n\n# Replace the last fully connected layer with a Linnear layer with 50 out features\nmodel_transfer.fc = nn.Linear(2048, len(class_names)) # Resnet 50+\n#model_transfer.fc = nn.Linear(512, len(class_names)) # Resnet18,34\n\nuse_cuda = torch.cuda.is_available()\n\nif use_cuda:\n model_transfer = model_transfer.cuda()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Model Training Optimization Algorithms\n\nThe optimizers are responsible for the feedforwand and backpropagation mechanisms. In more appropriate words, they will hold the current state and will update the parameters based on the computed gradients.\n\n**v4**: Added L2 regularization while training.\n\nThe Adam optimizer in pytorch does not implement true weight decay but rather uses L2 Regularization. It is mysteriously added in the Optimization functions because loss functions are used during Optimization. More has been discussed in this paper: [Fixing Weight Decay Regularization in Adam](https://openreview.net/pdf?id=rk6qdGgCZ)","metadata":{}},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model_transfer.fc.parameters(), lr=0.001, weight_decay=5e-5)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Training our model\n\nAfter obtaining the data, creating the model architecture, definiting optimization algorithm we can finally begin our training. Here we only save the model every time the validation loss goes down in order to make sure we don't have an overfitted model. If the validation loss stops decreasing for a few epochs, we can know that we have started overfitting and can accordingly lower the training epochs. Conversely, if it keeps decreasing, we can increase the training epochs. \n\nAn important thing to keep in mind is to make sure during training, our model is in training mode by using `model.train()` and during evaluation, it is in evaluation mode by using `model.eval()`. This ensures that during a feedforward operation, the gradients/weights are not updated, if we are currently just evaluating the model on our validation data. And conversely, the gradients/weights *are* updated if we wish to train our parameters.\n\nHere I perform the training on my RTX 2060 Mobile GPU.\n\n**v3**: 30 epochs has been overfitting the model over the validation data. Reduced to 15 epochs. Retains the original 96-97% accuracy as compared to 30 epochs\n\n**v5**: Increased number of epochs to 45 due to new lr decay (L2 regularization)","metadata":{}},{"cell_type":"code","source":"def train(n_epochs, loaders, model, optimizer, criterion, use_cuda, save_path):\n \"\"\"returns trained model\"\"\"\n # initialize tracker for minimum validation loss\n valid_loss_min = np.Inf \n \n for epoch in range(1, n_epochs+1):\n # initialize variables to monitor training and validation loss\n train_loss = 0.0\n valid_loss = 0.0\n \n ###################\n # train the model #\n ###################\n model.train()\n for batch_idx, (data, target) in enumerate(loaders['train']):\n # move to GPU\n if use_cuda:\n data, target = data.cuda(), target.cuda()\n ## find the loss and update the model parameters accordingly\n ## record the average training loss, using something like\n ## train_loss = train_loss + ((1 / (batch_idx + 1)) * (loss.data - train_loss))\n \n # clear the gradients of all optimized variables, initialize weights to zero\n optimizer.zero_grad()\n # forward pass\n output = model(data)\n # calculate batch loss\n loss = criterion(output, target)\n # backward pass\n loss.backward()\n # parameter update\n optimizer.step()\n # update training loss\n train_loss += loss.item() * data.size(0)\n \n ###################### \n # validate the model #\n ######################\n model.eval()\n for batch_idx, (data, target) in enumerate(loaders['valid']):\n # move to GPU\n if use_cuda:\n data, target = data.cuda(), target.cuda()\n ## update the average validation loss\n # forward pass\n output = model(data)\n # batch loss\n loss = criterion(output, target)\n # update validation loss\n valid_loss += loss.item() * data.size(0)\n \n # calculate average losses\n train_loss = train_loss/len(loaders['train'].dataset)\n valid_loss = valid_loss/len(loaders['valid'].dataset)\n \n # print training/validation statistics \n print('Epoch: {} \\tTraining Loss: {:.6f} \\tValidation Loss: {:.6f}'.format(\n epoch, \n train_loss,\n valid_loss\n ))\n \n ## TODO: save the model if validation loss has decreased\n if valid_loss <= valid_loss_min:\n print('Validation loss decreased ({:.6f} --> {:.6f}). Saving model...'.\n format(valid_loss_min, valid_loss))\n torch.save(model.state_dict(), save_path)\n valid_loss_min = valid_loss\n \n # return trained model\n return model\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train the model\nmodel_transfer = train(45, dataloaders, model_transfer, optimizer, criterion, use_cuda, 'model_transfer.pt')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Testing the model\n\nOnce we finish training, we can finally test our model to see how well it will perform with data it hasn't seen before. It is a fairly simple process, and we get a final accuracy of 97%","metadata":{}},{"cell_type":"code","source":"def test(loaders, model, criterion, use_cuda):\n\n # monitor test loss and accuracy\n test_loss = 0.\n correct = 0.\n total = 0.\n\n model.eval()\n for batch_idx, (data, target) in enumerate(loaders['test']):\n # move to GPU\n if use_cuda:\n data, target = data.cuda(), target.cuda()\n # forward pass: compute predicted outputs by passing inputs to the model\n output = model(data)\n # calculate the loss\n loss = criterion(output, target)\n # update average test loss \n test_loss = test_loss + ((1 / (batch_idx + 1)) * (loss.data - test_loss))\n # convert output probabilities to predicted class\n pred = output.data.max(1, keepdim=True)[1]\n # compare predictions to true label\n correct += np.sum(np.squeeze(pred.eq(target.data.view_as(pred))).cpu().numpy())\n total += data.size(0)\n \n print('Test Loss: {:.6f}\\n'.format(test_loss))\n\n print('\\nTest Accuracy: %2d%% (%2d/%2d)' % (\n 100. * correct / total, correct, total))\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test(dataloaders, model_transfer, criterion, use_cuda)","metadata":{},"execution_count":null,"outputs":[]}]} -------------------------------------------------------------------------------- /brain-tumor-detection-v1-0-cnn-vgg-16.ipynb: -------------------------------------------------------------------------------- 1 | {"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"**
Brain Tumor Detection with VGG-16 Model
**\n***\n**author**: Ruslan Klymentiev\n\n**date**: 10th June, 2019\n\n**Table of Contents**\n- 1. Project Overview and Objectives \n - 1.1. Data Set Description\n - 1.2. What is Brain Tumor?\n- 2. Setting up the Environment\n- 3. Data Import and Preprocessing\n- 4. CNN Model\n - 4.1. Data Augmentation\n - 4.1.1. Demo\n - 4.1.2. Apply\n - 4.2. Model Building\n - 4.3. Model Performance\n- 5. Conclusions","metadata":{}},{"cell_type":"markdown","source":"# 1. Project Overview and Objectives\n\nThe main purpose of this project was to build a CNN model that would classify if subject has a tumor or not base on MRI scan. I used the [VGG-16](https://www.kaggle.com/navoneel/brain-mri-images-for-brain-tumor-detection) model architecture and weights to train the model for this binary problem. I used `accuracy` as a metric to justify the model performance which can be defined as:\n\n$\\textrm{Accuracy} = \\frac{\\textrm{Number of correclty predicted images}}{\\textrm{Total number of tested images}} \\times 100\\%$\n\nFinal results look as follows:\n\n| Set | Accuracy |\n|:-:|:-:|\n| Validation Set* | ~88% |\n| Test Set* | ~80% |\n
\n\\* *Note: there might be some misunderstanding in terms of set names so I want to describe what do I mean by `test` and `validation` set:*\n* *`validation set` - is the set used during the model training to adjust the hyperparameters. *\n* *`test set` - is the small set that I don't touch for the whole training process at all. It's been used for final model performance evaluation.*\n\n## 1.1. Data Set Description\n\nThe image data that was used for this problem is [Brain MRI Images for Brain Tumor Detection](https://www.kaggle.com/navoneel/brain-mri-images-for-brain-tumor-detection). It conists of MRI scans of two classes:\n\n* `NO` - no tumor, encoded as `0`\n* `YES` - tumor, encoded as `1`\n\nUnfortunately, the data set description doesn't hold any information where this MRI scans come from and so on.\n\n## 1.2. What is Brain Tumor?\n\n> A brain tumor occurs when abnormal cells form within the brain. There are two main types of tumors: cancerous (malignant) tumors and benign tumors. Cancerous tumors can be divided into primary tumors, which start within the brain, and secondary tumors, which have spread from elsewhere, known as brain metastasis tumors. All types of brain tumors may produce symptoms that vary depending on the part of the brain involved. These symptoms may include headaches, seizures, problems with vision, vomiting and mental changes. The headache is classically worse in the morning and goes away with vomiting. Other symptoms may include difficulty walking, speaking or with sensations. As the disease progresses, unconsciousness may occur.\n>\n> ![](https://upload.wikimedia.org/wikipedia/commons/5/5f/Hirnmetastase_MRT-T1_KM.jpg)\n>\n> *Brain metastasis in the right cerebral hemisphere from lung cancer, shown on magnetic resonance imaging.*\n\nSource: [Wikipedia](https://en.wikipedia.org/wiki/Brain_tumor)","metadata":{}},{"cell_type":"markdown","source":"# 2. Setting up the Environment","metadata":{}},{"cell_type":"code","source":"from IPython.display import clear_output\n!pip install imutils\nclear_output()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np \nfrom tqdm import tqdm\nimport cv2\nimport os\nimport shutil\nimport itertools\nimport imutils\nimport matplotlib.pyplot as plt\nfrom sklearn.preprocessing import LabelBinarizer\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, confusion_matrix\n\nimport plotly.graph_objs as go\nfrom plotly.offline import init_notebook_mode, iplot\nfrom plotly import tools\n\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.applications.vgg16 import VGG16, preprocess_input\nfrom keras import layers\nfrom keras.models import Model, Sequential\nfrom keras.optimizers import Adam, RMSprop\nfrom keras.callbacks import EarlyStopping\n\ninit_notebook_mode(connected=True)\nRANDOM_SEED = 123","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Right now all images are in one folder with `yes` and `no` subfolders. I will split the data into `train`, `val` and `test` folders which makes its easier to work for me. The new folder heirarchy will look as follows:","metadata":{}},{"cell_type":"code","source":"!apt-get install tree\nclear_output()\n# create new folders\n!mkdir TRAIN TEST VAL TRAIN/YES TRAIN/NO TEST/YES TEST/NO VAL/YES VAL/NO\n!tree -d","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_PATH = '../input/brain-mri-images-for-brain-tumor-detection/brain_tumor_dataset/'\n# split the data by train/val/test\nfor CLASS in os.listdir(IMG_PATH):\n if not CLASS.startswith('.'):\n IMG_NUM = len(os.listdir(IMG_PATH + CLASS))\n for (n, FILE_NAME) in enumerate(os.listdir(IMG_PATH + CLASS)):\n img = IMG_PATH + CLASS + '/' + FILE_NAME\n if n < 5:\n shutil.copy(img, 'TEST/' + CLASS.upper() + '/' + FILE_NAME)\n elif n < 0.8*IMG_NUM:\n shutil.copy(img, 'TRAIN/'+ CLASS.upper() + '/' + FILE_NAME)\n else:\n shutil.copy(img, 'VAL/'+ CLASS.upper() + '/' + FILE_NAME)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Data Import and Preprocessing","metadata":{}},{"cell_type":"code","source":"def load_data(dir_path, img_size=(100,100)):\n \"\"\"\n Load resized images as np.arrays to workspace\n \"\"\"\n X = []\n y = []\n i = 0\n labels = dict()\n for path in tqdm(sorted(os.listdir(dir_path))):\n if not path.startswith('.'):\n labels[i] = path\n for file in os.listdir(dir_path + path):\n if not file.startswith('.'):\n img = cv2.imread(dir_path + path + '/' + file)\n X.append(img)\n y.append(i)\n i += 1\n X = np.array(X)\n y = np.array(y)\n print(f'{len(X)} images loaded from {dir_path} directory.')\n return X, y, labels\n\n\n\ndef plot_confusion_matrix(cm, classes,\n normalize=False,\n title='Confusion matrix',\n cmap=plt.cm.Blues):\n \"\"\"\n This function prints and plots the confusion matrix.\n Normalization can be applied by setting `normalize=True`.\n \"\"\"\n plt.figure(figsize = (6,6))\n plt.imshow(cm, interpolation='nearest', cmap=cmap)\n plt.title(title)\n plt.colorbar()\n tick_marks = np.arange(len(classes))\n plt.xticks(tick_marks, classes, rotation=90)\n plt.yticks(tick_marks, classes)\n if normalize:\n cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n\n thresh = cm.max() / 2.\n cm = np.round(cm,2)\n for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n plt.text(j, i, cm[i, j],\n horizontalalignment=\"center\",\n color=\"white\" if cm[i, j] > thresh else \"black\")\n plt.tight_layout()\n plt.ylabel('True label')\n plt.xlabel('Predicted label')\n plt.show()","metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_DIR = 'TRAIN/'\nTEST_DIR = 'TEST/'\nVAL_DIR = 'VAL/'\nIMG_SIZE = (224,224)\n\n# use predefined function to load the image data into workspace\nX_train, y_train, labels = load_data(TRAIN_DIR, IMG_SIZE)\nX_test, y_test, _ = load_data(TEST_DIR, IMG_SIZE)\nX_val, y_val, _ = load_data(VAL_DIR, IMG_SIZE)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's take a look at the distribution of classes among sets:","metadata":{}},{"cell_type":"code","source":"y = dict()\ny[0] = []\ny[1] = []\nfor set_name in (y_train, y_val, y_test):\n y[0].append(np.sum(set_name == 0))\n y[1].append(np.sum(set_name == 1))\n\ntrace0 = go.Bar(\n x=['Train Set', 'Validation Set', 'Test Set'],\n y=y[0],\n name='No',\n marker=dict(color='#33cc33'),\n opacity=0.7\n)\ntrace1 = go.Bar(\n x=['Train Set', 'Validation Set', 'Test Set'],\n y=y[1],\n name='Yes',\n marker=dict(color='#ff3300'),\n opacity=0.7\n)\ndata = [trace0, trace1]\nlayout = go.Layout(\n title='Count of classes in each set',\n xaxis={'title': 'Set'},\n yaxis={'title': 'Count'}\n)\nfig = go.Figure(data, layout)\niplot(fig)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_samples(X, y, labels_dict, n=50):\n \"\"\"\n Creates a gridplot for desired number of images (n) from the specified set\n \"\"\"\n for index in range(len(labels_dict)):\n imgs = X[np.argwhere(y == index)][:n]\n j = 10\n i = int(n/j)\n\n plt.figure(figsize=(15,6))\n c = 1\n for img in imgs:\n plt.subplot(i,j,c)\n plt.imshow(img[0])\n\n plt.xticks([])\n plt.yticks([])\n c += 1\n plt.suptitle('Tumor: {}'.format(labels_dict[index]))\n plt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_samples(X_train, y_train, labels, 30)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As you can see, images have different `width` and `height` and diffent size of \"black corners\". Since the image size for VGG-16 imput layer is `(224,224)` some wide images may look weird after resizing. Histogram of ratio distributions (`ratio = width/height`):","metadata":{}},{"cell_type":"code","source":"RATIO_LIST = []\nfor set in (X_train, X_test, X_val):\n for img in set:\n RATIO_LIST.append(img.shape[1]/img.shape[0])\n \nplt.hist(RATIO_LIST)\nplt.title('Distribution of Image Ratios')\nplt.xlabel('Ratio Value')\nplt.ylabel('Count')\nplt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The first step of \"normalization\" would be to crop the brain out of the images. I used technique which was perfectly described in [pyimagesearch](https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/) blog and I highly suggest to looks deeper into it.","metadata":{}},{"cell_type":"code","source":"def crop_imgs(set_name, add_pixels_value=0):\n \"\"\"\n Finds the extreme points on the image and crops the rectangular out of them\n \"\"\"\n set_new = []\n for img in set_name:\n gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n gray = cv2.GaussianBlur(gray, (5, 5), 0)\n\n # threshold the image, then perform a series of erosions +\n # dilations to remove any small regions of noise\n thresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]\n thresh = cv2.erode(thresh, None, iterations=2)\n thresh = cv2.dilate(thresh, None, iterations=2)\n\n # find contours in thresholded image, then grab the largest one\n cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n cnts = imutils.grab_contours(cnts)\n c = max(cnts, key=cv2.contourArea)\n\n # find the extreme points\n extLeft = tuple(c[c[:, :, 0].argmin()][0])\n extRight = tuple(c[c[:, :, 0].argmax()][0])\n extTop = tuple(c[c[:, :, 1].argmin()][0])\n extBot = tuple(c[c[:, :, 1].argmax()][0])\n\n ADD_PIXELS = add_pixels_value\n new_img = img[extTop[1]-ADD_PIXELS:extBot[1]+ADD_PIXELS, extLeft[0]-ADD_PIXELS:extRight[0]+ADD_PIXELS].copy()\n set_new.append(new_img)\n\n return np.array(set_new)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's look at example what this function will do with MRI scans:","metadata":{}},{"cell_type":"code","source":"img = cv2.imread('../input/brain-mri-images-for-brain-tumor-detection/brain_tumor_dataset/yes/Y108.jpg')\nimg = cv2.resize(\n img,\n dsize=IMG_SIZE,\n interpolation=cv2.INTER_CUBIC\n )\ngray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\ngray = cv2.GaussianBlur(gray, (5, 5), 0)\n\n# threshold the image, then perform a series of erosions +\n# dilations to remove any small regions of noise\nthresh = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY)[1]\nthresh = cv2.erode(thresh, None, iterations=2)\nthresh = cv2.dilate(thresh, None, iterations=2)\n\n# find contours in thresholded image, then grab the largest one\ncnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\ncnts = imutils.grab_contours(cnts)\nc = max(cnts, key=cv2.contourArea)\n\n# find the extreme points\nextLeft = tuple(c[c[:, :, 0].argmin()][0])\nextRight = tuple(c[c[:, :, 0].argmax()][0])\nextTop = tuple(c[c[:, :, 1].argmin()][0])\nextBot = tuple(c[c[:, :, 1].argmax()][0])\n\n# add contour on the image\nimg_cnt = cv2.drawContours(img.copy(), [c], -1, (0, 255, 255), 4)\n\n# add extreme points\nimg_pnt = cv2.circle(img_cnt.copy(), extLeft, 8, (0, 0, 255), -1)\nimg_pnt = cv2.circle(img_pnt, extRight, 8, (0, 255, 0), -1)\nimg_pnt = cv2.circle(img_pnt, extTop, 8, (255, 0, 0), -1)\nimg_pnt = cv2.circle(img_pnt, extBot, 8, (255, 255, 0), -1)\n\n# crop\nADD_PIXELS = 0\nnew_img = img[extTop[1]-ADD_PIXELS:extBot[1]+ADD_PIXELS, extLeft[0]-ADD_PIXELS:extRight[0]+ADD_PIXELS].copy()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(15,6))\nplt.subplot(141)\nplt.imshow(img)\nplt.xticks([])\nplt.yticks([])\nplt.title('Step 1. Get the original image')\nplt.subplot(142)\nplt.imshow(img_cnt)\nplt.xticks([])\nplt.yticks([])\nplt.title('Step 2. Find the biggest contour')\nplt.subplot(143)\nplt.imshow(img_pnt)\nplt.xticks([])\nplt.yticks([])\nplt.title('Step 3. Find the extreme points')\nplt.subplot(144)\nplt.imshow(new_img)\nplt.xticks([])\nplt.yticks([])\nplt.title('Step 4. Crop the image')\nplt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# apply this for each set\nX_train_crop = crop_imgs(set_name=X_train)\nX_val_crop = crop_imgs(set_name=X_val)\nX_test_crop = crop_imgs(set_name=X_test)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_samples(X_train_crop, y_train, labels, 30)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_new_images(x_set, y_set, folder_name):\n i = 0\n for (img, imclass) in zip(x_set, y_set):\n if imclass == 0:\n cv2.imwrite(folder_name+'NO/'+str(i)+'.jpg', img)\n else:\n cv2.imwrite(folder_name+'YES/'+str(i)+'.jpg', img)\n i += 1","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# saving new images to the folder\n!mkdir TRAIN_CROP TEST_CROP VAL_CROP TRAIN_CROP/YES TRAIN_CROP/NO TEST_CROP/YES TEST_CROP/NO VAL_CROP/YES VAL_CROP/NO\n\nsave_new_images(X_train_crop, y_train, folder_name='TRAIN_CROP/')\nsave_new_images(X_val_crop, y_val, folder_name='VAL_CROP/')\nsave_new_images(X_test_crop, y_test, folder_name='TEST_CROP/')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The next step would be resizing images to `(224,224)` and applying preprocessing needed for VGG-16 model input.","metadata":{}},{"cell_type":"code","source":"def preprocess_imgs(set_name, img_size):\n \"\"\"\n Resize and apply VGG-15 preprocessing\n \"\"\"\n set_new = []\n for img in set_name:\n img = cv2.resize(\n img,\n dsize=img_size,\n interpolation=cv2.INTER_CUBIC\n )\n set_new.append(preprocess_input(img))\n return np.array(set_new)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train_prep = preprocess_imgs(set_name=X_train_crop, img_size=IMG_SIZE)\nX_test_prep = preprocess_imgs(set_name=X_test_crop, img_size=IMG_SIZE)\nX_val_prep = preprocess_imgs(set_name=X_val_crop, img_size=IMG_SIZE)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot_samples(X_train_prep, y_train, labels, 30)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. CNN Model\n\nI was using [Transfer Learning](https://towardsdatascience.com/keras-transfer-learning-for-beginners-6c9b8b7143e) with VGG-16 architecture and weights as a base model.\n\n## 4.1. Data Augmentation\n\nSince I had small data set I used the technique called [Data Augmentation](https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html) which helps to \"increase\" the size of training set.\n\n### 4.1.1. Demo\n\nThat's the example from one image how does augmentation look like.","metadata":{}},{"cell_type":"code","source":"# set the paramters we want to change randomly\ndemo_datagen = ImageDataGenerator(\n rotation_range=15,\n width_shift_range=0.05,\n height_shift_range=0.05,\n rescale=1./255,\n shear_range=0.05,\n brightness_range=[0.1, 1.5],\n horizontal_flip=True,\n vertical_flip=True\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.mkdir('preview')\nx = X_train_crop[0] \nx = x.reshape((1,) + x.shape) \n\ni = 0\nfor batch in demo_datagen.flow(x, batch_size=1, save_to_dir='preview', save_prefix='aug_img', save_format='jpg'):\n i += 1\n if i > 20:\n break ","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(X_train_crop[0])\nplt.xticks([])\nplt.yticks([])\nplt.title('Original Image')\nplt.show()\n\nplt.figure(figsize=(15,6))\ni = 1\nfor img in os.listdir('preview/'):\n img = cv2.cv2.imread('preview/' + img)\n img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n plt.subplot(3,7,i)\n plt.imshow(img)\n plt.xticks([])\n plt.yticks([])\n i += 1\n if i > 3*7:\n break\nplt.suptitle('Augemented Images')\nplt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf preview/","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 4.1.2. Apply","metadata":{}},{"cell_type":"code","source":"TRAIN_DIR = 'TRAIN_CROP/'\nVAL_DIR = 'VAL_CROP/'\n\ntrain_datagen = ImageDataGenerator(\n rotation_range=15,\n width_shift_range=0.1,\n height_shift_range=0.1,\n shear_range=0.1,\n brightness_range=[0.5, 1.5],\n horizontal_flip=True,\n vertical_flip=True,\n preprocessing_function=preprocess_input\n)\n\ntest_datagen = ImageDataGenerator(\n preprocessing_function=preprocess_input\n)\n\n\ntrain_generator = train_datagen.flow_from_directory(\n TRAIN_DIR,\n color_mode='rgb',\n target_size=IMG_SIZE,\n batch_size=32,\n class_mode='binary',\n seed=RANDOM_SEED\n)\n\n\nvalidation_generator = test_datagen.flow_from_directory(\n VAL_DIR,\n color_mode='rgb',\n target_size=IMG_SIZE,\n batch_size=16,\n class_mode='binary',\n seed=RANDOM_SEED\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4.2. Model Building","metadata":{}},{"cell_type":"code","source":"# load base model\nvgg16_weight_path = '../input/keras-pretrained-models/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'\nbase_model = VGG16(\n weights=vgg16_weight_path,\n include_top=False, \n input_shape=IMG_SIZE + (3,)\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_CLASSES = 1\n\nmodel = Sequential()\nmodel.add(base_model)\nmodel.add(layers.Flatten())\nmodel.add(layers.Dropout(0.5))\nmodel.add(layers.Dense(NUM_CLASSES, activation='sigmoid'))\n\nmodel.layers[0].trainable = False\n\nmodel.compile(\n loss='binary_crossentropy',\n optimizer=RMSprop(lr=1e-4),\n metrics=['accuracy']\n)\n\nmodel.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"EPOCHS = 30\nes = EarlyStopping(\n monitor='val_acc', \n mode='max',\n patience=6\n)\n\nhistory = model.fit_generator(\n train_generator,\n steps_per_epoch=50,\n epochs=EPOCHS,\n validation_data=validation_generator,\n validation_steps=25,\n callbacks=[es]\n)","metadata":{"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4.3. Model Performance","metadata":{}},{"cell_type":"code","source":"# plot model performance\nacc = history.history['acc']\nval_acc = history.history['val_acc']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs_range = range(1, len(history.epoch) + 1)\n\nplt.figure(figsize=(15,5))\n\nplt.subplot(1, 2, 1)\nplt.plot(epochs_range, acc, label='Train Set')\nplt.plot(epochs_range, val_acc, label='Val Set')\nplt.legend(loc=\"best\")\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.title('Model Accuracy')\n\nplt.subplot(1, 2, 2)\nplt.plot(epochs_range, loss, label='Train Set')\nplt.plot(epochs_range, val_loss, label='Val Set')\nplt.legend(loc=\"best\")\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.title('Model Loss')\n\nplt.tight_layout()\nplt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# validate on val set\npredictions = model.predict(X_val_prep)\npredictions = [1 if x>0.5 else 0 for x in predictions]\n\naccuracy = accuracy_score(y_val, predictions)\nprint('Val Accuracy = %.2f' % accuracy)\n\nconfusion_mtx = confusion_matrix(y_val, predictions) \ncm = plot_confusion_matrix(confusion_mtx, classes = list(labels.items()), normalize=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# validate on test set\npredictions = model.predict(X_test_prep)\npredictions = [1 if x>0.5 else 0 for x in predictions]\n\naccuracy = accuracy_score(y_test, predictions)\nprint('Test Accuracy = %.2f' % accuracy)\n\nconfusion_mtx = confusion_matrix(y_test, predictions) \ncm = plot_confusion_matrix(confusion_mtx, classes = list(labels.items()), normalize=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now let's take a look at the images from the `test set` that were misclassified:","metadata":{}},{"cell_type":"code","source":"ind_list = np.argwhere((y_test == predictions) == False)[:, -1]\nif ind_list.size == 0:\n print('There are no missclassified images.')\nelse:\n for i in ind_list:\n plt.figure()\n plt.imshow(X_test_crop[i])\n plt.xticks([])\n plt.yticks([])\n plt.title(f'Actual class: {y_val[i]}\\nPredicted class: {predictions[i]}')\n plt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"First scan looks a bit misleading - what is that light spot in the middle? 🤔 I can clearly see why model classified it as `Tumor`.","metadata":{}},{"cell_type":"markdown","source":"# 5. Conclusions\n\nThis project was a combination of CNN model classification problem (to predict wheter the subject has brain tumor or not) & Computer Vision problem (to automate the process of brain cropping from MRI scans). The final accuracy is much higher than 50% baseline (random guess). However, it could be increased by larger number of train images or through model hyperparameters tuning.","metadata":{}},{"cell_type":"code","source":"# clean up the space\n!rm -rf TRAIN TEST VAL TRAIN_CROP TEST_CROP VAL_CROP\n# save the model\nmodel.save('2019-06-07_VGG_model.h5')","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]}]} -------------------------------------------------------------------------------- /tensorflow-pneumonia-classification-on-x-rays.ipynb: -------------------------------------------------------------------------------- 1 | {"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 1. Introduction + Set-up\n\nMachine learning has a phenomenal range of applications, including in health and diagnostics. This tutorial will explain the complete pipeline from loading data to predicting results, and it will explain how to build an X-ray image classification model from scratch to predict whether an X-ray scan shows presence of pneumonia. This is especially useful during these current times as COVID-19 is known to cause pneumonia.\n\nThis tutorial will explain how to utilize TPUs efficiently, load in image data, build and train a convolution neural network, finetune and regularize the model, and predict results. Data augmentation is not included in the model because X-ray scans are only taken in a specific orientation, and variations such as flips and rotations will not exist in real X-ray images. For a tutorial on image data augmentation, check out this [tutorial](https://www.kaggle.com/amyjang/tensorflow-data-augmentation-efficientnet).\n\nRun the following cell to load the necessary packages. Make sure to change the Accelerator on the right to `TPU`.","metadata":{}},{"cell_type":"code","source":"import re\nimport os\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom kaggle_datasets import KaggleDatasets\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\n\ntry:\n tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n print('Device:', tpu.master())\n tf.config.experimental_connect_to_cluster(tpu)\n tf.tpu.experimental.initialize_tpu_system(tpu)\n strategy = tf.distribute.experimental.TPUStrategy(tpu)\nexcept:\n strategy = tf.distribute.get_strategy()\nprint('Number of replicas:', strategy.num_replicas_in_sync)\n \nprint(tf.__version__)\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We need a Google Cloud link to our data to load the data using a TPU. While we're at it, we instantiate constant variables. It is generally better practice to use constant variables instead of hard-coding numbers.","metadata":{}},{"cell_type":"code","source":"AUTOTUNE = tf.data.experimental.AUTOTUNE\nGCS_PATH = KaggleDatasets().get_gcs_path()\nBATCH_SIZE = 16 * strategy.num_replicas_in_sync\nIMAGE_SIZE = [180, 180]\nEPOCHS = 25","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Load the data\n\nThe Chest X-ray data we are using from [*Cell*](https://www.kaggle.com/paultimothymooney/chest-xray-pneumonia) divides the data into train, val, and test files. There are only 16 files in the validation folder, and we would prefer to have a less extreme division between the training and the validation set. We will append the validation files and create a new split that resembes the standard 80:20 division instead.","metadata":{}},{"cell_type":"code","source":"filenames = tf.io.gfile.glob(str(GCS_PATH + '/chest_xray/train/*/*'))\nfilenames.extend(tf.io.gfile.glob(str(GCS_PATH + '/chest_xray/val/*/*')))\n\ntrain_filenames, val_filenames = train_test_split(filenames, test_size=0.2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Run the following cell to see how many healthy/normal chest X-rays we have and how many pneumonia chest X-rays we have.","metadata":{}},{"cell_type":"code","source":"COUNT_NORMAL = len([filename for filename in train_filenames if \"NORMAL\" in filename])\nprint(\"Normal images count in training set: \" + str(COUNT_NORMAL))\n\nCOUNT_PNEUMONIA = len([filename for filename in train_filenames if \"PNEUMONIA\" in filename])\nprint(\"Pneumonia images count in training set: \" + str(COUNT_PNEUMONIA))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Notice that the there are way more images that are classified as pneumonia than normal. This shows that we have a imbalance in our data. We will correct for this imbalance later on in our notebook.","metadata":{}},{"cell_type":"code","source":"train_list_ds = tf.data.Dataset.from_tensor_slices(train_filenames)\nval_list_ds = tf.data.Dataset.from_tensor_slices(val_filenames)\n\nfor f in train_list_ds.take(5):\n print(f.numpy())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Run the following cell to see how many images we have in our training dataset and how many images we have in our validation set. Verify that the ratio of images is 80:20.","metadata":{}},{"cell_type":"code","source":"TRAIN_IMG_COUNT = tf.data.experimental.cardinality(train_list_ds).numpy()\nprint(\"Training images count: \" + str(TRAIN_IMG_COUNT))\n\nVAL_IMG_COUNT = tf.data.experimental.cardinality(val_list_ds).numpy()\nprint(\"Validating images count: \" + str(VAL_IMG_COUNT))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As expected, we have two labels for our images.","metadata":{}},{"cell_type":"code","source":"CLASS_NAMES = np.array([str(tf.strings.split(item, os.path.sep)[-1].numpy())[2:-1]\n for item in tf.io.gfile.glob(str(GCS_PATH + \"/chest_xray/train/*\"))])\nCLASS_NAMES","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Currently our dataset is just a list of filenames. We want to map each filename to the corresponding (image, label) pair. The following methods will help us do that.\n\nAs we only have two labels, we will rewrite the label so that `1` or `True` indicates pneumonia and `0` or `False` indicates normal.","metadata":{}},{"cell_type":"code","source":"def get_label(file_path):\n # convert the path to a list of path components\n parts = tf.strings.split(file_path, os.path.sep)\n # The second to last is the class-directory\n return parts[-2] == \"PNEUMONIA\"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The images originally have values that range from [0, 255]. CNNs work better with smaller numbers so we will scale this down.","metadata":{}},{"cell_type":"code","source":"def decode_img(img):\n # convert the compressed string to a 3D uint8 tensor\n img = tf.image.decode_jpeg(img, channels=3)\n # Use `convert_image_dtype` to convert to floats in the [0,1] range.\n img = tf.image.convert_image_dtype(img, tf.float32)\n # resize the image to the desired size.\n return tf.image.resize(img, IMAGE_SIZE)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def process_path(file_path):\n label = get_label(file_path)\n # load the raw data from the file as a string\n img = tf.io.read_file(file_path)\n img = decode_img(img)\n return img, label","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = train_list_ds.map(process_path, num_parallel_calls=AUTOTUNE)\n\nval_ds = val_list_ds.map(process_path, num_parallel_calls=AUTOTUNE)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's visualize the shape of an (image, label) pair.","metadata":{}},{"cell_type":"code","source":"for image, label in train_ds.take(1):\n print(\"Image shape: \", image.numpy().shape)\n print(\"Label: \", label.numpy())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Load and format the test data as well.","metadata":{}},{"cell_type":"code","source":"test_list_ds = tf.data.Dataset.list_files(str(GCS_PATH + '/chest_xray/test/*/*'))\nTEST_IMAGE_COUNT = tf.data.experimental.cardinality(test_list_ds).numpy()\ntest_ds = test_list_ds.map(process_path, num_parallel_calls=AUTOTUNE)\ntest_ds = test_ds.batch(BATCH_SIZE)\n\nTEST_IMAGE_COUNT","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Visualize the dataset\n\nFirst, let's use buffered prefetching so we can yield data from disk without having I/O become blocking.","metadata":{}},{"cell_type":"code","source":"def prepare_for_training(ds, cache=True, shuffle_buffer_size=1000):\n # This is a small dataset, only load it once, and keep it in memory.\n # use `.cache(filename)` to cache preprocessing work for datasets that don't\n # fit in memory.\n if cache:\n if isinstance(cache, str):\n ds = ds.cache(cache)\n else:\n ds = ds.cache()\n\n ds = ds.shuffle(buffer_size=shuffle_buffer_size)\n\n # Repeat forever\n ds = ds.repeat()\n\n ds = ds.batch(BATCH_SIZE)\n\n # `prefetch` lets the dataset fetch batches in the background while the model\n # is training.\n ds = ds.prefetch(buffer_size=AUTOTUNE)\n\n return ds","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Call the next batch iteration of the training data.","metadata":{}},{"cell_type":"code","source":"train_ds = prepare_for_training(train_ds)\nval_ds = prepare_for_training(val_ds)\n\nimage_batch, label_batch = next(iter(train_ds))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Define the method to show the images in the batch.","metadata":{}},{"cell_type":"code","source":"def show_batch(image_batch, label_batch):\n plt.figure(figsize=(10,10))\n for n in range(25):\n ax = plt.subplot(5,5,n+1)\n plt.imshow(image_batch[n])\n if label_batch[n]:\n plt.title(\"PNEUMONIA\")\n else:\n plt.title(\"NORMAL\")\n plt.axis(\"off\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As the method takes in numpy arrays as its parameters, call the numpy function on the batches to return the tensor in numpy array form.","metadata":{}},{"cell_type":"code","source":"show_batch(image_batch.numpy(), label_batch.numpy())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Build the CNN\n\nTo make our model more modular and easier to understand, let's define some blocks. As we're building a convolution neural network, we'll create a convolution block and a dense layer block.\n\nThe architecture for this CNN has been inspired by this [article](https://towardsdatascience.com/deep-learning-for-detecting-pneumonia-from-x-ray-images-fc9a3d9fdba8).","metadata":{}},{"cell_type":"code","source":"def conv_block(filters):\n block = tf.keras.Sequential([\n tf.keras.layers.SeparableConv2D(filters, 3, activation='relu', padding='same'),\n tf.keras.layers.SeparableConv2D(filters, 3, activation='relu', padding='same'),\n tf.keras.layers.BatchNormalization(),\n tf.keras.layers.MaxPool2D()\n ]\n )\n \n return block","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def dense_block(units, dropout_rate):\n block = tf.keras.Sequential([\n tf.keras.layers.Dense(units, activation='relu'),\n tf.keras.layers.BatchNormalization(),\n tf.keras.layers.Dropout(dropout_rate)\n ])\n \n return block","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The following method will define the function to build our model for us. The Dropout layers are important as they \"drop out,\" hence the name, certain nodes to reduce the likelikhood of the model overfitting. We want to end the model with a Dense layer of one node, as this will be the output that determines if an X-ray shows an image of pneumonia.","metadata":{}},{"cell_type":"code","source":"def build_model():\n model = tf.keras.Sequential([\n tf.keras.Input(shape=(IMAGE_SIZE[0], IMAGE_SIZE[1], 3)),\n \n tf.keras.layers.Conv2D(16, 3, activation='relu', padding='same'),\n tf.keras.layers.Conv2D(16, 3, activation='relu', padding='same'),\n tf.keras.layers.MaxPool2D(),\n \n conv_block(32),\n conv_block(64),\n \n conv_block(128),\n tf.keras.layers.Dropout(0.2),\n \n conv_block(256),\n tf.keras.layers.Dropout(0.2),\n \n tf.keras.layers.Flatten(),\n dense_block(512, 0.7),\n dense_block(128, 0.5),\n dense_block(64, 0.3),\n \n tf.keras.layers.Dense(1, activation='sigmoid')\n ])\n \n return model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Correct for data imbalance\n\nWe saw earlier in this notebook that the data was imbalanced, with more images classified as pneumonia than normal. We will correct for that in this following section.","metadata":{}},{"cell_type":"code","source":"initial_bias = np.log([COUNT_PNEUMONIA/COUNT_NORMAL])\ninitial_bias","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"weight_for_0 = (1 / COUNT_NORMAL)*(TRAIN_IMG_COUNT)/2.0 \nweight_for_1 = (1 / COUNT_PNEUMONIA)*(TRAIN_IMG_COUNT)/2.0\n\nclass_weight = {0: weight_for_0, 1: weight_for_1}\n\nprint('Weight for class 0: {:.2f}'.format(weight_for_0))\nprint('Weight for class 1: {:.2f}'.format(weight_for_1))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The weight for class `0` (Normal) is a lot higher than the weight for class `1` (Pneumonia). Because there are less normal images, each normal image will be weighted more to balance the data as the CNN works best when the training data is balanced.","metadata":{}},{"cell_type":"markdown","source":"# 6. Train the model\n\nSince there are only two possible labels for the image, we will be using the `binary_crossentropy` loss. When we fit the model, identify the class weights. Because we are using a TPU, training will be relatively quick.\n\nFor our metrics, we want to include precision and recall as they will provide use with a more informed picture of how good our model is. Accuracy tells us what fractions are the labels are correct. Since our data is not balanced, accuracy might give a skewed sense of a good model (i.e. a model that always predicts PNEUMONIA will be 74% accurate but is not a good model).\n\nPrecision is the number of true positives (TP) over the sum of TP and false positives (FP). It shows what fraction of labeled positives are actually correct.\n\nRecall is the number of TP over the sum of TP and false negatves (FN). It shows what fraction of actual positives are correct.","metadata":{}},{"cell_type":"code","source":"with strategy.scope():\n model = build_model()\n\n METRICS = [\n 'accuracy',\n tf.keras.metrics.Precision(name='precision'),\n tf.keras.metrics.Recall(name='recall')\n ]\n \n model.compile(\n optimizer='adam',\n loss='binary_crossentropy',\n metrics=METRICS\n )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From exploring the data and the model, I noticed that the training for the model has a slow start. However, after 25 epochs, the model slowly starts to converge.","metadata":{}},{"cell_type":"code","source":"history = model.fit(\n train_ds,\n steps_per_epoch=TRAIN_IMG_COUNT // BATCH_SIZE,\n epochs=EPOCHS,\n validation_data=val_ds,\n validation_steps=VAL_IMG_COUNT // BATCH_SIZE,\n class_weight=class_weight,\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 7. Finetune the model\n\nFinetuning is an art when it comes to Machine Learning, and there are many ways to adjust the model in efforts to improve it. Finetuning is beyond the scope of this notebook, but check out this [article](https://www.pyimagesearch.com/2019/06/03/fine-tuning-with-keras-and-deep-learning/) for more information.\n\nFor our purposes, we'll use Keras callbacks to further finetune our model. The checkpoint callback saves the best weights of the model, so next time we want to use the model, we do not have to spend time training it. The early stopping callback stops the training process when the model starts becoming stagnant, or even worse, when the model starts overfitting. Since we set `restore_best_weights` to `True`, the returned model at the end of the training process will be the model with the best weights (i.e. low loss and high accuracy).","metadata":{}},{"cell_type":"code","source":"checkpoint_cb = tf.keras.callbacks.ModelCheckpoint(\"xray_model.h5\",\n save_best_only=True)\n\nearly_stopping_cb = tf.keras.callbacks.EarlyStopping(patience=10,\n restore_best_weights=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We also want to finetune our learning rate. Too high of a learning rate will cause the model to diverge. Too small of a learning rate will cause the model to be too slow. We implement the exponential learning rate scheduling method below.","metadata":{}},{"cell_type":"code","source":"def exponential_decay(lr0, s):\n def exponential_decay_fn(epoch):\n return lr0 * 0.1 **(epoch / s)\n return exponential_decay_fn\n\nexponential_decay_fn = exponential_decay(0.01, 20)\n\nlr_scheduler = tf.keras.callbacks.LearningRateScheduler(exponential_decay_fn)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n train_ds,\n steps_per_epoch=TRAIN_IMG_COUNT // BATCH_SIZE,\n epochs=100,\n validation_data=val_ds,\n validation_steps=VAL_IMG_COUNT // BATCH_SIZE,\n class_weight=class_weight,\n callbacks=[checkpoint_cb, early_stopping_cb, lr_scheduler]\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 8. Visualizing model performance\n\nLet's plot the model accuracy and loss for the training and the validating set. These plots show the accuracy and loss values for the second round of training. Since we initially trained the model with 30 epochs, these would be epochs 31-45. Note that no random seed is specified for this notebook. For your notebook, there might be slight variance.","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(1, 4, figsize=(20, 3))\nax = ax.ravel()\n\nfor i, met in enumerate(['precision', 'recall', 'accuracy', 'loss']):\n ax[i].plot(history.history[met])\n ax[i].plot(history.history['val_' + met])\n ax[i].set_title('Model {}'.format(met))\n ax[i].set_xlabel('epochs')\n ax[i].set_ylabel(met)\n ax[i].legend(['train', 'val'])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We see that the accuracy for our model is around 98%. Finetune the model further to see if we can achieve a higher accuracy.","metadata":{}},{"cell_type":"markdown","source":"# 9. Predict and evaluate results\n\nLet's evaluate the model on our test data!","metadata":{}},{"cell_type":"code","source":"loss, acc, prec, rec = model.evaluate(test_ds)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We see that our accuracy on our test data is 83%, which is lower than the accuracy for our validating set. This may indicate overfitting. Try finetuning the model further to decrease overfitting to the training and validation sets.\n\nOur recall is greater than our precision, indicating that almost all pneumonia images are correctly identified but some normal images are falsely identified. We should aim to increase our precision.","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]} -------------------------------------------------------------------------------- /wcwp-climate-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SARTHAK2511/Data-Science-Projects/4f5e6a5ec6ab14d699ba5f4f4564420387de7abe/wcwp-climate-master.zip --------------------------------------------------------------------------------