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):






