连通域标记图像函数:ConnectedComponents
/**
* 连通域标记图像ConnectedComponents,用于轮廓分析
* 对于一张二值化的图像,后续处理方式有两种。第一种方式就是利用findContours、drawContours等函数进行轮廓分析
* (opencv以对轮廓的处理为主)。第二种方式就是计算连通域进行区域分析
* connectedComponents(
* Mat image, // 输入二值图像
* Mat labels, // 输出的标记图像,背景index=0
* int connectivity = 8, // 连通域,默认是8连通
* int ltype = CvType.CV_32S // 输出的labels类型,默认是CV_32S
* )
*/
@Test
public void testConnectedComponents() {
Mat src = GeneralUtils.converMat("C:\\图片\\test\\0001.jpg");
//自动阈值
Mat gray = new Mat();
Mat binary = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(gray, binary, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
//计算连通域
Mat labels = new Mat(src.size(), CvType.CV_32S);
int num = Imgproc.connectedComponents(binary, labels, 8, CvType.CV_32S);
System.out.println("标记数:" + num);
//定义颜色
List<Integer[]> colors = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < num; i++) {
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
colors.add(new Integer[]{r, g, b});
}
//标记联通域
Mat dst = new Mat(src.size(), src.type());
dst.setTo(new Scalar(255, 255, 255));
int width = src.cols();
int height = src.rows();
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
int label = (int) labels.get(row, col)[0];
if (label == 0) continue;
dst.put(row, col, colors.get(label)[0], colors.get(label)[1], colors.get(label)[2]);
}
}
GeneralUtils.saveByteImg(dst, "C:\\图片\\test\\connectedComponents.jpg");
}
带有统计信息的连通域标记图像函数:connectedComponentsWithStats
/**
* 带有统计信息的连通域标记图像
* connectedComponentsWithStats(
* Mat image, // 输入二值图像
* Mat labels, // 输出的标记图像,背景index=0
* Mat stats, // 统计信息,包括每个组件的位置、宽、高与面积
* Mat centroids, // 每个组件的中心位置坐标cx, cy
* int connectivity, // 连通域,默认是8连通
* int ltype, // 输出的labels类型,默认是CV_32S
* int ccltype // 连通组件算法
* )
*/
@Test
public void testConnectedComponentsWithStats() {
Mat src = GeneralUtils.converMat("C:\\图片\\test\\0001.jpg");
//自动阈值
Mat gray = new Mat();
Mat binary = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(gray, binary, 0, 255, Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);
//计算连通域
Mat labels = new Mat(src.size(), CvType.CV_32S);
Mat status = new Mat();
Mat centroids = new Mat();
int num = Imgproc.connectedComponentsWithStats(binary, labels, status, centroids, 8, 4);
System.out.println("标记数:" + num);
//定义颜色
List<Scalar> colors = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < num; i++) {
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);
colors.add(new Scalar(r, g, b));
}
//标记联通域
Mat dst = src.clone();
dst.setTo(new Scalar(255, 255, 255));
for (int i = 1; i < num; i++) {
//中心位置
double cx = centroids.get(i, 0)[0];
double cy = centroids.get(i, 1)[0];
int x = (int) status.get(i, Imgproc.CC_STAT_LEFT)[0];
int y = (int) status.get(i, Imgproc.CC_STAT_TOP)[0];
int w = (int) status.get(i, Imgproc.CC_STAT_WIDTH)[0];
int h = (int) status.get(i, Imgproc.CC_STAT_HEIGHT)[0];
//绘制中心位置
Imgproc.circle(dst, new Point(cx, cy), 2, new Scalar(0, 0, 255), 2, 8, 0);
//绘制外接矩形
Imgproc.rectangle(dst, new Point(x, y), new Point(x + w, y + h), colors.get(i), 1, 8, 0);
}
GeneralUtils.saveByteImg(dst, "C:\\图片\\test\\connectedComponentsWithStats.jpg");
}
《中医基础理论》