連通區域處理

1. 查找最大連通區域

Mat findMaxContours(Mat src)
{
	Mat bw; src.copyTo(bw);
	//查找最大連通區域
	vector<vector<Point>>contours;  //每個輪廓中的點
	vector<Vec4i>hierarchy;         //輪廓的索引  
	findContours(bw, contours, hierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
	double max_area = 0;
	int index = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		if (contourArea(contours[i]) > max_area)
		{
			max_area = contourArea(contours[i]);
			index = i;
		}
	}
	Mat dstImage = Mat::zeros(src.rows, src.cols, CV_8UC1);
	if (contours.size()>0)
	{
		drawContours(dstImage, contours, index, Scalar(255), -1);
	}
	contours.clear();
	hierarchy.clear();
	contours.swap(vector<vector<Point>>(contours));
	hierarchy.swap(vector<Vec4i>(hierarchy));
	return dstImage;
}

2.connectedComponentsWithStats(0penCV2.4.10實現)

2.1 參數說明

//不帶統計信息的API:
int cv::connectedComponents(
        InputArray    image,             // 輸入二值圖像
        OutputArray   labels,            // 輸出的標記圖像,背景index=0
        int           connectivity = 8,  // 連通域,默認是8連通
        int           ltype = CV_32S     // 輸出的labels類型,默認是CV_32S
) 
//帶有統計信息的API:
int cv::connectedComponentsWithStats(
        InputArray   image,        // 輸入二值圖像
        OutputArray  labels,       // 輸出的標記圖像,背景index=0
        OutputArray  stats,        // 統計信息,包括每個組件的位置、寬、高與面積
        OutputArray  centroids,    // 每個組件的中心位置座標cx, cy
        int          connectivity, // 連通域,默認是8連通
        int          ltype,        // 輸出的labels類型,默認是CV_32S
        int          ccltype       // 連通組件算法
)
 
//其中stats包括以下枚舉類型數據信息: 
   CC_STAT_LEFT   組件的左上角點像素點座標的X位置
   CC_STAT_TOP    組件的左上角點像素點座標的Y位置
   CC_STAT_WIDTH  組件外接矩形的寬度 
   CC_STAT_HEIGHT 組件外接矩形的高度
   CC_STAT_AREA   當前連通組件的面積(像素單位)

2.2 m_precomp.hpp 改寫

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                          License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/core/mat.hpp"

#include "opencv2/imgproc/imgproc_c.h"
//#include "opencv2/core/private.hpp"
//#include "opencv2/core/ocl.hpp"
//#include "opencv2/core/hal/hal.hpp"
//#include "opencv2/imgproc/hal/hal.hpp"
//#include "hal_replacement.hpp"

#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <float.h>

#ifdef HAVE_TEGRA_OPTIMIZATION
#include "opencv2/imgproc/imgproc_tegra.hpp"
#else
#define GET_OPTIMIZED(func) (func)
#endif

enum ConnectedComponentsTypes {
	CC_STAT_LEFT = 0, //!< The leftmost (x) coordinate which is the inclusive start of the bounding
	//!< box in the horizontal direction.
	CC_STAT_TOP = 1, //!< The topmost (y) coordinate which is the inclusive start of the bounding
	//!< box in the vertical direction.
	CC_STAT_WIDTH = 2, //!< The horizontal size of the bounding box
	CC_STAT_HEIGHT = 3, //!< The vertical size of the bounding box
	CC_STAT_AREA = 4, //!< The total area (in pixels) of the connected component
#ifndef CV_DOXYGEN
	CC_STAT_MAX = 5 //!< Max enumeration value. Used internally only for memory allocation
#endif
};

//! connected components algorithm
enum ConnectedComponentsAlgorithmsTypes {
	CCL_WU = 0,  //!< SAUF algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity
	CCL_DEFAULT = -1, //!< BBDT algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity
	CCL_GRANA = 1   //!< BBDT algorithm for 8-way connectivity, SAUF algorithm for 4-way connectivity
};

/* helper tables */
extern const uchar icvSaturate8u_cv[];
#define CV_FAST_CAST_8U(t)  ( (-256 <= (t) && (t) <= 512) ? icvSaturate8u_cv[(t)+256] : 0 )
#define CV_CALC_MIN_8U(a,b) (a) -= CV_FAST_CAST_8U((a) - (b))
#define CV_CALC_MAX_8U(a,b) (a) += CV_FAST_CAST_8U((b) - (a))

// -256.f ... 511.f
extern const float icv8x32fTab_cv[];
#define CV_8TO32F(x)  icv8x32fTab_cv[(x)+256]

// (-128.f)^2 ... (255.f)^2
extern const float icv8x32fSqrTab[];
#define CV_8TO32F_SQR(x)  icv8x32fSqrTab[(x)+128]

#define  CV_COPY( dst, src, len, idx ) \
    for( (idx) = 0; (idx) < (len); (idx)++) (dst)[idx] = (src)[idx]

