The watershed algorithm converts the edge of the image into a "mountain range" and transforms the homogeneous region into a "valley". First, the gradient of the grayscale image is computed, and then the continuous "perfusion" of the basin is initiated from the user-specified point (or the algorithm-obtained point) until the regions are connected together. The resulting tag allows the area to be merged together, and the merged region is segmented by aggregation, as if the image were "filled". In this way, the basins connected to the indicator point are "owned" by the indicator point. Finally, we split the image into the corresponding labeled area.
Example 1:
#include "cv.h" #include "highgui.h" using namespace CV;
Mat Markermask, IMG;
Point Prept ( -1,-1); void Onmouse (int event, int x,int y,int flags,void* param) {if (event = = Cv_event_lbuttonup | |!) (
Flags & Cv_event_flag_lbutton)) prept = Point ( -1,-1);
if (event = = Cv_event_lbuttondown) prept = Point (X,y);
if (event = = Cv_event_mousemove && (Flags & Cv_event_flag_lbutton)) {Point pt (x,y);
if (Prept.x < 0) prept = pt;
Line (Markermask,prept,pt,scalar (255,255,255), 5);
Line (IMG, Prept, PT, Scalar (255, 255, 255), 5);
Prept = pt;
Imshow ("Original artwork", IMG);
int main () {Mat img0 = Imread ("d:\\tongliya.jpg", 1);
Img0.copyto (IMG);
Namedwindow ("original artwork", 1);
Imshow ("Original artwork", IMG);
Mat imggray;//The final display watershed effect diagram with Cvtcolor (Img0,markermask,cv_bgr2gray);
Cvtcolor (MARKERMASK,IMGGRAY,CV_GRAY2BGR);
Markermask = Scalar::all (0);
Setmousecallback ("original artwork", Onmouse,null);
while (1) {int c = Waitkey (10); if ((char) c = = ' Q ' | |
(char) c = n) return 0; if ((char) c = = ' R ') {IMg0.copyto (IMG);
Markermask = Scalar::all (0);
Imshow ("Original artwork", IMG);
} if (char (c) = = ' P ') {vector<vector<point>> contours;
Vector<vec4i> hierarchy;
int count=0; Findcontours (markermask,contours,hierarchy,cv_retr_ccomp,cv_chain_approx_simple); <span style= "color: #33CC00;"
>//input image must be a 2-value single channel image </span> if (Contours.empty ()) continue;
Mat Markers (Markermask.size (), cv_32s);
markers = Scalar::all (0); for (int idx = 0; idx >= 0; idx = hierarchy[idx][0], count++) <span style= "color: #33CC00;" >//hierarchy[idx][0] represents the latter profile </span> drawcontours (Markers,contours,idx,scalar::all (count+1), -1,8,
Hierarchy,int_max);
if (count = = 0) continue;
Watershed (img0,markers);
Vector<vec3b> Colortab; <span style= "color: #33CC00;" >//randomly set color </span> for (int i = 0; i < count; i++) {int b = therng (). Uniform (0,
255);
int g = THERNG (). Uniform (0, 255); int r = therng (). unifORM (0, 255);
Colortab.push_back (vec3b (Uchar) b, (Uchar) G, (Uchar) r));
} Mat wshed (Markers.size (), CV_8UC3); for (int i = 0, i < markers.rows;i++) for (int j = 0; J < Markers.cols; J +) {int tmp = markers.at<int>
(I,J); if (tmp = = 1) wshed.at<vec3b> (i, j) = Vec3b (255,255,255);//Boundary value = 1 else if (tmp <= 0 | | tmp>count) WSHED.A
T<vec3b> (i, j) = Vec3b (0,0,0);
else Wshed.at<vec3b> (i, j) = Colortab[tmp-1];
} imshow ("Watershed transform 1", wshed);
wshed = 0.5*wshed + 0.5*imggray;
Imshow ("Watershed Transformation", wshed);
} return 0; }
Personal Understanding:
1.watershed () function accepts two parameters, void watershed (Inputarray image, Inputoutputarraymarkers)
The input image is 8-bit 3-channel, markers with a tagged image (or map), and the result is saved in markers.
2.markers sets the pixel to 1,2,3 according to the Mark ....
The 3.findContours contours parameter is a detected contour array, count records the Contour group number, and the markers result is 1,2,.... count, so the color is also randomly set to count.
4. According to the markers value, different regions to draw different colors, the boundary value of 1, drawn to white.
5. Results screenshot
Example 2:
#include "cv.h" #include "highgui.h" using namespace CV;
int main () {Mat img = imread ("d:\\tongliya.jpg");
Imshow ("Original image", IMG);
Mat Imggray;
Cvtcolor (Img,imggray,cv_bgr2gray);
Imshow ("Gray image", imggray);
Mat binary;
Adaptivethreshold (imggray,binary,255,adaptive_thresh_mean_c,cv_thresh_binary,5,0);
Threshold (IMGGRAY,BINARY,100,255,CV_THRESH_BINARY_INV);
Imshow ("Binary image", binary);
Mat FG;
Erode (Binary,fg,mat (), point ( -1,-1), 1);//255 labeling foreground, corrosion makes the highlight area isolated and reduced, can obtain only the pixel imshow of important objects ("foreground image", FG);
Mat BG;
Dilate (Binary,bg,mat (), point ( -1,-1), 1)//background with 128 labeling, expansion of the highlighted areas are expanded and Unicom threshold (BG,BG,1,128,THRESH_BINARY_INV);
Imshow ("Background image", BG);
Mat Markers (Binary.size (), Cv_8u,scalar::all (0));
Markers = FG + bg;//watershed algorithm input parameter imshow ("markers image", markers);
Markers.convertto (markers,cv_32s);
Watershed (img,markers);//update tag image Mat TMP = Markers.clone (); Markers.convertto (tmp,cv_8u)//return Tagged Image, the watershed is located at a value of 0 imshow ("segmentation", TMP);
Markers.convertto (tmp,cv_8u,255,255);
Imshow ("Watersheds boundary", TMP);
Waitkey ();
return 0; }