我目前正致力于将Matlab版本的活动轮廓转换为OpenCV。似乎OpenCV有自己版本的活动轮廓,但是当时不推荐使用。我很好奇这个版本与Matlab版本有多么不同。所以我做了一个比较实验。给定MRI脑图像和初始边界,我应用Matlab和OpenCV版本活动轮廓来分割脑中的白质。
对于Matlab和OpenCV,我选择活动轮廓的渐变(边缘)方法。然后我在图像上标记了结果。红色曲线是初始边界,而绿色曲线是最终边界。
Matlab代码是:
clear
clc
I = imread('brain.png');
IMaskS = imread('shrinkMask.png');
figure(1)
imshow(I)
hold on
visboundaries( IMaskS, 'color', 'r');
bwSnake = activecontour(I, IMaskS, 250, 'edge','ContractionBias',-0.45,'SmoothFactor',0.7);
finalBoundary = bwboundaries(bwSnake);
visboundaries(finalBoundary, 'color', 'g');
在选择合适的参数时,Matlab似乎做得非常好。 " ContractionBias"参数(参考here)对于控制曲线缩小或扩展非常有用。
然而,OpenCV版本的活动轮廓似乎根本不起作用。我使用滑块来更改参数alpha,beta和gamma,但无法获得下降结果。无论我如何设置参数,似乎曲线都不会扩展。我使用OpenCV 2.4.13.3,活动轮廓可以在遗留文件夹中找到snakes.cpp。 Chek OpenCV github或更具体地snakes.cpp。 OpenCV测试代码是:
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/legacy/legacy.hpp"
using namespace std;
using namespace cv;
IplImage *image = 0;
IplImage *image2 = 0;
IplImage *imageMask = 0;
using namespace std;
int ialpha = 10;
int ibeta = 40;
int igamma = 50;
void onChange(int pos)
{
if (image2) cvReleaseImage(&image2);
if (image) cvReleaseImage(&image);
if (imageMask) cvReleaseImage(&imageMask);
image2 = cvLoadImage("brain.png", 1);
image = cvLoadImage("brain.png", 0);
imageMask = cvLoadImage("shrinkMask.png", 0);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours = 0;
cvFindContours(imageMask, storage, &contours, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
if (!contours) return;
int length = contours->total;
if (length<10) return;
CvPoint* point = new CvPoint[length];
CvSeqReader reader;
CvPoint pt = cvPoint(0, 0);;
CvSeq *contour2 = contours;
cvStartReadSeq(contour2, &reader);
for (int i = 0; i < length; i++)
{
CV_READ_SEQ_ELEM(pt, reader);
point[i] = pt;
}
cvReleaseMemStorage(&storage);
for (int i = 0; i<length; i++)
{
int j = (i + 1) % length;
cvLine(image2, point[i], point[j], CV_RGB(255, 0, 0), 1, 8, 0);
}
float alpha = ialpha / 100.0f;
float beta = ibeta / 100.0f;
float gamma = igamma / 100.0f;
CvSize size;
size.width = 3;
size.height = 3;
CvTermCriteria criteria;
criteria.type = CV_TERMCRIT_ITER;
criteria.max_iter = 500;
criteria.epsilon = 0.1;
cvSnakeImage(image, point, length, &alpha, &beta, &gamma, CV_VALUE, size, criteria, 1);
for (int i = 0; i<length; i++)
{
int j = (i + 1) % length;
cvLine(image2, point[i], point[j], CV_RGB(0, 255, 0), 1, 8, 0);
}
delete[]point;
}
int main(int argc, char* argv[])
{
cvNamedWindow("win1", 0);
cvCreateTrackbar("alpha", "win1", &ialpha, 100, onChange);
cvCreateTrackbar("beta", "win1", &ibeta, 100, onChange);
cvCreateTrackbar("gamma", "win1", &igamma, 100, onChange);
//cvResizeWindow("win1", 696, 520);
cvResizeWindow("win1", 256, 256);
onChange(0);
for (;;)
{
if (cvWaitKey(40) == 27) break;
cvShowImage("win1", image2);
}
return 0;
}
我做错了什么或者OpenCV中这个版本的活动轮廓完全没用?我检查了snake.cpp,OpenCV版本活动轮廓的源代码,它似乎是基于论文理论实现的。由于文件保护,我无法访问Matlab版本的活动轮廓。因此,我无法直接比较它们。从最终开始,我将使用OpenCV来实现内容,任何改进或更改我的OpenCV代码的建议都将受到赞赏。
我附上了原始图片和面具,以防有人想重复测试。
谢谢!