欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

OpenCV中的新函数connectedComponentsWithStats使用(python和c++实例)

程序员文章站 2022-06-12 12:13:29
包括C++和Python代码示例...


函数介绍

输入必须是单通道图像,最好是二值图

int  cv::connectedComponents (
    cv::InputArrayn image,                // input 8-bit single-channel  二值图
    cv::OutputArray labels,               // output label map
    int             connectivity = 8,     // 4- or 8-connected components
    int             ltype        = CV_32S // Output label type (CV_32S or CV_16U)
    );
int  cv::connectedComponentsWithStats (
    cv::InputArrayn image,                // input 8-bit single-channel  二值图
    cv::OutputArray labels,               // output label map
    cv::OutputArray stats,                // N x 5 matrix (CV_32S) of statistics: [x1, y1, width, height, area] 分别是连通域外接矩形和区域面积
    cv::OutputArray centroids,            // Nx2 CV_64F matrix of centroids: [cx0, cy0] 质心坐标
    int             connectivity = 8,     // 4- or 8-connected components
    int             ltype        = CV_32S // Output label type (CV_32S or CV_16U)
    );

C++ 代码示例

  • 参数类型:
num int
labels     = Mat   w × h        CV_32S
stats      = Mat   num × 5      CV_32S
centroids  = Mat   num × 2      CV64F
  • 获取随机色
vector<cv::Vec3b> getColors(int num)
{
    int step = 256 / num;
    vector<int> px;
    for (int i = 0; i < 256; i += step)
        px.push_back(i);

    vector<cv::Vec3b> colors(num);
    for (int j = 0; j < 3; j++)
    {
        random_shuffle(px.begin(), px.end());
        for (int i = 0; i < num; i++)
        {
            colors[i][j] = px[i];
        }
    }
    return colors;
}
  • 给各个连通域上色: 只需要用到标签矩阵 labels
cv::Mat labels, stats, centroids;  //labels CV_32S; stats CV_32S; centroids CV64F;
num = cv::connectedComponentsWithStats(img, labels, stats, centroids);
auto colors = getColors(num);
cv:: Mat drawing= cv::Mat(img.size(), CV_8UC3, cv::Scalar(255, 255, 255));
for (int i = 0; i < img.size().height; i++) {
    for (int j = 0; j < img.size().width; j++) {
        index = labels.at<int>(i, j);
        drawing.at<cv::Vec3b>(i, j) = colors[index];
    }
}
  • 过滤连通域,获取目标区域的标签: 只需要用到状态矩阵 stats (和质心坐标矩阵 centroids)
cv::Mat labels, stats, centroids;  //labels CV_32S; stats CV_32S; centroids CV64F;
num = cv::connectedComponentsWithStats(img, labels, stats, centroids);
int x0, y0, x1, y1, w, h;
std::cout << "符合规则的区域label: "<< std::endl;
for(int k = 0; k < num; k++){
	x0 = centroids.at<double>(k, 0);
	y0 = centroids.at<double>(k, 1);
    x1 = stats.at<int>(k, 0);  
    y1= stats.at<int>(k, 1);
    w = stats.at<int>(k, 2);
    h = stats.at<int>(k, 3);
    printf("Comp %2d: (%3d×%3d) from (%3d,%3d) 质心(%3d,%3d)\n", k, w, h, x1, y1, x0, y0);
    if(条件1 or 条件2 or ...) continue;
    std::cout << k << ", ";
}
std::cout << std::endl;

Python 代码示例

  • 获取随机色
def getColors(n):
    colors = np.zeros((n, 3))
    colors[:, 0] = np.random.permutation(np.linspace(0, 256, n))
    colors[:, 1] = np.random.permutation(colors[:, 0])
    colors[:, 2] = np.random.permutation(colors[:, 1])
    return colors
  • 给各个连通域上色: 只需要用到标签矩阵 labels
ccNum, labels, stats, centroids = cv.connectedComponentsWithStats(img)
colors = getColors(ccNum)
dst = np.ones((img.shape[0], img.shape[1], 3), dtype=np.uint8) * 255
for i in range(ccNum):
    dst[labels == i] = colors[i]
  • 过滤连通域,获取目标区域的标签: 只需要用到状态矩阵 stats (和质心坐标矩阵 centroids)
ccNum, labels, stats, centroids = cv.connectedComponentsWithStats(img)
colors = getColors(ccNum)
print("符合规则的区域label: ")
for i in range(ccNum):
    x1, y1, width, height, count = stats[i]
    x0, y0 = centroids[i]  # 质心坐标
    if 条件1 or 条件2 or ...: 
    	continue
    print("符合规则的区域label: ")
    dst[labels == i] = colors[i];  // 可以随手上色

参考文章: jsxyhelu: OpenCV中的新函数connectedComponentsWithStats使用

本文地址:https://blog.csdn.net/Augurlee/article/details/107068320