//src:待分割的二值图,最大值为255 //segMat:分割好的每个图片 //算法:判断连通域,有几个连通域就会分割成几个子图片 //用途:手写数字识别中进行无黏连数字的分割 void getConnectedDomain(cv::Mat &src, vector<cv::Mat>& segMat)//segMat为最终结果,存放分割好的每个数字 { int img_row = src.rows; int img_col = src.cols; cv::Mat flag = cv::Mat::zeros(cv::Size(img_col, img_row), CV_8UC1);//标志矩阵,为0则当前像素点未访问过 for (int i = 0; i < img_row; i++) { for (int j = 0; j < img_col; j++) { if (src.ptr<uchar>(i)[j] == 255 && flag.ptr<uchar>(i)[j] == 0) { cv::Mat subMat = cv::Mat::zeros(cv::Size(img_col, img_row), CV_8UC1);//表明子图 stack<cv::Point2f> cd; cd.push(cv::Point2f(j, i)); flag.ptr<uchar>(i)[j] = 1; subMat.ptr<uchar>(i)[j] = 255; while (!cd.empty()) { cv::Point2f tmp = cd.top(); cd.pop(); cv::Point2f p[4];//邻域像素点,这里用的四邻域 p[0] = cv::Point2f(tmp.x - 1 > 0 ? tmp.x - 1 : 0, tmp.y); p[1] = cv::Point2f(tmp.x + 1 < img_col - 1 ? tmp.x + 1 : img_row - 1, tmp.y); p[2] = cv::Point2f(tmp.x, tmp.y - 1 > 0 ? tmp.y - 1 : 0); p[3] = cv::Point2f(tmp.x, tmp.y + 1 < img_row - 1 ? tmp.y + 1 : img_row - 1); for (int m = 0; m < 4; m++) { int x = p[m].y; int y = p[m].x; if (src.ptr<uchar>(x)[y] == 255 && flag.ptr<uchar>(x)[y] == 0)//如果未访问,则入栈,并标记访问过该点 { cd.push(p[m]); flag.ptr<uchar>(x)[y] = 1; subMat.ptr<uchar>(x)[y] = 255; } } } segMat.push_back(subMat); } } } }