社区
C++ 语言
帖子详情
使用opencv2.4.9做图像连通域的问题
princeqy
2015-11-24 09:07:03
使用opencv2.4.9做图像连通域,用的是四连通,采用的是two-pass,为什么有时候一个字符会分成两个连通域,也就是说一个字符的连通域从中间断开了,希望知道的大神能告知
...全文
304
2
打赏
收藏
使用opencv2.4.9做图像连通域的问题
使用opencv2.4.9做图像连通域,用的是四连通,采用的是two-pass,为什么有时候一个字符会分成两个连通域,也就是说一个字符的连通域从中间断开了,希望知道的大神能告知
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用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; }
Open
cv2
.
4.9
源码分析——MSER
最大稳定极值区域(MSER-Maximally Stable Extremal Regions)可以用于
图像
的斑点区域检测。该算法最早是由Matas等人于2002年提出,它是基于分水岭的概念。 MSER的基本原理是对一幅灰度
图像
(灰度值为0~255)取阈值进行二值化处理,阈值从0到255依次递增。阈值的递增类似于分水岭算法中的水面的上升,随着水面的上升,有一些较矮的丘陵会被淹没,如果从天空往下看
利用种子填充法对二值
图像
进行
连通域
标记
利用种子填充法对二值
图像
进行
连通域
标记 最近一直在用
Open
CV
做
设计,其中有一个设计环节是设计检测二值
图像
的
连通域
及其特征,在网上搜了一下算法,看到了有two-pass法和种子填充法两种。两种经典的方法都编程实现过,个人觉得,种子填充法比较直观,不需要像two-pass法那么绕,只需要遍历一遍
图像
,而且还能顺带计算面积和外接矩形框, 种子填充法原理 关于种子填充法的详细原理可以参考O
【
图像
处理】利用种子填充法对二值
图像
进行
连通域
标记-计算目标中心位置方法2
种子填充法原理 关于种子填充法的详细原理可以参考
Open
CV_连通区域分析(Connected Component Analysis/Labeling) 大致算法如下: 设二值化
图像
A中,像素值为255的点是前景,为0的点是背景。A(x, y)为坐标(x, y)处的像素值,遍历
图像
的每个像素: 1、 如果像素值不等于255,则继续访问下一个元素。 2、 如果像素值为A(x
Open
CV各模块函数
使用
实例(7)--其他
图像
变换(Miscellaneous Image Transformations)
在
open
cv的imgproc模块中,其他
图像
变换(Miscellaneous Image transformations)模块中包含了一些
图像
变换的小工具。比如阈值变换,线性融合,漫灌式充填等,这些工具对于处理
图像
的细节可以起到意想不到的效果。本节介绍这些函数的用法实例,有些来自
open
cv的帮助资料(翻译),实例为实际
图像
处理效果分析。程序实现为vs 2010 c++。
使用
open
cv2
.
4.9
版和4.3.0以前版本的源码移植。文章主要针对有一定
图像
处理经验的读者。 (1)、voi...
Open
CV学习(9) 分水岭算法(3)
本教程我学习一下
open
cv中分水岭算法的具体实现方式。 原始
图像
和Mark
图像
,它们的大小都是32*32,分水岭算法的结果是得到两个
连通域
的轮廓图。 原始
图像
:(原始
图像
必须是3通道
图像
) Mark
图像
: 结果
图像
: 初始的mark
图像
数据如下,黄色的部分为我们的第一个mark区域,值为255,第二个区域为褐红色的区域,值为128,第三个绿色的区域,值为64。 ...
C++ 语言
64,652
社区成员
250,508
社区内容
发帖
与我相关
我的任务
C++ 语言
C++ 语言相关问题讨论,技术干货分享,前沿动态等
复制链接
扫一扫
分享
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++
技术论坛(原bbs)
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
请不要发布与C++技术无关的贴子
请不要发布与技术无关的招聘、广告的帖子
请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下
试试用AI创作助手写篇文章吧
+ 用AI写文章