-
-
Notifications
You must be signed in to change notification settings - Fork 347
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #799 from abckhush/patch-1
[Project Addition]: Real Time Sudoku Solver
- Loading branch information
Showing
13 changed files
with
800 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Real Time Sudoku Solver | ||
|
||
1. In the Models Folder, Run the `sudoku testing.ipynb` file. You need not run other files. This file itself will do all the work for you. | ||
2. Make sure your webcam is connected and all the requirements is satisfied. | ||
3. As soon as the window opens, show your sudoku image (as shown in the video demonstration). | ||
4. Your sudoku is solved! |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
455 changes: 455 additions & 0 deletions
455
Real Time Sudoku Solver/Model/RealTimeSudokuSolver.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"%matplotlib inline" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stderr", | ||
"output_type": "stream", | ||
"text": [ | ||
"Using TensorFlow backend.\n" | ||
] | ||
}, | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"importing Jupyter notebook from sudokuSolver.ipynb\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"import cv2\n", | ||
"import numpy as np\n", | ||
"import keras\n", | ||
"from tensorflow.keras.models import Sequential\n", | ||
"from tensorflow.keras.layers import Dense, Dropout, Flatten\n", | ||
"from tensorflow.keras.layers import Conv2D, MaxPooling2D\n", | ||
"from tensorflow.keras import backend as K\n", | ||
"\n", | ||
"import import_ipynb\n", | ||
"%run RealTimeSudokuSolver.ipynb\n", | ||
"%run sudokuSolver.ipynb\n", | ||
"# --->import RealTimeSudokuSolve\n", | ||
"from scipy import ndimage\n", | ||
"import math\n", | ||
"# --->import sudokuSolver\n", | ||
"import copy\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# This is the main file. Just run all cells in this file\n", | ||
"# you need not run other files. This file itself will do all the work for you.\n", | ||
"\n", | ||
"# I have trained the CNN model and saved the architecture in digitRecognition.h5 file.\n", | ||
"\n", | ||
"def showImage(img, name, width, height):\n", | ||
" new_image = np.copy(img)\n", | ||
" new_image = cv2.resize(new_image, (width, height))\n", | ||
" cv2.imshow(name, new_image)\n", | ||
"\n", | ||
"# Load and set up Camera\n", | ||
"cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)\n", | ||
"cap.set(3, 1280) # HD Camera\n", | ||
"cap.set(4, 720)\n", | ||
"\n", | ||
"# Loading model (Load weights and configuration seperately to speed up model and predictions)\n", | ||
"input_shape = (28, 28, 1)\n", | ||
"num_classes = 9\n", | ||
"model = Sequential()\n", | ||
"model.add(Conv2D(32, kernel_size=(3, 3),\n", | ||
" activation='relu',\n", | ||
" input_shape=input_shape))\n", | ||
"model.add(Conv2D(64, (3, 3), activation='relu'))\n", | ||
"model.add(MaxPooling2D(pool_size=(2, 2)))\n", | ||
"model.add(Dropout(0.25))\n", | ||
"model.add(Flatten())\n", | ||
"model.add(Dense(128, activation='relu'))\n", | ||
"model.add(Dropout(0.5))\n", | ||
"model.add(Dense(num_classes, activation='softmax'))\n", | ||
"\n", | ||
"# Load weights from pre-trained model. This model is trained in digitRecognition.py\n", | ||
"model.load_weights(\"digitRecognition.h5\") \n", | ||
"\n", | ||
"old_sudoku = None # Used to compare new sudoku or old sudoku\n", | ||
"while(True):\n", | ||
" ret, frame = cap.read() # Read the frame\n", | ||
" if ret == True:\n", | ||
" \n", | ||
" # RealTimeSudokuSolver.recognize_sudoku_and_solve\n", | ||
" sudoku_frame = recognize_sudoku_and_solve(frame, model, old_sudoku) \n", | ||
" showImage(sudoku_frame, \"Real Time Sudoku Solver\", 1066, 600)\n", | ||
" if cv2.waitKey(1) == ord('q'): # Hit q if you want to stop the camera\n", | ||
" break\n", | ||
" else:\n", | ||
" break\n", | ||
"\n", | ||
"cap.release()\n", | ||
"cv2.destroyAllWindows()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.7.5" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class EntryData:\n", | ||
" def __init__(self, r, c, n):\n", | ||
" self.row = r\n", | ||
" self.col = c\n", | ||
" self.choices = n\n", | ||
"\n", | ||
" def set_data(self, r, c, n):\n", | ||
" self.row = r\n", | ||
" self.col = c\n", | ||
" self.choices = n\n", | ||
" \n", | ||
"# Solve Sudoku using Best-first search\n", | ||
"def solve_sudoku(matrix):\n", | ||
" cont = [True]\n", | ||
" # See if it is even possible to have a solution\n", | ||
" for i in range(9):\n", | ||
" for j in range(9):\n", | ||
" if not can_be_correct(matrix, i, j): # If it is not possible, stop\n", | ||
" return\n", | ||
" sudoku_helper(matrix, cont) # Otherwise try to solve the Sudoku puzzle\n", | ||
"\n", | ||
"# Helper function - The heart of Best First Search\n", | ||
"def sudoku_helper(matrix, cont):\n", | ||
" if not cont[0]: # Stopping point 1\n", | ||
" return\n", | ||
"\n", | ||
" # Find the best entry (The one with the least possibilities)\n", | ||
" best_candidate = EntryData(-1, -1, 100)\n", | ||
" for i in range(9):\n", | ||
" for j in range(9):\n", | ||
" if matrix[i][j] == 0: # If it is unfilled\n", | ||
" num_choices = count_choices(matrix, i, j)\n", | ||
" if best_candidate.choices > num_choices:\n", | ||
" best_candidate.set_data(i, j, num_choices)\n", | ||
"\n", | ||
" # If didn't find any choices, it means...\n", | ||
" if best_candidate.choices == 100: # Has filled all board, Best-First Search done! Note, whether we have a solution or not depends on whether all Board is non-zero\n", | ||
" cont[0] = False # Set the flag so that the rest of the recursive calls can stop at \"stopping points\"\n", | ||
" return\n", | ||
"\n", | ||
" row = best_candidate.row\n", | ||
" col = best_candidate.col\n", | ||
"\n", | ||
" # If found the best candidate, try to fill 1-9\n", | ||
" for j in range(1, 10):\n", | ||
" if not cont[0]: # Stopping point 2\n", | ||
" return\n", | ||
"\n", | ||
" matrix[row][col] = j\n", | ||
"\n", | ||
" if can_be_correct(matrix, row, col):\n", | ||
" sudoku_helper(matrix, cont)\n", | ||
"\n", | ||
" if not cont[0]: # Stopping point 3\n", | ||
" return\n", | ||
" matrix[row][col] = 0 # Backtrack, mark the current cell empty again\n", | ||
" \n", | ||
"\n", | ||
"# Count the number of choices haven't been used\n", | ||
"def count_choices(matrix, i, j):\n", | ||
" can_pick = [True,True,True,True,True,True,True,True,True,True]; # From 0 to 9 - drop 0\n", | ||
" \n", | ||
" # Check row\n", | ||
" for k in range(9):\n", | ||
" can_pick[matrix[i][k]] = False\n", | ||
"\n", | ||
" # Check col\n", | ||
" for k in range(9):\n", | ||
" can_pick[matrix[k][j]] = False;\n", | ||
"\n", | ||
" # Check 3x3 square\n", | ||
" r = i // 3\n", | ||
" c = j // 3\n", | ||
" for row in range(r*3, r*3+3):\n", | ||
" for col in range(c*3, c*3+3):\n", | ||
" can_pick[matrix[row][col]] = False\n", | ||
"\n", | ||
" # Count\n", | ||
" count = 0\n", | ||
" for k in range(1, 10): # 1 to 9\n", | ||
" if can_pick[k]:\n", | ||
" count += 1\n", | ||
"\n", | ||
" return count\n", | ||
"\n", | ||
"# Return true if the current cell doesn't create any violation\n", | ||
"def can_be_correct(matrix, row, col):\n", | ||
" \n", | ||
" # Check row\n", | ||
" for c in range(9):\n", | ||
" if matrix[row][col] != 0 and col != c and matrix[row][col] == matrix[row][c]:\n", | ||
" return False\n", | ||
"\n", | ||
" # Check column\n", | ||
" for r in range(9):\n", | ||
" if matrix[row][col] != 0 and row != r and matrix[row][col] == matrix[r][col]:\n", | ||
" return False\n", | ||
"\n", | ||
" # Check 3x3 square\n", | ||
" r = row // 3\n", | ||
" c = col // 3\n", | ||
" for i in range(r*3, r*3+3):\n", | ||
" for j in range(c*3, c*3+3):\n", | ||
" if row != i and col != j and matrix[i][j] != 0 and matrix[i][j] == matrix[row][col]:\n", | ||
" return False\n", | ||
" \n", | ||
" return True\n", | ||
"\n", | ||
"# Return true if the whole board has been occupied by some non-zero number\n", | ||
"# If this happens, the current board is the solution to the original Sudoku\n", | ||
"def all_board_non_zero(matrix):\n", | ||
" for i in range(9):\n", | ||
" for j in range(9):\n", | ||
" if matrix[i][j] == 0:\n", | ||
" return False\n", | ||
" return True" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.7.5" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Real Time Sudoku Solver | ||
|
||
## 🎯 **Goal** | ||
This project aims to develop an application that can solve standard Sudoku puzzles in real time using image processing and machine learning techniques, specifically Convolutional Neural Networks (CNN). The application captures video to identify the Sudoku board, solve the puzzle, and writes the solution on the board itself. | ||
|
||
## 🧵 **Dataset** | ||
The application starts by capturing video to identify the Sudoku board in real time. It processes the captured image to detect and recognize the numbers on the board, solves the puzzle, and overlays the solution back onto the original board. | ||
|
||
If you want to try training the Convolution Network on your computer, you will need to download Chars74K Dataset http://www.ee.surrey.ac.uk/CVSSP/demos/chars74k/, takes images 1-9 (We only need 1-9) and put them in folders "1", "2", ..., "9" respectively in the same directory with where you put all my Python files. After that, just run digitRecognition.py | ||
|
||
## 🧾 **Description** | ||
This project leverages image processing and machine learning to create a real-time Sudoku solver. The core functionality involves using a Convolutional Neural Network (CNN) to recognize the digits on the Sudoku board from a live video feed. The recognized digits are then processed to solve the Sudoku puzzle, and the solution is displayed directly on the video feed. This application combines the power of computer vision and deep learning to deliver a seamless and interactive Sudoku-solving experience. | ||
|
||
## 🧮 **What I had done!** | ||
1. Video Capture and Preprocessing: Implemented video capture to continuously get frames from the webcam. Applied image preprocessing techniques to enhance the quality of the captured frames for better digit recognition. | ||
2. Digit Recognition: Trained a Convolutional Neural Network (CNN) model to recognize digits from the preprocessed images. Integrated the trained model into the application to identify digits on the Sudoku board. | ||
3. Sudoku Solver: Developed an algorithm to solve the Sudoku puzzle using the recognized digits. Ensured the solution is accurate and efficient. | ||
4. Overlay Solution: Implemented a method to overlay the solved Sudoku puzzle back onto the original video feed, displaying the solution in real time. | ||
|
||
The step by step images are provided in the Images Folder. | ||
|
||
## 📚 **Libraries Needed** | ||
1. keras==2.3.1 | ||
2. numpy==1.22.0 | ||
3. opencv-python==4.2.0.34 | ||
4. scipy==1.4.1 | ||
5. import-ipynb==0.1.3 | ||
|
||
## **How To Start?** | ||
`sudoku testing.ipynb` is the entry of the application. Just run the file and show the sudoku image as soon as the window opens. Make sure to have all the requirements. | ||
|
||
## 📢 **Conclusion** | ||
The real-time Sudoku solver successfully combines image processing and machine learning techniques to deliver an interactive and efficient solution for solving Sudoku puzzles. The application demonstrates high accuracy in digit recognition and puzzle-solving, thanks to the trained CNN model. | ||
By leveraging CNN for digit recognition and combining it with efficient puzzle-solving algorithms, the project provides a seamless user experience in solving Sudoku puzzles directly from a live video feed. The accuracy and efficiency of the solution make it a valuable tool for Sudoku enthusiasts and showcase the potential of integrating image processing and machine learning for real-time applications. | ||
|
||
## Video Demonstration | ||
![Real Time Sudoku Solver](https://github.com/abckhush/DL-Simplified/assets/127378920/6485b261-b624-46e5-8947-61c13390fe11) | ||
|
||
## ✒️ **Your Signature** | ||
Khushi Kalra <br> | ||
<a href="https://www.github.com/abckhush">Github</a> <br> | ||
<a href="https://www.linkedin.com/in/kalrakhushi/">LinkedIn</a> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
keras==2.3.1 | ||
numpy==1.22.0 | ||
opencv-python==4.2.0.34 | ||
scipy==1.4.1 | ||
import-ipynb==0.1.3 |