2016/7/17
在分割图像中,经常会对图像进行差分处理再进行分割,那么对于一个输入的带有导管信息的差分图像(如图所示),该如何分割出导管信息呢,方法是构造灰度密度图像进行分割。具体步骤和实现效果容我慢慢道来。
1、 输入一个差分图像
2、 对该差分图像的每条边界扩充10个像素点,扩充像素点的像素值设置为0;
遍历图像,记灰度最大值为Max。这里我自己写的扩充边界的函数,同时统计灰度最大值。还可以使用函数copyMakeBorder();不过该函数的接口是Mat型的,参数较为复杂。使用IplImage* 图像格式的时候记得转换。
3、 构造一个21*21的模板,从像素点(10,10)开始遍历新图像,统计模板内灰度值大于0.5*Max的像素点的数目,将其转化为(0-255)之间,构造灰度密度图像。
4、 对灰度密度图像进行二维Otsu阈值分割,得到分割后的导管图像。
源码如下:
#include
#include
using namespace std;
double max_pixel=0;
double count_pixel(int i,int j,IplImage* a);
int cvOtsu2D(CvMat *pGrayMat) ;
/*扩展边界*/
IplImage* externBorder(IplImage* src,int addRows,intaddCols);
int main()
{
IplImage *img=cvLoadImage("sub.png",1);
cvNamedWindow("差分图",0);
cvNamedWindow("新图",0);
cvShowImage("差分图",img);
//构造一幅在原图基础上每条边界扩展10个像素点,并将这些像素点的值设置为0
IplImage*img_p = externBorder(img,10,10);
cvShowImage("新图",img_p);
//构造一个21*21的模板,从像素点(10,10)遍历新的图像,统计模板内灰度值大于0.55*Max的像素点的数目,构造出灰度密度图像(转换成0-255)。
IplImage*img_grey=cvCreateImage(cvGetSize(img),8,1);
CvScalarpixel_s;
for(inti=10;i
for(intj=10;j
{
pixel_s.val[0]=count_pixel(i,j,img_p);
cvSet2D(img_grey,i-10,j-10,pixel_s);
}
cvShowImage("灰度密度图像",img_grey);
CvMat*imgMat = cvCreateMat(img_grey->height, img_grey->width, CV_8UC1);//创建矩阵,其type为CV_8UC1
cvConvert(img_grey,imgMat);
int threshold = cvOtsu2D(imgMat);//求二维阈值分割的阈值
cvThreshold(img_grey,img_grey,threshold,255,CV_THRESH_BINARY);
cvShowImage("Otsu分割图",img_grey);
cvWaitKey(0);
cvReleaseImage(&img);
cvReleaseImage(&img_p);
cvReleaseImage(&img_grey);
}
/*扩展边界*/
IplImage* externBorder(IplImage* src,int addRows,intaddCols)
{
CvSizesize=cvSize(src->width+2*addCols,src->height+2*addRows);
IplImage*dst=cvCreateImage(size,8,1);
CvScalarpixel;
for(inti=0;i
for(intj=0;j
{
pixel=cvGet2D(src,i,j);
if(pixel.val[0]>max_pixel)
max_pixel=pixel.val[0];
cvSet2D(dst,i+addCols,j+addRows,pixel);
}
CvScalarpixel_s;
pixel_s.val[0]=0;
for(inti=0;i
for(intj=0;j cvSet2D(dst,i,j,pixel_s); for(inti=0;i for(intj=dst->width-addCols;j cvSet2D(dst,i,j,pixel_s); for(inti=0;i for(intj=0;j cvSet2D(dst,i,j,pixel_s); for(inti=dst->height-addRows;i for(intj=0;j cvSet2D(dst,i,j,pixel_s); return dst; } /*统计像素点*/ double count_pixel(int i,int j,IplImage* a) { double temp=0; for(intk=i-10;k
for(intm=j-10;m { if((cvGet2D(a,k,m).val[0])>(0.55*max_pixel)) temp++; } temp=temp*255/441; return temp; }