fanfuhan OpenCV 教學047 ~ opencv-047-二值圖像連通組件狀態統計[八方鍊碼:元件標記/尋找/計算(計數)/統計參數]


資料來源: https://fanfuhan.github.io/

https://fanfuhan.github.io/2019/04/15/opencv-047/

GITHUB:https://github.com/jash-git/fanfuhan_ML_OpenCV

C++

#include 
#include 

using namespace std;
using namespace cv;

RNG rng(12345);

void componentwithstats_demo(Mat &image);

/*
 * 二值圖像連通組件狀態統計
 */
int main() {
    Mat src = imread("../images/rice.png");
    if (src.empty()) {
        cout << "could not load image.." << endl;
    }
    imshow("input", src);

    componentwithstats_demo(src);

    waitKey(0);
    return 0;
}

void componentwithstats_demo(Mat &image) {
    // extract labels
    Mat gray, binary;
    GaussianBlur(image, image, Size(3, 3), 0);
    cvtColor(image, gray, COLOR_BGR2GRAY);
    threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
    Mat labels = Mat::zeros(image.size(), CV_32S);
    Mat stats, centroids;
    int num_labels = connectedComponentsWithStats(binary, labels, stats, centroids, 8, 4);
    cout << "total labels : " << num_labels - 1 << endl;
    vector colors(num_labels);

    // 背景顏色
    colors[0] = Vec3b(0, 0, 0);

    // 目標顏色
    for (int i = 1; i < num_labels; ++i) {
        colors[i] = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
    }

    // 抽取統計信息
    Mat dst = image.clone();
    for (int i = 1; i < num_labels; ++i) {
        // 中心位置
        int cx = centroids.at(i, 0);
        int cy = centroids.at(i, 1);

        // 統計信息
        int x = stats.at(i, CC_STAT_LEFT);
        int y = stats.at(i, CC_STAT_TOP);
        int w = stats.at(i, CC_STAT_WIDTH);
        int h = stats.at(i, CC_STAT_HEIGHT);
        int area = stats.at(i, CC_STAT_AREA);

        // 中心位置繪製
        circle(dst, Point(cx, cy), 2, Scalar(0, 255, 0), 2);

        // 外接矩形
        Rect rect(x, y, w, h);
        rectangle(dst, rect, colors[i]);
        putText(dst, format("num:%d", i), Point(x, y), FONT_HERSHEY_SIMPLEX,
                .5, Scalar(0, 0, 255), 1);
        printf("num : %d, rice area : %d\n", i, area);
    }

    imshow("result", dst);
}

Python

import cv2 as cv
import numpy as np


def connected_components_stats_demo(src):
    src = cv.GaussianBlur(src, (3, 3), 0)
    gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    cv.imshow("binary", binary)

    num_labels, labels, stats, centers = cv.connectedComponentsWithStats(binary, connectivity=8, ltype=cv.CV_32S)
    colors = []
    for i in range(num_labels):
        b = np.random.randint(0, 256)
        g = np.random.randint(0, 256)
        r = np.random.randint(0, 256)
        colors.append((b, g, r))

    colors[0] = (0, 0, 0)
    image = np.copy(src)
    for t in range(1, num_labels, 1):
        x, y, w, h, area = stats[t]
        cx, cy = centers[t]
        cv.circle(image, (np.int32(cx), np.int32(cy)), 2, (0, 255, 0), 2, 8, 0)
        cv.rectangle(image, (x, y), (x+w, y+h), colors[t], 1, 8, 0)
        cv.putText(image, "num:" + str(t), (x, y), cv.FONT_HERSHEY_SIMPLEX, .5, (0, 0, 255), 1);
        print("label index %d, area of the label : %d"%(t, area))

    cv.imshow("colored labels", image)
    cv.imwrite("D:/labels.png", image)
    print("total rice : ", num_labels - 1)


input = cv.imread("D:/images/rice.png")
connected_components_stats_demo(input)
cv.waitKey(0)
cv.destroyAllWindows()

相關文章