图像分割
1.基于金字塔的方法
//输入:src-原始彩色图像
void gray_segmentation(IplImage * src,IplImage *dst)
{
////////////////////parameters initialization//////////////////////
int mode = CV_RETR_LIST;
int level = 2, block_size = 1000;
CvMemStorage* storage = cvCreateMemStorage(block_size);
CvSeq* components;
double threshold1 = 100,threshold2 = 50;
IplImage *image = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
cvCvtColor(src,image,CV_RGB2GRAY);
image->width = dst->width = (src->width & -(1 << level));
image->height = dst->height = (src->height & -(1 << level));
//////////////////////Segment/////////////////////////
cvPyrSegmentation(image,dst,storage,&components,level,threshold1,threshold2);
int ncomp = components->total;
cout<<"segemented into "<<ncomp<<" components."<<endl;
//////////////////////////Get Components/////////////////////////////
for (int i = 0; i < ncomp; i++)//foreach connection component
{
CvConnectedComp* cc = (CvConnectedComp*) cvGetSeqElem(components,i);
cvDrawRect(dst,cvPoint(cc->rect.x,cc->rect.y),cvPoint(cc->rect.x+cc->rect.width,cc->rect.y+cc->rect.height),cvScalar(0,0,0));
}
cvReleaseMemStorage(&storage);
cvReleaseImage(&image);
}
//
//输入:src-原始彩色图像
// dst- 空
//
void rgb_segmentation(IplImage * src,IplImage *dst)
{
////////////////////parameters initialization//////////////////////
int mode = CV_RETR_LIST;
int level = 2, block_size = 1000;
CvMemStorage* storage = cvCreateMemStorage(block_size);
CvSeq* components;
double threshold1 = 10,threshold2 = 50;
IplImage *image = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
image = cvCloneImage(src);
image->width = dst->width = (src->width & -(1 << level));
image->height = dst->height = (src->height & -(1 << level));
//////////////////////Segment/////////////////////////
cvPyrSegmentation(image,dst,storage,&components,level,threshold1,threshold2);
int ncomp = components->total;
//////////////////////////Get Components/////////////////////////////
for (int i = 0; i < ncomp; i++)//foreach connection component
{
CvConnectedComp* cc = (CvConnectedComp*) cvGetSeqElem(components,i);
cvDrawRect(dst,cvPoint(cc->rect.x,cc->rect.y),cvPoint(cc->rect.x+cc->rect.width,cc->rect.y+cc->rect.height),cvScalar(255,0,0));
}
cvReleaseImage(&image);
cvReleaseMemStorage(&storage);
}
2.基于边缘的方法
//
//基于边缘检测进行图像分割
//输入:src- 原始图像
// dst-原始图像
//返回:dst -分割结果
// 1- 输入为空
// 2-
int seg_base_edge(IplImage * src,IplImage * dst)
{
if(NULL == src || NULL == dst){
return 1;
}
//获取灰度图片
IplImage * pGrayImg = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
cvCvtColor(src,pGrayImg,CV_BGR2GRAY);
//利用Canny算子进行边缘检测
IplImage * pCannyImg = cvCreateImage(cvGetSize(pGrayImg),pGrayImg->depth,pGrayImg->nChannels);
cvCanny(pGrayImg,pCannyImg,50,150,3);
//膨胀,使边缘轮廓闭合
IplImage * pDilateImg = cvCreateImage(cvGetSize(pGrayImg),pGrayImg->depth,1);
IplConvKernel *rect_2;
rect_2 = cvCreateStructuringElementEx(2, 3, 1, 1, CV_SHAPE_RECT);
cvDilate(pCannyImg, pDilateImg);
//检测图片轮廓
CvMemStorage * storage = cvCreateMemStorage(0);
CvSeq * contour = 0;
int mode = CV_RETR_EXTERNAL;
int num = cvFindContours(pDilateImg,storage,&contour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_NONE, cvPoint(0,0) );
//用白色填充面积最大的轮廓
double maxArea = 1000;
IplImage * pContourImg = cvCreateImage(cvGetSize(pCannyImg), IPL_DEPTH_8U, 3);
//初始化为黑色
cvZero(pContourImg);
while(contour)
{
double area = fabs(cvContourArea(contour, CV_WHOLE_SEQ));
if(area > maxArea)
{
cvDrawContours(pContourImg,contour,cvScalarAll(255),cvScalarAll(0),0,CV_FILLED);
}
contour = contour->h_next;
}
cvReleaseMemStorage(&storage);
//填充图作为mask,与原图像进行按像素与操作
for(int height = 0; height < src->height;height++){
for(int width = 0; width < src->width; width++)
{
int piex = height * src->width + width;
if((BYTE)pContourImg->imageData[piex * 3] != 255u)
{
dst->imageData[piex * 3] = 0;
dst->imageData[piex * 3 + 1] = 0;
dst->imageData[piex * 3 + 2] = 0;
}
}
}
//释放资源
cvReleaseImage(&pGrayImg);
cvReleaseImage(&pCannyImg);
cvReleaseImage(&pDilateImg);
cvReleaseImage(&pContourImg);
return 0;
}