简单有效的连通区域提取算法实现

连通区域提取是图像处理中的一个基本方法,本文给出一个简单有效容易理解的8邻域方法

#include <iostream>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <vector>

#pragma comment(lib, "cv")
#pragma comment(lib, "cxcore")
#pragma comment(lib, "highgui")

using namespace std;

static IplImage* MarkImage;
static CvPoint* PointArray ;
void CreateBuff(int width, int height)
{	
	int y;	
	MarkImage = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
	PointArray = (CvPoint*)malloc(width*height*sizeof(CvPoint));
	
	cvZero(MarkImage);
	memset(PointArray, 0, width*height*sizeof(CvPoint));
}

void ReleaseBuff()
{
	cvReleaseImage(&MarkImage);
	free(PointArray);
}

typedef struct Region
{
	int size;
	CvRect rect;
}Region;

void FilterMaxHeightWidthRegionForRect(IplImage* srcImage, vector<Region>& Reg)
{
	int hIndex = 0, wIndex = 0, Position = 0;
	int iStartNum = 0, iEndNum = 0, EdgeNum = 0;
	int XValue = 0, YValue = 0, dIndex = 0; 

	int width = srcImage->width;
	int height= srcImage->height;

	int MinXValue = 0, MaxXValue = 0, MinYValue = 0, MaxYValue = 0;
	int PointArrayCnt;
	for (hIndex = 0; hIndex < height; hIndex++)
	{
		for (wIndex = 0; wIndex < width; wIndex++)
		{
			Position = hIndex*srcImage->widthStep + wIndex;

			if (srcImage->imageData[Position] == 0 )
				continue;

			if (MarkImage->imageData[Position] != 0)
				continue;

			iStartNum = -1; iEndNum = 0;  EdgeNum = 0;
			PointArrayCnt = 0;
			PointArray[PointArrayCnt] = cvPoint(wIndex, hIndex);

			MarkImage->imageData[Position] = 128;

			MinXValue = MaxXValue = wIndex;
			MinYValue = MaxYValue = hIndex;

			while(iStartNum < iEndNum)
			{
				iStartNum = iStartNum + 1;

				XValue = PointArray[iStartNum].x;
				YValue = PointArray[iStartNum].y;

				MinXValue = MinXValue < XValue ? MinXValue : XValue;
				MaxXValue = MaxXValue > XValue ? MaxXValue : XValue;
				MinYValue = MinYValue < YValue ? MinYValue : YValue;
				MaxYValue = MaxYValue > YValue ? MaxYValue : YValue;
				
				if(XValue < 0 || XValue >= width
					|| YValue < 0 || YValue >= height)
					continue;

				Position = YValue*srcImage->widthStep + XValue;
			
				if (XValue - 1 >= 0 && YValue - 1 >= 0
					&& MarkImage->imageData[Position - srcImage->widthStep - 1] == 0 
					&& srcImage->imageData[Position - srcImage->widthStep - 1] != 0)
				{
					
					++PointArrayCnt;			
					PointArray[PointArrayCnt] = cvPoint(XValue - 1, YValue - 1);
					MarkImage->imageData[Position - srcImage->widthStep - 1] = 128;
				}

				if (XValue >= 0 && YValue - 1 >= 0
					&& MarkImage->imageData[Position - srcImage->widthStep] == 0
					&& srcImage->imageData[Position - srcImage->widthStep] != 0)
				{
					
					++PointArrayCnt;
					PointArray[PointArrayCnt] = cvPoint(XValue, YValue - 1);
					MarkImage->imageData[Position - srcImage->widthStep] = 128;
				}

				if (XValue + 1 < width && YValue - 1 >= 0
					&& MarkImage->imageData[Position - srcImage->widthStep + 1] == 0
					&& srcImage->imageData[Position - srcImage->widthStep + 1] != 0)
				{
					
					++PointArrayCnt;
					PointArray[PointArrayCnt] = cvPoint(XValue + 1, YValue - 1);
					MarkImage->imageData[Position - srcImage->widthStep + 1] = 128;
				}

				if (XValue + 1 < width && YValue >= 0
					&& MarkImage->imageData[Position + 1] == 0
					&& srcImage->imageData[Position + 1] != 0)
				{
					
					++PointArrayCnt;
					PointArray[PointArrayCnt] = cvPoint(XValue + 1, YValue);
					MarkImage->imageData[Position + 1] = 128;
				}

				if (XValue + 1 < width && YValue + 1 < height
					&& MarkImage->imageData[Position + srcImage->widthStep + 1] == 0
					&& srcImage->imageData[Position + srcImage->widthStep + 1] != 0)
				{
					
					++PointArrayCnt;
					PointArray[PointArrayCnt] = cvPoint(XValue + 1, YValue + 1);
					MarkImage->imageData[Position + srcImage->widthStep + 1] = 128;
				}

				if (XValue >= 0 && YValue + 1 < height
					&& MarkImage->imageData[Position + srcImage->widthStep] == 0
					&& srcImage->imageData[Position + srcImage->widthStep] != 0)
				{
					
					++PointArrayCnt;
					PointArray[PointArrayCnt] = cvPoint(XValue, YValue + 1);
					MarkImage->imageData[Position + srcImage->widthStep] = 128;
				}

				if (XValue - 1 >= 0 && YValue + 1 < height
					&& MarkImage->imageData[Position + srcImage->widthStep - 1] == 0
					&& srcImage->imageData[Position + srcImage->widthStep - 1] != 0)
				{
					
					++PointArrayCnt;
					PointArray[PointArrayCnt] = cvPoint(XValue - 1, YValue + 1);
					MarkImage->imageData[Position + srcImage->widthStep - 1] = 128;
				}

				if (XValue - 1 >= 0 && YValue >= 0
					&&MarkImage->imageData[Position - 1] == 0
					&& srcImage->imageData[Position - 1] != 0)
				{
					
					++PointArrayCnt;
					PointArray[PointArrayCnt] = cvPoint(XValue - 1, YValue);
					MarkImage->imageData[Position - 1] = 128;
				}

				iEndNum = PointArrayCnt;
			}
			if(PointArrayCnt >0)
			{
				Region tmpRegion;
				tmpRegion.size = PointArrayCnt;
				tmpRegion.rect.x = MinXValue;
				tmpRegion.rect.y = MinYValue;
				tmpRegion.rect.width = MaxXValue - MinXValue + 1; 
				tmpRegion.rect.height = MaxYValue - MinYValue + 1;

				Reg.push_back(tmpRegion);
				memset(PointArray, 0, width*height*sizeof(CvPoint));
			}
		}
	}
}
void main()
{
	IplImage* img = cvLoadImage("E:\\temp54\\180_disp.jpg", 0);
	int width = img->width;
	int height= img->height;

	IplImage* tmp = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
	cvZero(tmp);
	cvThreshold(img, tmp, 160, 255, CV_THRESH_BINARY);
	cvNamedWindow("tmp");
	cvShowImage("tmp", tmp);
	CreateBuff(width, height);
	
	vector<Region> region;	
	FilterMaxHeightWidthRegionForRect(tmp, region);
	cout<<region.size()<<endl;
	cvNamedWindow("Draw");
	for(int i=0; i<region.size(); ++i)
	{
		CvPoint pt1, pt2;
		pt1.x = region.at(i).rect.x-1;
		pt1.y = region.at(i).rect.y-1;
		pt2.x = pt1.x + region.at(i).rect.width+1;
		pt2.y = pt1.y + region.at(i).rect.height+1;

		cvRectangle(tmp, pt1, pt2, CV_RGB(255,255,255), 1, 8, 0);

		cout<<"size = "<<region.at(i).size<<endl;
	}
	cvShowImage("Draw", tmp);
	cvWaitKey(0);

	system("pause");
}



//


//

附上处理结果


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值