//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); } } } }