├── FaceAttendance ├── Attendance │ └── Attendance_13-05-2021.csv ├── StudentDetails │ └── StudentDetails.csv ├── TrainingImageLabel │ ├── Trainner.yml │ └── psd.txt ├── VideoPlayer.py ├── VideoRecorder.py ├── exportToHTML │ └── main.py.html ├── haarcascade_frontalface_default.xml ├── main.py └── requirements.txt ├── Marksheet update using tkinter simple project ├── Marksheet.xlsx └── mainapp.py └── README.md /FaceAttendance/Attendance/Attendance_13-05-2021.csv: -------------------------------------------------------------------------------- 1 | Id,,Name,,Date,,Time 2 | ,,,,,, 3 | ,,,,,, 4 | ,,,,,, 5 | ,,,,,, 6 | -------------------------------------------------------------------------------- /FaceAttendance/StudentDetails/StudentDetails.csv: -------------------------------------------------------------------------------- 1 | SERIAL NO.,,ID,,NAME 2 | -------------------------------------------------------------------------------- /FaceAttendance/TrainingImageLabel/psd.txt: -------------------------------------------------------------------------------- 1 | bbb -------------------------------------------------------------------------------- /FaceAttendance/VideoPlayer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Mar 18 03:55:06 2017 4 | 5 | """ 6 | 7 | import numpy 8 | import cv2 9 | 10 | cap=cv2.VideoCapture('C:\Users\Mohammad Bakir\Documents\FACE RECOGNITION BASED ATTENDANCE MONITORING SYSTEM/video.avi') 11 | print("VideoPlayer") 12 | while(cap.isOpened()): 13 | ret,frame=cap.read() 14 | cv2.resizeWindow('Videoplayer',640,340) 15 | cv2.imshow('VideoPlayer',frame) 16 | if cv2.waitKey(25)==ord('q'): 17 | break 18 | cap.release() 19 | cv2.destroyAllWindows() 20 | -------------------------------------------------------------------------------- /FaceAttendance/VideoRecorder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Mar 18 20:01:14 2017 4 | 5 | """ 6 | 7 | 8 | import matplotlib.pyplot as plt 9 | import cv2 10 | 11 | try: 12 | 13 | cap=cv2.VideoCapture(0) 14 | fourcc=cv2.VideoWriter_fourcc(*'DIVX') 15 | output=cv2.VideoWriter('C:\Users\Mohammad Bakir\Documents\FACE RECOGNITION BASED ATTENDANCE MONITORING SYSTEM/capture1.mp4',fourcc,15.0,(640,480),True) 16 | 17 | while(True): 18 | ret,frame=cap.read() 19 | gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) 20 | hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV) 21 | output.write(hsv) 22 | cv2.resizeWindow('Cam',640,460) 23 | cv2.imshow('Cam',frame) 24 | if cv2.waitKey(1)==ord('q'): 25 | break 26 | 27 | cap.release() 28 | output.release() 29 | cv2.destroyAllWindows() 30 | except: 31 | cap.release() 32 | output.release() 33 | cv2.destroyAllWindows() 34 | 35 | -------------------------------------------------------------------------------- /FaceAttendance/exportToHTML/main.py.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |############################################# IMPORTING ################################################ 21 | import tkinter as tk 22 | from tkinter import ttk 23 | from tkinter import messagebox as mess 24 | import tkinter.simpledialog as tsd 25 | import cv2,os 26 | import csv 27 | import numpy as np 28 | from PIL import Image 29 | import pandas as pd 30 | import datetime 31 | import time 32 | 33 | ############################################# FUNCTIONS ################################################ 34 | 35 | def assure_path_exists(path): 36 | dir = os.path.dirname(path) 37 | if not os.path.exists(dir): 38 | os.makedirs(dir) 39 | 40 | ################################################################################## 41 | 42 | def tick(): 43 | time_string = time.strftime('%H:%M:%S') 44 | clock.config(text=time_string) 45 | clock.after(200,tick) 46 | 47 | ################################################################################### 48 | 49 | def contact(): 50 | mess._show(title='Contact us', message="Please contact us on : 'shubhamkumar8180323@gmail.com' ") 51 | 52 | ################################################################################### 53 | 54 | def check_haarcascadefile(): 55 | exists = os.path.isfile("haarcascade_frontalface_default.xml") 56 | if exists: 57 | pass 58 | else: 59 | mess._show(title='Some file missing', message='Please contact us for help') 60 | window.destroy() 61 | 62 | ################################################################################### 63 | 64 | def save_pass(): 65 | assure_path_exists("TrainingImageLabel/") 66 | exists1 = os.path.isfile("TrainingImageLabel\psd.txt") 67 | if exists1: 68 | tf = open("TrainingImageLabel\psd.txt", "r") 69 | key = tf.read() 70 | else: 71 | master.destroy() 72 | new_pas = tsd.askstring('Old Password not found', 'Please enter a new password below', show='*') 73 | if new_pas == None: 74 | mess._show(title='No Password Entered', message='Password not set!! Please try again') 75 | else: 76 | tf = open("TrainingImageLabel\psd.txt", "w") 77 | tf.write(new_pas) 78 | mess._show(title='Password Registered', message='New password was registered successfully!!') 79 | return 80 | op = (old.get()) 81 | newp= (new.get()) 82 | nnewp = (nnew.get()) 83 | if (op == key): 84 | if(newp == nnewp): 85 | txf = open("TrainingImageLabel\psd.txt", "w") 86 | txf.write(newp) 87 | else: 88 | mess._show(title='Error', message='Confirm new password again!!!') 89 | return 90 | else: 91 | mess._show(title='Wrong Password', message='Please enter correct old password.') 92 | return 93 | mess._show(title='Password Changed', message='Password changed successfully!!') 94 | master.destroy() 95 | 96 | ################################################################################### 97 | 98 | def change_pass(): 99 | global master 100 | master = tk.Tk() 101 | master.geometry("400x160") 102 | master.resizable(False,False) 103 | master.title("Change Password") 104 | master.configure(background="white") 105 | lbl4 = tk.Label(master,text=' Enter Old Password',bg='white',font=('times', 12, ' bold ')) 106 | lbl4.place(x=10,y=10) 107 | global old 108 | old=tk.Entry(master,width=25 ,fg="black",relief='solid',font=('times', 12, ' bold '),show='*') 109 | old.place(x=180,y=10) 110 | lbl5 = tk.Label(master, text=' Enter New Password', bg='white', font=('times', 12, ' bold ')) 111 | lbl5.place(x=10, y=45) 112 | global new 113 | new = tk.Entry(master, width=25, fg="black",relief='solid', font=('times', 12, ' bold '),show='*') 114 | new.place(x=180, y=45) 115 | lbl6 = tk.Label(master, text='Confirm New Password', bg='white', font=('times', 12, ' bold ')) 116 | lbl6.place(x=10, y=80) 117 | global nnew 118 | nnew = tk.Entry(master, width=25, fg="black", relief='solid',font=('times', 12, ' bold '),show='*') 119 | nnew.place(x=180, y=80) 120 | cancel=tk.Button(master,text="Cancel", command=master.destroy ,fg="black" ,bg="red" ,height=1,width=25 , activebackground = "white" ,font=('times', 10, ' bold ')) 121 | cancel.place(x=200, y=120) 122 | save1 = tk.Button(master, text="Save", command=save_pass, fg="black", bg="#3ece48", height = 1,width=25, activebackground="white", font=('times', 10, ' bold ')) 123 | save1.place(x=10, y=120) 124 | master.mainloop() 125 | 126 | ##################################################################################### 127 | 128 | def psw(): 129 | assure_path_exists("TrainingImageLabel/") 130 | exists1 = os.path.isfile("TrainingImageLabel\psd.txt") 131 | if exists1: 132 | tf = open("TrainingImageLabel\psd.txt", "r") 133 | key = tf.read() 134 | else: 135 | new_pas = tsd.askstring('Old Password not found', 'Please enter a new password below', show='*') 136 | if new_pas == None: 137 | mess._show(title='No Password Entered', message='Password not set!! Please try again') 138 | else: 139 | tf = open("TrainingImageLabel\psd.txt", "w") 140 | tf.write(new_pas) 141 | mess._show(title='Password Registered', message='New password was registered successfully!!') 142 | return 143 | password = tsd.askstring('Password', 'Enter Password', show='*') 144 | if (password == key): 145 | TrainImages() 146 | elif (password == None): 147 | pass 148 | else: 149 | mess._show(title='Wrong Password', message='You have entered wrong password') 150 | 151 | ###################################################################################### 152 | 153 | def clear(): 154 | txt.delete(0, 'end') 155 | res = "1)Take Images >>> 2)Save Profile" 156 | message1.configure(text=res) 157 | 158 | 159 | def clear2(): 160 | txt2.delete(0, 'end') 161 | res = "1)Take Images >>> 2)Save Profile" 162 | message1.configure(text=res) 163 | 164 | ####################################################################################### 165 | 166 | def TakeImages(): 167 | check_haarcascadefile() 168 | columns = ['SERIAL NO.', '', 'ID', '', 'NAME'] 169 | assure_path_exists("StudentDetails/") 170 | assure_path_exists("TrainingImage/") 171 | serial = 0 172 | exists = os.path.isfile("StudentDetails\StudentDetails.csv") 173 | if exists: 174 | with open("StudentDetails\StudentDetails.csv", 'r') as csvFile1: 175 | reader1 = csv.reader(csvFile1) 176 | for l in reader1: 177 | serial = serial + 1 178 | serial = (serial // 2) 179 | csvFile1.close() 180 | else: 181 | with open("StudentDetails\StudentDetails.csv", 'a+') as csvFile1: 182 | writer = csv.writer(csvFile1) 183 | writer.writerow(columns) 184 | serial = 1 185 | csvFile1.close() 186 | Id = (txt.get()) 187 | name = (txt2.get()) 188 | if ((name.isalpha()) or (' ' in name)): 189 | cam = cv2.VideoCapture(0) 190 | harcascadePath = "haarcascade_frontalface_default.xml" 191 | detector = cv2.CascadeClassifier(harcascadePath) 192 | sampleNum = 0 193 | while (True): 194 | ret, img = cam.read() 195 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 196 | faces = detector.detectMultiScale(gray, 1.3, 5) 197 | for (x, y, w, h) in faces: 198 | cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 199 | # incrementing sample number 200 | sampleNum = sampleNum + 1 201 | # saving the captured face in the dataset folder TrainingImage 202 | cv2.imwrite("TrainingImage\ " + name + "." + str(serial) + "." + Id + '.' + str(sampleNum) + ".jpg", 203 | gray[y:y + h, x:x + w]) 204 | # display the frame 205 | cv2.imshow('Taking Images', img) 206 | # wait for 100 miliseconds 207 | if cv2.waitKey(100) & 0xFF == ord('q'): 208 | break 209 | # break if the sample number is morethan 100 210 | elif sampleNum > 100: 211 | break 212 | cam.release() 213 | cv2.destroyAllWindows() 214 | res = "Images Taken for ID : " + Id 215 | row = [serial, '', Id, '', name] 216 | with open('StudentDetails\StudentDetails.csv', 'a+') as csvFile: 217 | writer = csv.writer(csvFile) 218 | writer.writerow(row) 219 | csvFile.close() 220 | message1.configure(text=res) 221 | else: 222 | if (name.isalpha() == False): 223 | res = "Enter Correct name" 224 | message.configure(text=res) 225 | 226 | ######################################################################################## 227 | 228 | def TrainImages(): 229 | check_haarcascadefile() 230 | assure_path_exists("TrainingImageLabel/") 231 | recognizer = cv2.face_LBPHFaceRecognizer.create() 232 | harcascadePath = "haarcascade_frontalface_default.xml" 233 | detector = cv2.CascadeClassifier(harcascadePath) 234 | faces, ID = getImagesAndLabels("TrainingImage/") 235 | try: 236 | recognizer.train(faces, np.array(ID)) 237 | except: 238 | mess._show(title='No Registrations', message='Please Register someone first!!!') 239 | return 240 | recognizer.save("TrainingImageLabel\Trainner.yml") 241 | res = "Profile Saved Successfully" 242 | message1.configure(text=res) 243 | message.configure(text='Total Registrations till now : ' + str(ID[0])) 244 | 245 | ############################################################################################3 246 | 247 | def getImagesAndLabels(path): 248 | # get the path of all the files in the folder 249 | imagePaths = [os.path.join(path, f) for f in os.listdir(path)] 250 | # create empth face list 251 | faces = [] 252 | # create empty ID list 253 | Ids = [] 254 | # now looping through all the image paths and loading the Ids and the images 255 | for imagePath in imagePaths: 256 | # loading the image and converting it to gray scale 257 | pilImage = Image.open(imagePath).convert('L') 258 | # Now we are converting the PIL image into numpy array 259 | imageNp = np.array(pilImage, 'uint8') 260 | # getting the Id from the image 261 | ID = int(os.path.split(imagePath)[-1].split(".")[1]) 262 | # extract the face from the training image sample 263 | faces.append(imageNp) 264 | Ids.append(ID) 265 | return faces, Ids 266 | 267 | ########################################################################################### 268 | 269 | def TrackImages(): 270 | check_haarcascadefile() 271 | assure_path_exists("Attendance/") 272 | assure_path_exists("StudentDetails/") 273 | for k in tv.get_children(): 274 | tv.delete(k) 275 | msg = '' 276 | i = 0 277 | j = 0 278 | recognizer = cv2.face.LBPHFaceRecognizer_create() # cv2.createLBPHFaceRecognizer() 279 | exists3 = os.path.isfile("TrainingImageLabel\Trainner.yml") 280 | if exists3: 281 | recognizer.read("TrainingImageLabel\Trainner.yml") 282 | else: 283 | mess._show(title='Data Missing', message='Please click on Save Profile to reset data!!') 284 | return 285 | harcascadePath = "haarcascade_frontalface_default.xml" 286 | faceCascade = cv2.CascadeClassifier(harcascadePath); 287 | 288 | cam = cv2.VideoCapture(0) 289 | font = cv2.FONT_HERSHEY_SIMPLEX 290 | col_names = ['Id', '', 'Name', '', 'Date', '', 'Time'] 291 | exists1 = os.path.isfile("StudentDetails\StudentDetails.csv") 292 | if exists1: 293 | df = pd.read_csv("StudentDetails\StudentDetails.csv") 294 | else: 295 | mess._show(title='Details Missing', message='Students details are missing, please check!') 296 | cam.release() 297 | cv2.destroyAllWindows() 298 | window.destroy() 299 | while True: 300 | ret, im = cam.read() 301 | gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) 302 | faces = faceCascade.detectMultiScale(gray, 1.2, 5) 303 | for (x, y, w, h) in faces: 304 | cv2.rectangle(im, (x, y), (x + w, y + h), (225, 0, 0), 2) 305 | serial, conf = recognizer.predict(gray[y:y + h, x:x + w]) 306 | if (conf < 50): 307 | ts = time.time() 308 | date = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y') 309 | timeStamp = datetime.datetime.fromtimestamp(ts).strftime('%H:%M:%S') 310 | aa = df.loc[df['SERIAL NO.'] == serial]['NAME'].values 311 | ID = df.loc[df['SERIAL NO.'] == serial]['ID'].values 312 | ID = str(ID) 313 | ID = ID[1:-1] 314 | bb = str(aa) 315 | bb = bb[2:-2] 316 | attendance = [str(ID), '', bb, '', str(date), '', str(timeStamp)] 317 | 318 | else: 319 | Id = 'Unknown' 320 | bb = str(Id) 321 | cv2.putText(im, str(bb), (x, y + h), font, 1, (255, 255, 255), 2) 322 | cv2.imshow('Taking Attendance', im) 323 | if (cv2.waitKey(1) == ord('q')): 324 | break 325 | ts = time.time() 326 | date = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y') 327 | exists = os.path.isfile("Attendance\Attendance_" + date + ".csv") 328 | if exists: 329 | with open("Attendance\Attendance_" + date + ".csv", 'a+') as csvFile1: 330 | writer = csv.writer(csvFile1) 331 | writer.writerow(attendance) 332 | csvFile1.close() 333 | else: 334 | with open("Attendance\Attendance_" + date + ".csv", 'a+') as csvFile1: 335 | writer = csv.writer(csvFile1) 336 | writer.writerow(col_names) 337 | writer.writerow(attendance) 338 | csvFile1.close() 339 | with open("Attendance\Attendance_" + date + ".csv", 'r') as csvFile1: 340 | reader1 = csv.reader(csvFile1) 341 | for lines in reader1: 342 | i = i + 1 343 | if (i > 1): 344 | if (i % 2 != 0): 345 | iidd = str(lines[0]) + ' ' 346 | tv.insert('', 0, text=iidd, values=(str(lines[2]), str(lines[4]), str(lines[6]))) 347 | csvFile1.close() 348 | cam.release() 349 | cv2.destroyAllWindows() 350 | 351 | ######################################## USED STUFFS ############################################ 352 | 353 | global key 354 | key = '' 355 | 356 | ts = time.time() 357 | date = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y') 358 | day,month,year=date.split("-") 359 | 360 | mont={'01':'January', 361 | '02':'February', 362 | '03':'March', 363 | '04':'April', 364 | '05':'May', 365 | '06':'June', 366 | '07':'July', 367 | '08':'August', 368 | '09':'September', 369 | '10':'October', 370 | '11':'November', 371 | '12':'December' 372 | } 373 | 374 | ######################################## GUI FRONT-END ########################################### 375 | 376 | window = tk.Tk() 377 | window.geometry("1280x720") 378 | window.resizable(True,False) 379 | window.title("Attendance System") 380 | window.configure(background='#262523') 381 | 382 | frame1 = tk.Frame(window, bg="#00aeff") 383 | frame1.place(relx=0.11, rely=0.17, relwidth=0.39, relheight=0.80) 384 | 385 | frame2 = tk.Frame(window, bg="#00aeff") 386 | frame2.place(relx=0.51, rely=0.17, relwidth=0.38, relheight=0.80) 387 | 388 | message3 = tk.Label(window, text="Face Recognition Based Attendance System" ,fg="white",bg="#262523" ,width=55 ,height=1,font=('times', 29, ' bold ')) 389 | message3.place(x=10, y=10) 390 | 391 | frame3 = tk.Frame(window, bg="#c4c6ce") 392 | frame3.place(relx=0.52, rely=0.09, relwidth=0.09, relheight=0.07) 393 | 394 | frame4 = tk.Frame(window, bg="#c4c6ce") 395 | frame4.place(relx=0.36, rely=0.09, relwidth=0.16, relheight=0.07) 396 | 397 | datef = tk.Label(frame4, text = day+"-"+mont[month]+"-"+year+" | ", fg="orange",bg="#262523" ,width=55 ,height=1,font=('times', 22, ' bold ')) 398 | datef.pack(fill='both',expand=1) 399 | 400 | clock = tk.Label(frame3,fg="orange",bg="#262523" ,width=55 ,height=1,font=('times', 22, ' bold ')) 401 | clock.pack(fill='both',expand=1) 402 | tick() 403 | 404 | head2 = tk.Label(frame2, text=" For New Registrations ", fg="black",bg="#3ece48" ,font=('times', 17, ' bold ') ) 405 | head2.grid(row=0,column=0) 406 | 407 | head1 = tk.Label(frame1, text=" For Already Registered ", fg="black",bg="#3ece48" ,font=('times', 17, ' bold ') ) 408 | head1.place(x=0,y=0) 409 | 410 | lbl = tk.Label(frame2, text="Enter ID",width=20 ,height=1 ,fg="black" ,bg="#00aeff" ,font=('times', 17, ' bold ') ) 411 | lbl.place(x=80, y=55) 412 | 413 | txt = tk.Entry(frame2,width=32 ,fg="black",font=('times', 15, ' bold ')) 414 | txt.place(x=30, y=88) 415 | 416 | lbl2 = tk.Label(frame2, text="Enter Name",width=20 ,fg="black" ,bg="#00aeff" ,font=('times', 17, ' bold ')) 417 | lbl2.place(x=80, y=140) 418 | 419 | txt2 = tk.Entry(frame2,width=32 ,fg="black",font=('times', 15, ' bold ') ) 420 | txt2.place(x=30, y=173) 421 | 422 | message1 = tk.Label(frame2, text="1)Take Images >>> 2)Save Profile" ,bg="#00aeff" ,fg="black" ,width=39 ,height=1, activebackground = "yellow" ,font=('times', 15, ' bold ')) 423 | message1.place(x=7, y=230) 424 | 425 | message = tk.Label(frame2, text="" ,bg="#00aeff" ,fg="black" ,width=39,height=1, activebackground = "yellow" ,font=('times', 16, ' bold ')) 426 | message.place(x=7, y=450) 427 | 428 | lbl3 = tk.Label(frame1, text="Attendance",width=20 ,fg="black" ,bg="#00aeff" ,height=1 ,font=('times', 17, ' bold ')) 429 | lbl3.place(x=100, y=115) 430 | 431 | res=0 432 | exists = os.path.isfile("StudentDetails\StudentDetails.csv") 433 | if exists: 434 | with open("StudentDetails\StudentDetails.csv", 'r') as csvFile1: 435 | reader1 = csv.reader(csvFile1) 436 | for l in reader1: 437 | res = res + 1 438 | res = (res // 2) - 1 439 | csvFile1.close() 440 | else: 441 | res = 0 442 | message.configure(text='Total Registrations till now : '+str(res)) 443 | 444 | ##################### MENUBAR ################################# 445 | 446 | menubar = tk.Menu(window,relief='ridge') 447 | filemenu = tk.Menu(menubar,tearoff=0) 448 | filemenu.add_command(label='Change Password', command = change_pass) 449 | filemenu.add_command(label='Contact Us', command = contact) 450 | filemenu.add_command(label='Exit',command = window.destroy) 451 | menubar.add_cascade(label='Help',font=('times', 29, ' bold '),menu=filemenu) 452 | 453 | ################## TREEVIEW ATTENDANCE TABLE #################### 454 | 455 | tv= ttk.Treeview(frame1,height =13,columns = ('name','date','time')) 456 | tv.column('#0',width=82) 457 | tv.column('name',width=130) 458 | tv.column('date',width=133) 459 | tv.column('time',width=133) 460 | tv.grid(row=2,column=0,padx=(0,0),pady=(150,0),columnspan=4) 461 | tv.heading('#0',text ='ID') 462 | tv.heading('name',text ='NAME') 463 | tv.heading('date',text ='DATE') 464 | tv.heading('time',text ='TIME') 465 | 466 | ###################### SCROLLBAR ################################ 467 | 468 | scroll=ttk.Scrollbar(frame1,orient='vertical',command=tv.yview) 469 | scroll.grid(row=2,column=4,padx=(0,100),pady=(150,0),sticky='ns') 470 | tv.configure(yscrollcommand=scroll.set) 471 | 472 | ###################### BUTTONS ################################## 473 | 474 | clearButton = tk.Button(frame2, text="Clear", command=clear ,fg="black" ,bg="#ea2a2a" ,width=11 ,activebackground = "white" ,font=('times', 11, ' bold ')) 475 | clearButton.place(x=335, y=86) 476 | clearButton2 = tk.Button(frame2, text="Clear", command=clear2 ,fg="black" ,bg="#ea2a2a" ,width=11 , activebackground = "white" ,font=('times', 11, ' bold ')) 477 | clearButton2.place(x=335, y=172) 478 | takeImg = tk.Button(frame2, text="Take Images", command=TakeImages ,fg="white" ,bg="blue" ,width=34 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 479 | takeImg.place(x=30, y=300) 480 | trainImg = tk.Button(frame2, text="Save Profile", command=psw ,fg="white" ,bg="blue" ,width=34 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 481 | trainImg.place(x=30, y=380) 482 | trackImg = tk.Button(frame1, text="Take Attendance", command=TrackImages ,fg="black" ,bg="yellow" ,width=35 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 483 | trackImg.place(x=30,y=50) 484 | quitWindow = tk.Button(frame1, text="Quit", command=window.destroy ,fg="black" ,bg="red" ,width=35 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 485 | quitWindow.place(x=30, y=450) 486 | 487 | ##################### END ###################################### 488 | 489 | window.configure(menu=menubar) 490 | window.mainloop() 491 | 492 | #################################################################################################### 493 |494 | 495 | 496 | -------------------------------------------------------------------------------- /FaceAttendance/main.py: -------------------------------------------------------------------------------- 1 | ############################################# IMPORTING ################################################ 2 | import tkinter as tk 3 | from tkinter import ttk 4 | from tkinter import messagebox as mess 5 | import tkinter.simpledialog as tsd 6 | import cv2 7 | import os 8 | import csv 9 | import numpy as np 10 | from PIL import Image 11 | import pandas as pd 12 | import datetime 13 | import time 14 | 15 | ############################################# FUNCTIONS ################################################ 16 | 17 | def assure_path_exists(path): 18 | dir = os.path.dirname(path) 19 | if not os.path.exists(dir): 20 | os.makedirs(dir) 21 | 22 | ################################################################################## 23 | 24 | def tick(): 25 | time_string = time.strftime('%H:%M:%S') 26 | clock.config(text=time_string) 27 | clock.after(200,tick) 28 | 29 | ################################################################################### 30 | 31 | def contact(): 32 | mess._show(title='Contact us', message="Please contact us on : 'shubhamkumar8180323@gmail.com' ") 33 | 34 | ################################################################################### 35 | 36 | def check_haarcascadefile(): 37 | exists = os.path.isfile("haarcascade_frontalface_default.xml") 38 | if exists: 39 | pass 40 | else: 41 | mess._show(title='Some file missing', message='Please contact us for help') 42 | window.destroy() 43 | 44 | ################################################################################### 45 | 46 | def save_pass(): 47 | assure_path_exists("TrainingImageLabel/") 48 | exists1 = os.path.isfile("TrainingImageLabel\psd.txt") 49 | if exists1: 50 | tf = open("TrainingImageLabel\psd.txt", "r") 51 | key = tf.read() 52 | else: 53 | master.destroy() 54 | new_pas = tsd.askstring('Old Password not found', 'Please enter a new password below', show='*') 55 | if new_pas == None: 56 | mess._show(title='No Password Entered', message='Password not set!! Please try again') 57 | else: 58 | tf = open("TrainingImageLabel\psd.txt", "w") 59 | tf.write(new_pas) 60 | mess._show(title='Password Registered', message='New password was registered successfully!!') 61 | return 62 | op = (old.get()) 63 | newp= (new.get()) 64 | nnewp = (nnew.get()) 65 | if (op == key): 66 | if(newp == nnewp): 67 | txf = open("TrainingImageLabel\psd.txt", "w") 68 | txf.write(newp) 69 | else: 70 | mess._show(title='Error', message='Confirm new password again!!!') 71 | return 72 | else: 73 | mess._show(title='Wrong Password', message='Please enter correct old password.') 74 | return 75 | mess._show(title='Password Changed', message='Password changed successfully!!') 76 | master.destroy() 77 | 78 | ################################################################################### 79 | 80 | def change_pass(): 81 | global master 82 | master = tk.Tk() 83 | master.geometry("400x160") 84 | master.resizable(False,False) 85 | master.title("Change Password") 86 | master.configure(background="white") 87 | lbl4 = tk.Label(master,text=' Enter Old Password',bg='white',font=('times', 12, ' bold ')) 88 | lbl4.place(x=10,y=10) 89 | global old 90 | old=tk.Entry(master,width=25 ,fg="black",relief='solid',font=('times', 12, ' bold '),show='*') 91 | old.place(x=180,y=10) 92 | lbl5 = tk.Label(master, text=' Enter New Password', bg='white', font=('times', 12, ' bold ')) 93 | lbl5.place(x=10, y=45) 94 | global new 95 | new = tk.Entry(master, width=25, fg="black",relief='solid', font=('times', 12, ' bold '),show='*') 96 | new.place(x=180, y=45) 97 | lbl6 = tk.Label(master, text='Confirm New Password', bg='white', font=('times', 12, ' bold ')) 98 | lbl6.place(x=10, y=80) 99 | global nnew 100 | nnew = tk.Entry(master, width=25, fg="black", relief='solid',font=('times', 12, ' bold '),show='*') 101 | nnew.place(x=180, y=80) 102 | cancel=tk.Button(master,text="Cancel", command=master.destroy ,fg="black" ,bg="red" ,height=1,width=25 , activebackground = "white" ,font=('times', 10, ' bold ')) 103 | cancel.place(x=200, y=120) 104 | save1 = tk.Button(master, text="Save", command=save_pass, fg="black", bg="#3ece48", height = 1,width=25, activebackground="white", font=('times', 10, ' bold ')) 105 | save1.place(x=10, y=120) 106 | master.mainloop() 107 | 108 | ##################################################################################### 109 | 110 | def psw(): 111 | assure_path_exists("TrainingImageLabel/") 112 | exists1 = os.path.isfile("TrainingImageLabel\psd.txt") 113 | if exists1: 114 | tf = open("TrainingImageLabel\psd.txt", "r") 115 | key = tf.read() 116 | else: 117 | new_pas = tsd.askstring('Old Password not found', 'Please enter a new password below', show='*') 118 | if new_pas == None: 119 | mess._show(title='No Password Entered', message='Password not set!! Please try again') 120 | else: 121 | tf = open("TrainingImageLabel\psd.txt", "w") 122 | tf.write(new_pas) 123 | mess._show(title='Password Registered', message='New password was registered successfully!!') 124 | return 125 | password = tsd.askstring('Password', 'Enter Password', show='*') 126 | if (password == key): 127 | TrainImages() 128 | elif (password == None): 129 | pass 130 | else: 131 | mess._show(title='Wrong Password', message='You have entered wrong password') 132 | 133 | ###################################################################################### 134 | 135 | def clear(): 136 | txt.delete(0, 'end') 137 | res = "1)Take Images >>> 2)Save Profile" 138 | message1.configure(text=res) 139 | 140 | 141 | def clear2(): 142 | txt2.delete(0, 'end') 143 | res = "1)Take Images >>> 2)Save Profile" 144 | message1.configure(text=res) 145 | 146 | ####################################################################################### 147 | 148 | def TakeImages(): 149 | check_haarcascadefile() 150 | columns = ['SERIAL NO.', '', 'ID', '', 'NAME'] 151 | assure_path_exists("StudentDetails/") 152 | assure_path_exists("TrainingImag=e/") 153 | serial = 0 154 | exists = os.path.isfile("StudentDetails\StudentDetails.csv") 155 | if exists: 156 | with open("StudentDetails\StudentDetails.csv", 'r') as csvFile1: 157 | reader1 = csv.reader(csvFile1) 158 | for l in reader1: 159 | serial = serial + 1 160 | serial = (serial // 2) 161 | csvFile1.close() 162 | else: 163 | with open("StudentDetails\StudentDetails.csv", 'a+') as csvFile1: 164 | writer = csv.writer(csvFile1) 165 | writer.writerow(columns) 166 | serial = 1 167 | csvFile1.close() 168 | Id = (txt.get()) 169 | name = (txt2.get()) 170 | if ((name.isalpha()) or (' ' in name)): 171 | cam = cv2.VideoCapture(0) 172 | harcascadePath = "haarcascade_frontalface_default.xml" 173 | detector = cv2.CascadeClassifier(harcascadePath) 174 | sampleNum = 0 175 | while (True): 176 | ret, img = cam.read() 177 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 178 | faces = detector.detectMultiScale(gray, 1.3, 5) 179 | for (x, y, w, h) in faces: 180 | cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) 181 | # incrementing sample number 182 | sampleNum = sampleNum + 1 183 | # saving the captured face in the dataset folder TrainingImage 184 | cv2.imwrite("TrainingImage\ " + name + "." + str(serial) + "." + Id + '.' + str(sampleNum) + ".jpg", 185 | gray[y:y + h, x:x + w]) 186 | # display the frame 187 | cv2.imshow('Taking Images', img) 188 | # wait for 100 miliseconds 189 | if cv2.waitKey(100) & 0xFF == ord('q'): 190 | break 191 | # break if the sample number is morethan 100 192 | elif sampleNum > 100: 193 | break 194 | cam.release() 195 | cv2.destroyAllWindows() 196 | res = "Images Taken for ID : " + Id 197 | row = [serial, '', Id, '', name] 198 | with open('StudentDetails\StudentDetails.csv', 'a+') as csvFile: 199 | writer = csv.writer(csvFile) 200 | writer.writerow(row) 201 | csvFile.close() 202 | message1.configure(text=res) 203 | else: 204 | if (name.isalpha() == False): 205 | res = "Enter Correct name" 206 | message.configure(text=res) 207 | 208 | ######################################################################################## 209 | 210 | def TrainImages(): 211 | check_haarcascadefile() 212 | assure_path_exists("TrainingImageLabel/") 213 | recognizer = cv2.face_LBPHFaceRecognizer.create() 214 | harcascadePath = "haarcascade_frontalface_default.xml" 215 | detector = cv2.CascadeClassifier(harcascadePath) 216 | faces, ID = getImagesAndLabels("TrainingImage/") 217 | try: 218 | recognizer.train(faces, np.array(ID)) 219 | except: 220 | mess._show(title='No Registrations', message='Please Register someone first!!!') 221 | return 222 | recognizer.save("TrainingImageLabel\Trainner.yml") 223 | res = "Profile Saved Successfully" 224 | message1.configure(text=res) 225 | message.configure(text='Total Registrations till now : ' + str(ID[0])) 226 | 227 | ############################################################################################3 228 | 229 | def getImagesAndLabels(path): 230 | # get the path of all the files in the folder 231 | imagePaths = [os.path.join(path, f) for f in os.listdir(path)] 232 | # create empth face list 233 | faces = [] 234 | # create empty ID list 235 | Ids = [] 236 | # now looping through all the image paths and loading the Ids and the images 237 | for imagePath in imagePaths: 238 | # loading the image and converting it to gray scale 239 | pilImage = Image.open(imagePath).convert('L') 240 | # Now we are converting the PIL image into numpy array 241 | imageNp = np.array(pilImage, 'uint8') 242 | # getting the Id from the image 243 | ID = int(os.path.split(imagePath)[-1].split(".")[1]) 244 | # extract the face from the training image sample 245 | faces.append(imageNp) 246 | Ids.append(ID) 247 | return faces, Ids 248 | 249 | ########################################################################################### 250 | 251 | def TrackImages(): 252 | check_haarcascadefile() 253 | assure_path_exists("Attendance/") 254 | assure_path_exists("StudentDetails/") 255 | for k in tv.get_children(): 256 | tv.delete(k) 257 | msg = '' 258 | i = 0 259 | j = 0 260 | recognizer = cv2.face.LBPHFaceRecognizer_create() # cv2.createLBPHFaceRecognizer() 261 | exists3 = os.path.isfile("TrainingImageLabel\Trainner.yml") 262 | if exists3: 263 | recognizer.read("TrainingImageLabel\Trainner.yml") 264 | else: 265 | mess._show(title='Data Missing', message='Please click on Save Profile to reset data!!') 266 | return 267 | harcascadePath = "haarcascade_frontalface_default.xml" 268 | faceCascade = cv2.CascadeClassifier(harcascadePath); 269 | 270 | cam = cv2.VideoCapture(0) 271 | font = cv2.FONT_HERSHEY_SIMPLEX 272 | col_names = ['Id', '', 'Name', '', 'Date', '', 'Time'] 273 | exists1 = os.path.isfile("StudentDetails\StudentDetails.csv") 274 | if exists1: 275 | df = pd.read_csv("StudentDetails\StudentDetails.csv") 276 | else: 277 | mess._show(title='Details Missing', message='Students details are missing, please check!') 278 | cam.release() 279 | cv2.destroyAllWindows() 280 | window.destroy() 281 | while True: 282 | ret, im = cam.read() 283 | gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) 284 | faces = faceCascade.detectMultiScale(gray, 1.2, 5) 285 | for (x, y, w, h) in faces: 286 | cv2.rectangle(im, (x, y), (x + w, y + h), (225, 0, 0), 2) 287 | serial, conf = recognizer.predict(gray[y:y + h, x:x + w]) 288 | if (conf < 50): 289 | ts = time.time() 290 | date = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y') 291 | timeStamp = datetime.datetime.fromtimestamp(ts).strftime('%H:%M:%S') 292 | aa = df.loc[df['SERIAL NO.'] == serial]['NAME'].values 293 | ID = df.loc[df['SERIAL NO.'] == serial]['ID'].values 294 | ID = str(ID) 295 | ID = ID[1:-1] 296 | bb = str(aa) 297 | bb = bb[2:-2] 298 | attendance = [str(ID), '', bb, '', str(date), '', str(timeStamp)] 299 | 300 | else: 301 | Id = 'Unknown' 302 | bb = str(Id) 303 | cv2.putText(im, str(bb), (x, y + h), font, 1, (255, 255, 255), 2) 304 | cv2.imshow('Taking Attendance', im) 305 | if (cv2.waitKey(1) == ord('q')): 306 | break 307 | ts = time.time() 308 | date = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y') 309 | exists = os.path.isfile("Attendance\Attendance_" + date + ".csv") 310 | if exists: 311 | with open("Attendance\Attendance_" + date + ".csv", 'a+') as csvFile1: 312 | writer = csv.writer(csvFile1) 313 | writer.writerow(attendance) 314 | csvFile1.close() 315 | else: 316 | with open("Attendance\Attendance_" + date + ".csv", 'a+') as csvFile1: 317 | writer = csv.writer(csvFile1) 318 | writer.writerow(col_names) 319 | writer.writerow(attendance) 320 | csvFile1.close() 321 | with open("Attendance\Attendance_" + date + ".csv", 'r') as csvFile1: 322 | reader1 = csv.reader(csvFile1) 323 | for lines in reader1: 324 | i = i + 1 325 | if (i > 1): 326 | if (i % 2 != 0): 327 | iidd = str(lines[0]) + ' ' 328 | tv.insert('', 0, text=iidd, values=(str(lines[2]), str(lines[4]), str(lines[6]))) 329 | csvFile1.close() 330 | cam.release() 331 | cv2.destroyAllWindows() 332 | 333 | ######################################## USED STUFFS ############################################ 334 | 335 | global key 336 | key = '' 337 | 338 | ts = time.time() 339 | date = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y') 340 | day,month,year=date.split("-") 341 | 342 | mont={'01':'January', 343 | '02':'February', 344 | '03':'March', 345 | '04':'April', 346 | '05':'May', 347 | '06':'June', 348 | '07':'July', 349 | '08':'August', 350 | '09':'September', 351 | '10':'October', 352 | '11':'November', 353 | '12':'December' 354 | } 355 | 356 | ######################################## GUI FRONT-END ########################################### 357 | 358 | window = tk.Tk() 359 | window.geometry("1280x720") 360 | window.resizable(True,False) 361 | window.title("Attendance System") 362 | window.configure(background='#262523') 363 | 364 | frame1 = tk.Frame(window, bg="#00aeff") 365 | frame1.place(relx=0.11, rely=0.17, relwidth=0.39, relheight=0.80) 366 | 367 | frame2 = tk.Frame(window, bg="#00aeff") 368 | frame2.place(relx=0.51, rely=0.17, relwidth=0.38, relheight=0.80) 369 | 370 | message3 = tk.Label(window, text="Face Recognition Based Attendance System" ,fg="white",bg="#262523" ,width=55 ,height=1,font=('times', 29, ' bold ')) 371 | message3.place(x=10, y=10) 372 | 373 | frame3 = tk.Frame(window, bg="#c4c6ce") 374 | frame3.place(relx=0.52, rely=0.09, relwidth=0.09, relheight=0.07) 375 | 376 | frame4 = tk.Frame(window, bg="#c4c6ce") 377 | frame4.place(relx=0.36, rely=0.09, relwidth=0.16, relheight=0.07) 378 | 379 | datef = tk.Label(frame4, text = day+"-"+mont[month]+"-"+year+" | ", fg="orange",bg="#262523" ,width=55 ,height=1,font=('times', 22, ' bold ')) 380 | datef.pack(fill='both',expand=1) 381 | 382 | clock = tk.Label(frame3,fg="orange",bg="#262523" ,width=55 ,height=1,font=('times', 22, ' bold ')) 383 | clock.pack(fill='both',expand=1) 384 | tick() 385 | 386 | head2 = tk.Label(frame2, text=" For New Registrations ", fg="black",bg="#3ece48" ,font=('times', 17, ' bold ') ) 387 | head2.grid(row=0,column=0) 388 | 389 | head1 = tk.Label(frame1, text=" For Already Registered ", fg="black",bg="#3ece48" ,font=('times', 17, ' bold ') ) 390 | head1.place(x=0,y=0) 391 | 392 | lbl = tk.Label(frame2, text="Enter ID",width=20 ,height=1 ,fg="black" ,bg="#00aeff" ,font=('times', 17, ' bold ') ) 393 | lbl.place(x=80, y=55) 394 | 395 | txt = tk.Entry(frame2,width=32 ,fg="black",font=('times', 15, ' bold ')) 396 | txt.place(x=30, y=88) 397 | 398 | lbl2 = tk.Label(frame2, text="Enter Name",width=20 ,fg="black" ,bg="#00aeff" ,font=('times', 17, ' bold ')) 399 | lbl2.place(x=80, y=140) 400 | 401 | txt2 = tk.Entry(frame2,width=32 ,fg="black",font=('times', 15, ' bold ') ) 402 | txt2.place(x=30, y=173) 403 | 404 | message1 = tk.Label(frame2, text="1)Take Images >>> 2)Save Profile" ,bg="#00aeff" ,fg="black" ,width=39 ,height=1, activebackground = "yellow" ,font=('times', 15, ' bold ')) 405 | message1.place(x=7, y=230) 406 | 407 | message = tk.Label(frame2, text="" ,bg="#00aeff" ,fg="black" ,width=39,height=1, activebackground = "yellow" ,font=('times', 16, ' bold ')) 408 | message.place(x=7, y=450) 409 | 410 | lbl3 = tk.Label(frame1, text="Attendance",width=20 ,fg="black" ,bg="#00aeff" ,height=1 ,font=('times', 17, ' bold ')) 411 | lbl3.place(x=100, y=115) 412 | 413 | res=0 414 | exists = os.path.isfile("StudentDetails\StudentDetails.csv") 415 | if exists: 416 | with open("StudentDetails\StudentDetails.csv", 'r') as csvFile1: 417 | reader1 = csv.reader(csvFile1) 418 | for l in reader1: 419 | res = res + 1 420 | res = (res // 2) - 1 421 | csvFile1.close() 422 | else: 423 | res = 0 424 | message.configure(text='Total Registrations till now : '+str(res)) 425 | 426 | ##################### MENUBAR ################################# 427 | 428 | menubar = tk.Menu(window,relief='ridge') 429 | filemenu = tk.Menu(menubar,tearoff=0) 430 | filemenu.add_command(label='Change Password', command = change_pass) 431 | filemenu.add_command(label='Contact Us', command = contact) 432 | filemenu.add_command(label='Exit',command = window.destroy) 433 | menubar.add_cascade(label='Help',font=('times', 29, ' bold '),menu=filemenu) 434 | 435 | ################## TREEVIEW ATTENDANCE TABLE #################### 436 | 437 | tv= ttk.Treeview(frame1,height =13,columns = ('name','date','time')) 438 | tv.column('#0',width=82) 439 | tv.column('name',width=130) 440 | tv.column('date',width=133) 441 | tv.column('time',width=133) 442 | tv.grid(row=2,column=0,padx=(0,0),pady=(150,0),columnspan=4) 443 | tv.heading('#0',text ='ID') 444 | tv.heading('name',text ='NAME') 445 | tv.heading('date',text ='DATE') 446 | tv.heading('time',text ='TIME') 447 | 448 | ###################### SCROLLBAR ################################ 449 | 450 | scroll=ttk.Scrollbar(frame1,orient='vertical',command=tv.yview) 451 | scroll.grid(row=2,column=4,padx=(0,100),pady=(150,0),sticky='ns') 452 | tv.configure(yscrollcommand=scroll.set) 453 | 454 | ###################### BUTTONS ################################## 455 | 456 | clearButton = tk.Button(frame2, text="Clear", command=clear ,fg="black" ,bg="#ea2a2a" ,width=11 ,activebackground = "white" ,font=('times', 11, ' bold ')) 457 | clearButton.place(x=335, y=86) 458 | clearButton2 = tk.Button(frame2, text="Clear", command=clear2 ,fg="black" ,bg="#ea2a2a" ,width=11 , activebackground = "white" ,font=('times', 11, ' bold ')) 459 | clearButton2.place(x=335, y=172) 460 | takeImg = tk.Button(frame2, text="Take Images", command=TakeImages ,fg="white" ,bg="blue" ,width=34 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 461 | takeImg.place(x=30, y=300) 462 | trainImg = tk.Button(frame2, text="Save Profile", command=psw ,fg="white" ,bg="blue" ,width=34 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 463 | trainImg.place(x=30, y=380) 464 | trackImg = tk.Button(frame1, text="Take Attendance", command=TrackImages ,fg="black" ,bg="yellow" ,width=35 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 465 | trackImg.place(x=30,y=50) 466 | quitWindow = tk.Button(frame1, text="Quit", command=window.destroy ,fg="black" ,bg="red" ,width=35 ,height=1, activebackground = "white" ,font=('times', 15, ' bold ')) 467 | quitWindow.place(x=30, y=450) 468 | 469 | ##################### END ###################################### 470 | 471 | window.configure(menu=menubar) 472 | window.mainloop() 473 | 474 | #################################################################################################### 475 | -------------------------------------------------------------------------------- /FaceAttendance/requirements.txt: -------------------------------------------------------------------------------- 1 | tk-tools 2 | opencv-contrib-python 3 | datetime 4 | pytest-shutil 5 | python-csv 6 | numpy 7 | pillow 8 | pandas 9 | times -------------------------------------------------------------------------------- /Marksheet update using tkinter simple project/Marksheet.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BarathkumarJK/Projects/7ce9d078634207925fdc2c0ba07f4b3225d2c4c4/Marksheet update using tkinter simple project/Marksheet.xlsx -------------------------------------------------------------------------------- /Marksheet update using tkinter simple project/mainapp.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | import pandas as pd 3 | 4 | def submit_fields(): 5 | path = 'D:\Projects\simple projects\Marksheet update project\Marksheet.xlsx' 6 | df1 = pd.read_excel(path) 7 | columns = ['Roll No', 'Name', 'Maths', 'COA', 'DLD', 'FAIDS', 'OOPJ', 'DS'] 8 | data = {col: pd.Series(entry.get()) for col, entry in zip(columns, entries)} 9 | 10 | df2 = df1.append(pd.DataFrame(data), ignore_index=True) 11 | df2.to_excel(path, index=False) 12 | clear_entries() 13 | 14 | def clear_entries(): 15 | for entry in entries: 16 | entry.delete(0, END) 17 | 18 | app = Tk() 19 | app.title("Marksheet Generator") 20 | app.geometry("900x600") 21 | 22 | labels = ['Roll No', 'Name', 'Maths', 'COA', 'DLD', 'FAIDS', 'OOPJ', 'DS'] 23 | entries = [] 24 | 25 | for row, label in enumerate(labels, start=3): 26 | Label(app, text=label).grid(row=row, column=0, padx=5) 27 | entry = Entry(app) 28 | entry.grid(row=row, column=1) 29 | entries.append(entry) 30 | 31 | Button(app, text='Quit', command=app.quit).grid(row=11, column=0, pady=10) 32 | Button(app, text='Submit', command=submit_fields).grid(row=11, column=2, pady=4) 33 | 34 | mainloop() 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Projects 2 | In This repo I will add my simple projects source code . 3 | --------------------------------------------------------------------------------