├── .gitignore ├── Eye Images ├── eye1.jpg ├── eye2.jpg ├── eye3.jpg ├── eye4.jpg ├── eye5.jpg ├── eye6.jpg ├── eye7.jpg ├── eye8.jpg ├── result │ ├── eye1.jpg.jpg │ ├── eye2.jpg.jpg │ ├── eye3.jpg.jpg │ ├── eye4.jpg.jpg │ ├── eye5.jpg.jpg │ ├── eye6.jpg.jpg │ ├── eye7.jpg.jpg │ └── eye8.jpg.jpg └── result_erosion │ ├── eye1.jpg.jpg │ ├── eye2.jpg.jpg │ ├── eye3.jpg.jpg │ ├── eye4.jpg.jpg │ ├── eye5.jpg.jpg │ ├── eye6.jpg.jpg │ ├── eye7.jpg.jpg │ └── eye8.jpg.jpg ├── LICENSE ├── README.md ├── detect_pupil.py └── detect_pupil_v2.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /Eye Images/eye1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye1.jpg -------------------------------------------------------------------------------- /Eye Images/eye2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye2.jpg -------------------------------------------------------------------------------- /Eye Images/eye3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye3.jpg -------------------------------------------------------------------------------- /Eye Images/eye4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye4.jpg -------------------------------------------------------------------------------- /Eye Images/eye5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye5.jpg -------------------------------------------------------------------------------- /Eye Images/eye6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye6.jpg -------------------------------------------------------------------------------- /Eye Images/eye7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye7.jpg -------------------------------------------------------------------------------- /Eye Images/eye8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/eye8.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye1.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye1.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye2.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye2.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye3.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye3.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye4.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye4.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye5.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye5.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye6.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye6.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye7.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye7.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result/eye8.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result/eye8.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye1.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye1.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye2.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye2.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye3.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye3.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye4.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye4.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye5.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye5.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye6.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye6.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye7.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye7.jpg.jpg -------------------------------------------------------------------------------- /Eye Images/result_erosion/eye8.jpg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thelalitarora/PUPIL-Detection-using-OpenCV/e52836028178c2df196bf5e82a4290e828a494de/Eye Images/result_erosion/eye8.jpg.jpg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 LALIT ARORA 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PUPIL-Detection-using-OpenCV 2 | PUPIL detection from eyes images using OpenCV 3 and Python 3.6. 3 | 4 | Face detection and Eyes detection using OpenCV is a common project which can be demonstrated using HAARCASCADEs by OpenCV. OpenCV have provided various trainers which can be used directly in detecting Faces, Eyes and other various elements. 5 | 6 | ## PUPIL detection 7 | Detecting PUPIL or EyeBall using OpenCV. 8 | 9 | ### Algorithm 10 | 1. First take the eye image. 11 | 2. Make it invert. 12 | 3. Convert it to gray scale. 13 | 4. Apply Erosion Transform. 14 | 5. Use binary filter taking threshold value 220. 15 | 6. Find the biggest object. 16 | 7. Find that object's center point and height. 17 | 8. Highlight that circle. 18 | 19 | ### detect_pupil_v2.py 20 | Color Image Denoising and Gaussian Blur techniques are used for pre-processing the eye image before applying inversion filter over it. 21 | For segmentation, the contour with center nearest to center of image is filtered. **Eyeball will be near to center of eye image** 22 | Rest algorithm for pupil detection is same as in detect_pupil.py 23 | 24 | 25 | ### Useful Links 26 | 27 | **Morphological Erosion** : https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html 28 | 29 | **OpenCV contours and Hierarchy** : https://github.com/eyantrainternship/eYSIP_2015_Marker_based_Robot_Localisation/wiki/Contours-and-Hierarchy 30 | 31 | **Denoising Images** : https://docs.opencv.org/3.2.0/d5/d69/tutorial_py_non_local_means.html 32 | 33 | **Smoothing Images** : https://docs.opencv.org/3.1.0/d4/d13/tutorial_py_filtering.html 34 | -------------------------------------------------------------------------------- /detect_pupil.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Aug 3 12:46:13 2019 4 | IDE : Anaconda (Spyder) 5 | @author: LALIT ARORA 6 | """ 7 | 8 | import cv2 9 | import os 10 | import numpy as np 11 | from pprint import pprint 12 | 13 | # directory that holds eyes images to find and detect the purpil 14 | eyes_dir = "Eye Images" 15 | 16 | 17 | class pupil_detection(): 18 | def __init__(self, image_path): 19 | self._img = None 20 | self._img_path = image_path 21 | self._pupil = None 22 | 23 | def load_image(self): 24 | self._img = cv2.imread(self._img_path) 25 | # If the image doesn't exists or is not valid then imread returns None 26 | if type(self._img) == None: 27 | return False 28 | else: 29 | return True 30 | 31 | def save_image (self): 32 | name = "\\".join(self._img_path.split('\\')[:-1])+"\\result_erosion\\"+str(self._img_path.split('\\')[-1])+".jpg" 33 | print(name) 34 | cv2.imwrite(name,self._img) 35 | 36 | def detect_pupil (self): 37 | inv = cv2.bitwise_not(self._img) 38 | thresh = cv2.cvtColor(inv, cv2.COLOR_BGR2GRAY) 39 | kernel = np.ones((2,2),np.uint8) 40 | erosion = cv2.erode(thresh,kernel,iterations = 1) 41 | ret,thresh1 = cv2.threshold(erosion,220,255,cv2.THRESH_BINARY) 42 | cnts, hierarchy = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 43 | if len(cnts) != 0: 44 | c = max(cnts, key = cv2.contourArea) 45 | (x,y),radius = cv2.minEnclosingCircle(c) 46 | center = (int(x),int(y)) 47 | radius = int(radius) 48 | cv2.circle(self._img,center,radius,(255,0,0),2) 49 | 50 | def start_detection(self): 51 | if(self.load_image()): 52 | self.detect_pupil() 53 | cv2.imshow("IRIS DETECTION", self._img) 54 | cv2.waitKey(0) 55 | self.save_image() 56 | else: 57 | print('Image file "' + self._img_path + '" could not be loaded.') 58 | 59 | 60 | images = [] 61 | 62 | for file in os.listdir(eyes_dir): 63 | if file.endswith(".jpg"): 64 | path = os.getcwd() 65 | images.append(os.path.join(path, eyes_dir, file)) 66 | 67 | 68 | for image in images: 69 | id = pupil_detection(image) 70 | id.start_detection() 71 | -------------------------------------------------------------------------------- /detect_pupil_v2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Aug 3 12:46:13 2019 4 | 5 | @author: LALIT ARORA 6 | """ 7 | 8 | #import numpy 9 | import cv2 10 | import operator 11 | import numpy as np 12 | 13 | class pupil_detection(): 14 | def __init__(self, image_path): 15 | ''' 16 | initialize the class and set the class attributes 17 | ''' 18 | self._img = None 19 | self._img_path = image_path 20 | self._pupil = None 21 | self._centroid = None 22 | 23 | def load_image(self): 24 | ''' 25 | load the image based on the path passed to the class 26 | it should use the method cv2.imread to load the image 27 | it should also detect if the file exists 28 | ''' 29 | self._img = cv2.imread(self._img_path) 30 | # If the image doesn't exists or is not valid then imread returns None 31 | if type(self._img) == None: 32 | return False 33 | else: 34 | return True 35 | 36 | def show_image (self,img): 37 | cv2.imshow("Result",img) 38 | cv2.waitKey(0) 39 | 40 | def centroid (self): 41 | # convert image to grayscale image 42 | gray_image = cv2.cvtColor(self._img, cv2.COLOR_BGR2GRAY) 43 | # convert the grayscale image to binary image 44 | ret,thresh = cv2.threshold(gray_image,127,255,0) 45 | # calculate moments of binary image 46 | M = cv2.moments(thresh) 47 | # calculate x,y coordinate of center 48 | cX = int(M["m10"] / M["m00"]) 49 | cY = int(M["m01"] / M["m00"]) 50 | self._centroid = (cX,cY) 51 | #cv2.circle(self._img, (cX, cY), 5, (255, 255, 255), -1) 52 | 53 | def detect_pupil (self): 54 | dst = cv2.fastNlMeansDenoisingColored(self._img,None,10,10,7,21) 55 | blur = cv2.GaussianBlur(dst,(5,5),0) 56 | inv = cv2.bitwise_not(blur) 57 | thresh = cv2.cvtColor(inv, cv2.COLOR_BGR2GRAY) 58 | kernel = np.ones((2,2),np.uint8) 59 | erosion = cv2.erode(thresh,kernel,iterations = 1) 60 | ret,thresh1 = cv2.threshold(erosion,210,255,cv2.THRESH_BINARY) 61 | cnts, hierarchy = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 62 | flag = 10000 63 | final_cnt = None 64 | for cnt in cnts: 65 | (x,y),radius = cv2.minEnclosingCircle(cnt) 66 | distance = abs(self._centroid[0]-x)+abs(self._centroid[1]-y) 67 | if distance < flag : 68 | flag = distance 69 | final_cnt = cnt 70 | else: 71 | continue 72 | (x,y),radius = cv2.minEnclosingCircle(final_cnt) 73 | center = (int(x),int(y)) 74 | radius = int(radius) 75 | cv2.circle(self._img,center,radius,(255,0,0),2) 76 | 77 | self._pupil = (center[0],center[1],radius) 78 | self.show_image(self._img) 79 | 80 | def start_detection(self): 81 | if(self.load_image()): 82 | self.centroid() 83 | self.detect_pupil() 84 | else: 85 | print('Image file "' + self._img_path + '" could not be loaded.') 86 | 87 | id = pupil_detection(r'') 88 | id.start_detection() 89 | --------------------------------------------------------------------------------