Я использую OpenCV Watershed со своим изображением:
#include "opencv2/opencv.hpp"#include <string>
using namespace cv;
using namespace std;
class WatershedSegmenter{
private:
cv::Mat markers;
public:
void setMarkers(cv::Mat& markerImage)
{
markerImage.convertTo(markers, CV_32S);
}
cv::Mat process(cv::Mat &image)
{
cv::watershed(image, markers);
markers.convertTo(markers,CV_8U);
return markers;
}
};int main(int argc, char* argv[])
{
cv::Mat image = cv::imread("d:\\projekty\\OpenCV\\trainData\\base01.jpg"); //http://i.imgur.com/sEWFHfY.jpg
cv::Mat blank(image.size(),CV_8U,cv::Scalar(0xFF));
cv::Mat dest;
imshow("originalimage", image);
// Create markers image
cv::Mat markers(image.size(),CV_8U,cv::Scalar(-1));
//Rect(topleftcornerX, topleftcornerY, width, height);
//top rectangle
markers(Rect(0,0,image.cols, 5)) = Scalar::all(1);
//bottom rectangle
markers(Rect(0,image.rows-5,image.cols, 5)) = Scalar::all(1);
//left rectangle
markers(Rect(0,0,5,image.rows)) = Scalar::all(1);
//right rectangle
markers(Rect(image.cols-5,0,5,image.rows)) = Scalar::all(1);
//centre rectangle
int centreW = image.cols/4;
int centreH = image.rows/4;
markers(Rect((image.cols/2)-(centreW/2),(image.rows/2)-(centreH/2), centreW, centreH)) = Scalar::all(2);
markers.convertTo(markers,CV_BGR2GRAY);
imshow("markers", markers);
//Create watershed segmentation object
WatershedSegmenter segmenter;
segmenter.setMarkers(markers);
cv::Mat wshedMask = segmenter.process(image);
cv::Mat mask;
convertScaleAbs(wshedMask, mask, 1, 0);
double thresh = threshold(mask, mask, 1, 255, THRESH_BINARY);
bitwise_and(image, image, dest, mask);
dest.convertTo(dest,CV_8U);
imshow("final_result", dest);
cv::waitKey(0);
return 0;
}
Но это дает мне только индивидуальную маску. Я также попытался создать маркеры в виде двух точек — в результате была получена только одна маска. Можно ли с помощью OpenCV разделить ячейки (объекты) с контурами, как в примере http://biodynamics.ucsd.edu/ir/ ?
Если нет, возможно ли создать в качестве маски результата значения: 1 для первого объекта, 2 для второго, 99 для 99?
после выполнения
cv::watershed(image, markers);
markers
image будет иметь значение -1 на границах областей, и будет 1 в области, соответствующей семени, которое было отмечено 1, и будет 2 в области, соответствующей семени, которое было отмечено 2, и так далее. Так что вы можете сделать что-то вроде этого:
cv::Mat region1 = markers==1;
Я использую следующий подход для извлечения отсчетов объектов после сегментации водораздела. Выходной сигнал водораздела представляет собой одно изображение маркеров, содержащее код сегмента каждого пикселя. Я создаю двоичное изображение маски для каждого отдельного сегмента объекта из изображения маркеров. Это можно сделать за одну итерацию по всем пикселям изображения маркеров. Для ядра «для цикла», см. Пример opencv https://github.com/Itseez/opencv/blob/master/samples/cpp/watershed.cpp. У меня есть все маски объектов, хранящиеся в vector <Mat>
, Затем я запускаю findContours для каждой такой маски -> контур каждого объекта. Увидеть http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html. Вам просто не нужно использовать детектор контуров Canny, поскольку изображения маски уже являются двоичными.