python
python的图像连通区域提取使用的函数是measure.label(img)做连通标记,然后具体信息的话通过measure.regionprops获取
import cv2
import time
import numpy as np
from skimage import measure
image = cv.imread("test.jpg")
_, temp_bin = cv2.threshold(image, 126, 255, cv2.THRESH_BINARY)
# 做闭操作:去掉小范围点和线的影响提升连通区域计算速度
img = cv2.morphologyEx(temp_bin, cv2.MORPH_CLOSE, self.kernel)
# 获取连通区域
label_image = measure.label(img)
self.temps['boxs'].clear()
# 循环得到每一个连通区域属性集,参数较多,具体可以查看源码
for region in measure.regionprops(label_image, cache=False):
if 100 < region.area < 1000: # 忽略极小/极大区域
rect = dict(zip(('top', 'left', 'bottom', 'right'), region.bbox))
area = region.area # region.convex_area
C++
可以使用opencv的connectedComponentsWithStats(参照源码)或
使用findContours+minAreaRect+boundingRect+contourArea来实现
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
int ImageAnaly(Mat src_img)
{
int count = 0;
Mat img_bool, labels, stats, centroids, img_color, img_gray, img_closed;
cvtColor(src_img, img_gray, COLOR_BGR2GRAY);
threshold(img_gray, img_bool, 126, 255, THRESH_OTSU); //生成二值图
Mat element =getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
morphologyEx(img_bool, img_closed, MORPH_CLOSE, element); //闭操作
//连通域计算
int nccomps = connectedComponentsWithStats (
img_closed, //闭操作后的二值图像
labels, //和原图一样大的标记图
stats, //nccomps×5的矩阵 表示每个连通区域的外接矩形和面积(x, y, w, h, area),索引0是背景信息
centroids //nccomps×2的矩阵 表示每个连通区域的质心(x, y)
);
printf("nccomps num: %d", nccomps);
//显示统计结果
for(int i = 1; i < nccomps; i++ ) { //跳过背景信息0
int x = stats.at<int>(i, CC_STAT_LEFT);
int y = stats.at<int>(i, CC_STAT_TOP);
int width = stats.at<int>(i, CC_STAT_WIDTH);
int height = stats.at<int>(i, CC_STAT_HEIGHT);
int area = stats.at<int>(i, CC_STAT_AREA);
float proportion = (float)height/width; // 长宽比
if(100 < area && area < 1000){ // 忽略极小/极大区域
printf("num:%d, area:%d\n", i, area);
count++;
}
return count;
}
int minRect(Mat srcImage)
{
int count = 0;
Mat grayImage, binaryImage, img_closed;
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
threshold(grayImage, binaryImage, 126, 255, THRESH_BINARY);//自适应二值化
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
Mat element =getStructuringElement(cv::MORPH_ELLIPSE, Size(5, 5));
morphologyEx(binaryImage, img_closed, cv::MORPH_CLOSE, element); //闭操作
findContours(img_closed, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
for (int i = 0; i < contours.size(); i++)
{
int area = contourArea(contours[i]); //面积
RotatedRect rect = minAreaRect(contours[i]); //最小外结矩形
Rect brect = boundingRect(contours[i]); //外接矩形
int len = arcLength(contours[i], true); //周长
printf("%f, %f, %f, %f, %f\n", rect.center.x, rect.center.y, rect.angle, rect.size.width, rect.size.height);
if(100 < area && area < 1000)
{
printf("num:%d, area:%d\n", i, area);
count++;
}
}
return count;
}
注意:
connectedComponentsWithStats获取的是外接矩形,如果要最小外接矩形需要使用minAreaRect,使用arcLength获取周长,但这两个函数都需要点向量作为参数