使用opencv2.4.9做图像连通域的问题

princeqy 2015-11-24 09:07:03
使用opencv2.4.9做图像连通域,用的是四连通,采用的是two-pass,为什么有时候一个字符会分成两个连通域,也就是说一个字符的连通域从中间断开了,希望知道的大神能告知
...全文
304 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2015-11-25
  • 打赏
  • 举报
回复
比如:这个字符?
princeqy 2015-11-25
  • 打赏
  • 举报
回复
比如说一个数字“6”,用opencv的四连通有时候会出现两个连通域,代码如下: void Two_Pass(const cv::Mat& binImg, cv::Mat& lableImg) //两遍扫描法 { if (binImg.empty() || binImg.type() != CV_8UC1) { return; } // 第一个通路 lableImg.release(); binImg.convertTo(lableImg, CV_32SC1); int label = 1; std::vector<int> labelSet; labelSet.push_back(0); labelSet.push_back(1); int rows = binImg.rows - 1; int cols = binImg.cols - 1; for (int i = 1; i < rows; i++) { int* data_preRow = lableImg.ptr<int>(i-1); int* data_curRow = lableImg.ptr<int>(i); for (int j = 1; j < cols; j++) { if (data_curRow[j] == 1) { std::vector<int> neighborLabels; neighborLabels.reserve(2); int leftPixel = data_curRow[j-1]; int upPixel = data_preRow[j]; if ( leftPixel > 1) { neighborLabels.push_back(leftPixel); } if (upPixel > 1) { neighborLabels.push_back(upPixel); } if (neighborLabels.empty()) { labelSet.push_back(++label); // 不连通,标签+1 data_curRow[j] = label; labelSet[label] = label; } else { std::sort(neighborLabels.begin(), neighborLabels.end()); int smallestLabel = neighborLabels[0]; data_curRow[j] = smallestLabel; // 保存最小等价表 for (size_t k = 1; k < neighborLabels.size(); k++) { int tempLabel = neighborLabels[k]; int& oldSmallestLabel = labelSet[tempLabel]; if (oldSmallestLabel > smallestLabel) { labelSet[oldSmallestLabel] = smallestLabel; oldSmallestLabel = smallestLabel; } else if (oldSmallestLabel < smallestLabel) { labelSet[smallestLabel] = oldSmallestLabel; } } } } } } // 更新等价对列表 // 将最小标号给重复区域 for (size_t i = 2; i < labelSet.size(); i++) { int curLabel = labelSet[i]; int preLabel = labelSet[curLabel]; while (preLabel != curLabel) { curLabel = preLabel; preLabel = labelSet[preLabel]; } labelSet[i] = curLabel; } ; for (int i = 0; i < rows; i++) { int* data = lableImg.ptr<int>(i); for (int j = 0; j < cols; j++) { int& pixelLabel = data[j]; pixelLabel = labelSet[pixelLabel]; } } } //彩色显示 cv::Scalar GetRandomColor() { uchar r = 255 * (rand()/(1.0 + RAND_MAX)); uchar g = 255 * (rand()/(1.0 + RAND_MAX)); uchar b = 255 * (rand()/(1.0 + RAND_MAX)); return cv::Scalar(b,g,r); } void LabelColor(const cv::Mat& labelImg, cv::Mat& colorLabelImg) { if (labelImg.empty() || labelImg.type() != CV_32SC1) { return; } std::map<int, cv::Scalar> colors; int rows = labelImg.rows; int cols = labelImg.cols; colorLabelImg.release(); colorLabelImg.create(rows, cols, CV_8UC3); colorLabelImg = cv::Scalar::all(0); for (int i = 0; i < rows; i++) { const int* data_src = (int*)labelImg.ptr<int>(i); uchar* data_dst = colorLabelImg.ptr<uchar>(i); for (int j = 0; j < cols; j++) { int pixelValue = data_src[j]; if (pixelValue > 1) { if (colors.count(pixelValue) <= 0) { colors[pixelValue] = GetRandomColor(); } cv::Scalar color = colors[pixelValue]; *data_dst++ = color[0]; *data_dst++ = color[1]; *data_dst++ = color[2]; } else { data_dst++; data_dst++; data_dst++; } } } } int main() { cv::Mat binImage = cv::imread("test.jpg", 0); cv::threshold(binImage, binImage, 50, 1, CV_THRESH_BINARY_INV); cv::Mat labelImg; Two_Pass(binImage, labelImg, num); //Seed_Filling(binImage, labelImg); //彩色显示 cv::Mat colorLabelImg; LabelColor(labelImg, colorLabelImg); cv::imshow("colorImg", colorLabelImg); /* //灰度显示 cv::Mat grayImg; labelImg *= 10; labelImg.convertTo(grayImg, CV_8UC1); cv::imshow("labelImg", grayImg); */ cv::waitKey(0); return 0; }

64,652

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