opencv用于医学图像分割

初衷

最近比较闲,跟同学聊天讲到他的课题:医学图像分割,提取左心室区域。

我就好奇要了原始图片,发现超声图像果然比红外图像分辨率低,他指给我左心室所在区域。

思路

拿到这张图第一眼,脑海里蹦出无数个小想法:

  • 感兴趣区域为一个扇形,所以首先制作掩模;
  • 这种灰度分级模糊的图像,若想分类,可以试试Kmeans,或者直接用阈值分割;
  • 后续可以分析特征,通过边界跟踪一类得到。

具体流程

  • 1、原图通过k_means二分类,并得到二值分割图;
  • 2、形态学处理将粘连区域拆分,去除连通区域内部空洞;
  • 3、掩模后只保留扇形内数据;
  • 4、提取轮廓并以面积为评估对象做筛选;
  • 5、欧式距离为评估对象,后续维护好目标跟踪。(在后续分析视频序列时,发现其实目标位置基本不会大的变化,只是在形状发生变化,因此可以借助欧式距离跟踪)

制作扇形掩模

查找opencv并没有现成的绘制扇形函数,只有手动绘制了。
大概思路为:

  • 1、绘制扇形的圆弧;
  • 2、绘制两条半径,绘制半径需要知道角点,所以牵扯些许三角函数的计算。

尝试参数后,代码如下:

//生成扇形轮廓,角度
void get_fans(Mat &img,cv::Point center,double angle, int radius)
{

	ellipse(img, center, cv::Size(radius, radius), 0, 90 - angle / 2, 90 + angle / 2, Scalar(255, 255, 255), 3, 8);

	//计算扇形顶点坐标,先计算弦长和高

	int chord_len = radius*sin(angle*3.14 / (2 * 180));

	int height = radius*cos(angle*3.14 / (2 * 180));

	//一左一右,中心点加偏移量即为顶点坐标
	
	cv::Point corner_1 = center + cv::Point(-chord_len, height);

	cv::Point corner_2 = center + cv::Point(chord_len, height);

	line(img, center, corner_1, Scalar(255, 255, 255), 3, 8);

	line(img, center, corner_2, Scalar(255, 255, 255), 3, 8);

}

朋友只需要根据参数调整,就能得到他们项目所需要的掩模。这个程序只是生成一张扇形的轮廓,生成掩模,还需要提取轮廓重新绘制,并将内部填充。
这部分代码如下:

get_fans(maskImage, cv::Point(520, 0), 77.4, 806);

		vector > contours;//查找轮廓	

		vector hierarchy;//轮廓需要

		findContours(maskImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

		maskImage = cv::Mat::zeros(cv::Size(srcImage.cols, srcImage.rows), CV_8UC1);

		//绘制自定义掩模,CV_FILLED表示完全填充内部
		drawContours(maskImage, contours, -1, cv::Scalar::all(255), CV_FILLED);

完整代码就不分享了,借用Kmeans在分类时存在需要不定时反色情形,在对视频序列处理时,直接阈值化后效果也不错。
Kmeans效果还是有那么点的:

opencv用于医学图像分割_第1张图片

opencv用于医学图像分割_第2张图片

你可能感兴趣的:(C++)