函數介紹
輸入必須是單通道圖像,最好是二值圖
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]; // 可以隨手上色