水岭分割方法是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形成分水岭。
1.创建WatershedSegmenter类处理方法
/*WatershedSegmenter*/
class WatershedSegmenter {
private:
cv::Mat markers;
public:
void setMarkers(const cv::Mat& markerImage) {
// Convert to image of ints
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(const cv::Mat &image) {
// Apply watershed
cv::watershed(image, markers);
return markers;
}
// Return result in the form of an image
cv::Mat getSegmentation() {
cv::Mat tmp;
// all segment with label higher than 255
// will be assigned value 255
markers.convertTo(tmp, CV_8U);
return tmp;
}
// Return watershed in the form of an image
cv::Mat getWatersheds() {
cv::Mat tmp;
markers.convertTo(tmp, CV_8U, 255, 255);
return tmp;
}
};
2.实现过程
void OpenCVQtGui::Watershed_clicked()
{
cv::Mat Result = image.clone();
cvtColor(Result, Result, CV_BGR2GRAY);
/**/
// cv::threshold(Result, Result, 0, 255, cv::THRESH_BINARY|cv::THRESH_OTSU);
//
// cv::imshow("Foreground Image1", Result);
//
// /*形态学操作,进一步消除图像中噪点*/
// cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
//
// cv::morphologyEx(Result, Result, cv::MORPH_OPEN, element, cv::Point(-1, -1), 2);
//
// cv::Mat bg;
// cv::dilate(Result, bg, element, cv::Point(-1, -1), 6);
// cv::imshow("Background Image2", bg);
//Eliminate noise and smaller objects
cv::threshold(Result, Result, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
cv::Mat fg;
cv::erode(Result, fg, cv::Mat(), cv::Point(-1, -1), 6);
// Display the foreground image
cv::imshow("Foreground Image1", fg);
// Identify image pixels without objects
cv::Mat bg;
cv::dilate(Result, bg, cv::Mat(), cv::Point(-1, -1), 6);
cv::threshold(bg, bg, 1, 128, cv::THRESH_BINARY_INV);
// Display the background image
cv::imshow("Background Image2", bg);
// Show markers image
cv::Mat markers(Result.size(), CV_8U, cv::Scalar(0));
markers = fg + bg;
cv::imshow("Markers3", markers);
// Create watershed segmentation object
WatershedSegmenter segmenter;
// Set markers and process
segmenter.setMarkers(markers);
markers = segmenter.process(image);
//cv::imshow("Segmentation4", image);
// Display segmentation result
cv::imshow("Segmentation4", segmenter.getSegmentation());
// Display watersheds
cv::Mat marker1 = segmenter.getWatersheds();
cv::imshow("Waterheds5", marker1);
cv::Mat mask;
cv::compare(markers, -1, mask, cv::CMP_EQ);
cv::imshow("Waterheds6", mask);
Result = image.clone();
Result.setTo(cv::Scalar(0, 255, 0), mask);
cvtColor(Result, Result, CV_BGR2RGB);
QImage img1 = QImage((const unsigned char*)(Result.data), Result.cols, Result.rows, QImage::Format_RGB888);
ui.label_2->setPixmap(QPixmap::fromImage(img1));
ui.label_2->resize(QSize(img1.width(), img1.height()));
}
3.实现结果