连通区域提取是图像处理中的一个基本方法,本文给出一个简单有效容易理解的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");
}
//
//
附上处理结果