python和c++ ---- opencv图像连通区域提取

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获取周长,但这两个函数都需要点向量作为参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值