#define  CV_SET( dst, val, len, idx )  \
    for( (idx) = 0; (idx) < (len); (idx)++) (dst)[idx] = (val)

#undef   CV_CALC_MIN
#define  CV_CALC_MIN(a, b) if((a) > (b)) (a) = (b)

#undef   CV_CALC_MAX
#define  CV_CALC_MAX(a, b) if((a) < (b)) (a) = (b)

#ifdef HAVE_IPP
static inline IppiInterpolationType ippiGetInterpolation(int inter)
{
    inter &= cv::INTER_MAX;
    return inter == cv::INTER_NEAREST ? ippNearest :
        inter == cv::INTER_LINEAR ? ippLinear :
        inter == cv::INTER_CUBIC ? ippCubic :
        inter == cv::INTER_LANCZOS4 ? ippLanczos :
        inter == cv::INTER_AREA ? ippSuper :
        (IppiInterpolationType)-1;
}
#endif

//#include "_geom.h"
//#include "filterengine.hpp"
//
//#include "opencv2/core/sse_utils.hpp"
//
//inline bool isStorageOrMat(void * arr)
//{
//    if (CV_IS_STORAGE( arr ))
//        return true;
//    else if (CV_IS_MAT( arr ))
//        return false;
//    else
//        CV_Error( CV_StsBadArg, "Destination is not CvMemStorage* nor CvMat*" );
//    return false;
//}

#endif /*__OPENCV_CV_INTERNAL_H_*/
#include<opencv2/opencv.hpp>
using namespace cv;

int connectedComponentsWithStats(InputArray img_, OutputArray _labels, OutputArray statsv,
	OutputArray centroids, int connectivity, int ltype, int ccltype);

2.3 m_connectedcomponents.cpp改寫

受代碼長度限制,部分代碼如下,下載資源提供全部代碼。

	int connectedComponents(InputArray img_, OutputArray _labels, int connectivity, int ltype, int ccltype){
		const cv::Mat img = img_.getMat();
		_labels.create(img.size(), CV_MAT_DEPTH(ltype));
		cv::Mat labels = _labels.getMat();
		connectedcomponents::NoOp sop;
		if (ltype == CV_16U){
			return connectedComponents_sub1(img, labels, connectivity, ccltype, sop);
		}
		else if (ltype == CV_32S){
			return connectedComponents_sub1(img, labels, connectivity, ccltype, sop);
		}
		else{
			CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s");
			return 0;
		}
	}
	
	int connectedComponentsWithStats(InputArray img_, OutputArray _labels, OutputArray statsv,
		OutputArray centroids, int connectivity = 8, int ltype = CV_32S, int ccltype = CCL_DEFAULT)
	{
		const cv::Mat img = img_.getMat();
		_labels.create(img.size(), CV_MAT_DEPTH(ltype));
		cv::Mat labels = _labels.getMat();
		connectedcomponents::CCStatsOp sop(statsv, centroids);
		if (ltype == CV_16U){
			return connectedComponents_sub1(img, labels, connectivity, ccltype, sop);
		}
		else if (ltype == CV_32S){
			return connectedComponents_sub1(img, labels, connectivity, ccltype, sop);
		}
		else{
			CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s");
			return 0;
		}
	}

3. 測試主函數

//OpenCV3.3.0

#include <algorithm>
#include <iostream>
#include<opencv2/opencv.hpp>
#include "m_precomp.hpp"
using namespace cv;
using namespace std;

int main()
{
	Mat img, img_edge, labels, centroids, img_color, stats;
	img = imread("1.png", 0);
	threshold(img, img_edge, 0, 255, THRESH_OTSU);
	int nccomps = connectedComponentsWithStats(img_edge, labels, stats, centroids, 8, CV_32S, CCL_DEFAULT);
	cout << "連通域個數: " << nccomps << endl;
	vector<Vec3b>colors(nccomps + 1);;
	colors[0] = Vec3b(0, 0, 0);
	for (int i = 1; i <= nccomps; i++)
	{
		colors[i] = Vec3b(rand() % 256, rand() % 256, rand() % 256);
		if (stats.at<int>(i-1, CC_STAT_AREA) < 2500)
			colors[i] = Vec3b(0, 0, 0);

		cout << stats.at<int>(i - 1, CC_STAT_AREA) << endl;//連通域的面積

	}
	img_color = Mat::zeros(img.size(), CV_8UC3);
	for (int y = 0; y < img_color.rows; y++)
		for (int x = 0; x < img_color.cols; x++)
		{
			int label = labels.at<int>(y, x);
			CV_Assert(0 <= label && label <= nccomps);
			img_color.at<Vec3b>(y, x) = colors[label];
		}
	return 0;
}

4. 結果

原始圖
標記圖

5.參考

https://github.com/opencv/opencv/blob/master/modules/imgproc/src/connectedcomponents.cpp
https://blog.csdn.net/jgj123321/article/details/93489417

源代碼下載鏈接:
https://download.csdn.net/download/fei13148687/12241852

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章