环境:OpenCV3.2.0 + VS2015
1、快速连通区域分析(可用于降噪)
cv::connectedComponents():
仅创建了一个标记图(图中不同连通域使用不同的标记,和原图宽高一致)
cv::connectedComponentsWithStats():
除了创建标记图以外,还可以返回每个连通区域的重要信息-- bounding box, area, and center of mass( centroid)
void QuickDemo::connectedComponents_demo(Mat & image)
{
cv::Mat grayMat;
cv::cvtColor(image, grayMat, cv::COLOR_BGR2GRAY);
cv::Mat thresholdMat;
cv::threshold(grayMat, thresholdMat, 120, 255, CV_THRESH_BINARY);
int nccomps;
cv::Mat labels, stats, centroids;
nccomps = cv::connectedComponentsWithStats(thresholdMat, labels, stats, centroids);
//参数一:二值图像 labels参数二:标记图(和原图同大)
//stats参数三:nccomps*5的矩阵(每个连通域外接矩形的 x, y, width, heigth, area)
//centroids参数四:每个连通域的质心
printf("原始图像 轮廓数 nccomps = %d n", nccomps);
//初始化颜色表
vector colors(nccomps);
colors[0] = cv::Vec3b(0, 0, 0); //第一个连通域为背景,背景色设为黑色
for (int i = 1; i < nccomps; i++)
{
//用于不同区域的随机彩色
colors[i] = cv::Vec3b(rand() % 256, rand() % 256, rand() % 256);
//colors[i] = cv::Vec3b(255, 255, 255);
//将面积<100的连通域填充为黑色(相当于去除,即与背景同化)
if (stats.at(i, cv::CC_STAT_AREA) < 100)
colors[i] = cv::Vec3b(0, 0, 0);
}
cv::Mat imgColor = cv::Mat::zeros(thresholdMat.size(), CV_8UC3);
for (int y = 0; y < imgColor.rows; y++)
{
for (int x = 0; x < imgColor.cols; x++)
{
int label = labels.at(y, x);
//CV_Assert() 若括号中的表达式值为false,则返回一个错误信息。
CV_Assert(0 <= label && label <= nccomps);
//同个标签则设为同样的颜色
imgColor.at(y, x) = colors[label];
}
}
//统计去除小连通域后图像 的轮廓数
cv::imshow("降噪后imgColor", imgColor);
cv::cvtColor(imgColor, imgColor, cv::COLOR_BGR2GRAY);
nccomps = cv::connectedComponentsWithStats(imgColor, labels, stats, centroids);
printf("处理后图像 轮廓数 nccomps = %d n", nccomps);
cv::imshow("gray", grayMat);
cv::imshow("thresholdMat", thresholdMat);
cv::Mat thresholdMat2;
cv::threshold(imgColor, thresholdMat2, 0, 255, CV_THRESH_BINARY);
cv::imshow("二次阈值", thresholdMat2);
cv::threshold(imgColor, thresholdMat, 0, 255, CV_THRESH_BINARY_INV);
cv::imshow("黑白颠倒后", thresholdMat);
}
2、



