opencv watershed
demo: http://download.csdn.net/detail/keen_zuxwang/9852585
分水岭算法
1、一种基于拓扑理论的数学形态学的图像分割方法。分水岭算法容易导致图像的过度分割。opencv中,使用预定义的一组标记来引导对图像的分割,防止过度切割。
2、一种图像区域分割法,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭算法的一个重要特征。
//! segments the image using watershed algorithm
CV_EXPORTS_W void watershed( InputArray image, InputOutputArray markers );
功能:标识出不同区域间的值被置为-1(边界), 没有标记清楚的区域被置为0,其他每个区域的值保持不变
image
输入图像,须为CV_8UC3类型
markers
声明为CV_32S类型(32位单通道),既作为输入,也作为输出保存函数调用的结果。
watershed函数
1、watershed第二个参数markers必须包含了种子点信息,它应该包含不同区域的轮廓,每个轮廓有一个自己唯一的编号,轮廓的定位可以通过Opencv中findContours方法实现,这个是执行分水岭之前的要求。
2、分水岭算法会根据markers传入的轮廓作为种子(注水点),对图像上其他的像素点根据分水岭算法规则进行判断,并对每个像素点的区域归属进行划定,直到处理完图像上所有像素点。而区域与区域之间的分界处的值被置为“-1”,以做区分。
JNI:
JNIEXPORT jlong JNICALL Java_com_example_grabcut_MainActivity_doWatershed(JNIEnv *env, jclass clz, jlong imageGray)
{
Mat img0 = Mat(*(Mat*)imageGray);
Mat img(img0.size(),CV_8UC3); //输入图像须为CV_8UC3类型
cvtColor(img0, img, CV_BGRA2BGR);
Mat gray;
cvtColor(img, gray, CV_BGR2GRAY);//1、转换为灰度图
equalizeHist(gray, gray); //2、直方图均衡化 CV_EXPORTS_W void equalizeHist( InputArray src, OutputArray dst );
blur(gray, gray, Size(5,5)); //3、均值滤波
Mat binary;
adaptiveThreshold(gray, binary, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 5, 10);//4、将灰度图转换为二值图
Mat markers(gray.size(), CV_32S, Scalar::all(0));
vector< vector > contours;
vector hierarchy;
findContours(binary, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); //5、findContour()函数找出图像的轮廓
int idx = 0;
int compIdx = 0;
for( ; idx >= 0; idx = hierarchy[idx][0],compIdx++){
//Scalar color(rand()&255, rand()&255, rand()&255);
//drawContours(markers, contours, idx, color, CV_FILLED, 8, hierarchy);
drawContours(markers, contours, idx, Scalar::all(compIdx+1), CV_FILLED, 8, hierarchy);//6、markers上绘制contours
}
Mat marks0;
convertScaleAbs(markers,marks0);
//调用分水岭算法分割图像
watershed(img, markers); //7、img须为CV_8UC3类型,markers须为CV_32S类型
Mat marks1;
convertScaleAbs(markers,marks1);
//Mat marker;
//markers.convertTo(marker, CV_8U);
//marks1.convertTo(marker,CV_8U);//CV_8UC3 输出测试使用
Mat fillMat = Mat::zeros(gray.size(),CV_8UC3); // 8、填充绘制
for(int i=0;ifor(int j=0;jint index=markers.at<int>(i,j);
if(markers.at<int>(i,j)==-1) {
fillMat.at(i,j)= Vec3b(255,255,255);
}else {
fillMat.at(i,j)= RandomColor(index);
}
}
}
//Mat mix;
//addWeighted(img,0.5,fillMat,0.5,0,mix); //输出测试使用
Mat *hist = new Mat(fillMat); // 9、回传Java端显示
return (jlong) hist;
}