This OpenCV C++ Tutorial is about solving mazes using Simple Morphological transformation.
The script works for only perfect mazes, i.e the maze which has one and only one unique solution,no subsections,no circular area and no open areas.These kind of perfect mazes can be generated using online maze generation tools.
Lets take this simple maze as test image:
The steps for Solving Perfect Mazes are:
1. Load the Source Image.
2. Convert the given image into binary image.
3. Extract Counters from it.
Now the External Counter for a perfect maze is 2(because the perfect maze has only 2 walls).
So if the given Maze is perfect,it would have 2 External Counters,then proceed with the logic below
4. So select any one wall, and dilate and erode the ways by the same amount of pixels.
5.Subtract the eroded image from the dilated image to get the final output i.e the solution of the maze.
//Opencv C++ Program to solve mazes using mathematical morphology #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <cmath> #include <iostream> using namespace cv; using namespace std; int main() { Mat src = imread("C:\\Users\\arjun\\Desktop\\opencv-maze-generator.png"); if( !src.data ) { printf("Error loading src \n"); return -1;} //Convert the given image into Binary Image Mat bw; cvtColor(src, bw, CV_BGR2GRAY); threshold(bw, bw, 10, 255, CV_THRESH_BINARY_INV); //Detect Contours in an Image vector<std::vector<cv::Point> > contours; findContours(bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); if (contours.size() != 2) { // "Perfect maze" should have 2 walls std::cout << "This is not a 'perfect maze' with just 2 walls!" << std::endl; return -1; } Mat path = Mat::zeros(src.size(), CV_8UC1); drawContours(path, contours, 0, CV_RGB(255,255,255), CV_FILLED); //Dilate the Image Mat kernel = Mat::ones(21, 21, CV_8UC1); dilate(path, path, kernel); //Erode the Image Mat path_erode; erode(path, path_erode, kernel); //Subtract Eroded Image from the Dilate One absdiff(path, path_erode, path); //Draw the Path by Red Color vector<Mat> channels; split(src, channels); channels[0] &= ~path; channels[1] &= ~path; channels[2] |= path; Mat dst; merge(channels, dst); imshow("solution", dst); waitKey(0); return 0; }
1. Input :
2. After converting the given Image to Binary :
3. After detecting Contours:
4. After Dilation:
5. After Appying Erosion:
6. After Subtracting Dilated Image from the Eroded:
7. Tracing the path with red Color(Final Output):