OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割

OPENCV系列博客主要记录自己学习OPENCV的历程,以及存储已经实现的代码,以备后续回顾使用,代码中包含了主要的备注。

1.距离变换和分水岭分割原理 

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第1张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第2张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第3张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第4张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第5张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第6张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第7张图片

 

 

2.距离变换和分水岭分割--处理流程

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第8张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第9张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第10张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第11张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第12张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第13张图片

 OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第14张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第15张图片

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第16张图片

 

2.代码实现

#include 
#include 
#include 

using namespace std;
using namespace cv;

/*
   This program is used to verify the Watershed method, also as the final project of the OPENCV learning
*/


char input_win[] = "Input image";
char black_background[] = "Black background";
char watershed_win[] = "Water shed image";
char sharped_win[] = "Sharped image";


int main(int argc, char** argv) {
	// Step 0: 读取image,并判断是否为空
		Mat src;
		src = imread("E:/OpenCVLearning/Project/source_image/card.png");
		if (src.empty()) {
			printf("Could not load this image, please check...");
			return -1;
				}
		namedWindow(input_win,CV_WINDOW_AUTOSIZE);
		imshow(input_win,src);
	

	   // Step 1: 将白色背景转化为黑色背景,为后续变换做准备
		for (int row = 0; row < src.rows; row++) {
			for (int col = 0; col < src.cols; col++) {
				if (src.at(row,col) == Vec3b(255,255,255)) {
					src.at(row, col)[0] = 0;
					src.at(row, col)[1] = 0;				//判断当前像素的RGB是否均为255-白色,若是,将其替换为黑色
					src.at(row, col)[2] = 0;				//!!注意:这个方法可以同样用在替换某一像素的特定颜色!
				}
			}
		}
		namedWindow(black_background, CV_WINDOW_AUTOSIZE);
		imshow(black_background, src);


		// Step 2: 使用Laplace算子,将图片进行锐化Sharp (注意:算子定义,filter2D, 图片格式转换等)
		Mat kernal = (Mat_(3, 3) << 1, 1, 1, 1, -8, 1, 1, 1, 1);   //创建Laplace算子
		Mat laplaceImg;
		Mat sharp = src;

		filter2D(sharp, laplaceImg,CV_32F, kernal, Point(-1,-1),0);	     //进行滤波
		src.convertTo(sharp,CV_32F);
		Mat imgResult = sharp - laplaceImg;

		//
		imgResult.convertTo(imgResult, CV_8UC3);
		laplaceImg.convertTo(laplaceImg, CV_8UC3);						 //转换图片格式

		namedWindow(sharped_win, CV_WINDOW_AUTOSIZE);
		imshow(sharped_win, imgResult);


		// Step 3: 二值距离变换
		Mat binImage;
		cvtColor(src, binImage, CV_BGR2GRAY);
		threshold(binImage, binImage,40,255, CV_THRESH_BINARY | CV_THRESH_OTSU);  //使用自动方式查找二值化阈值


		Mat dist;    
		distanceTransform(binImage,dist, CV_DIST_L1,3);						     //距离变化??得到的是什么??
		normalize(dist,dist,0,1,NORM_MINMAX);


		threshold(dist, dist, 0.4, 1, CV_THRESH_BINARY);                        //得到marker?

		// Step 4: 二值腐蚀
		Mat kernel1 = Mat::ones(13,13,CV_8UC1);
		erode(dist, dist, kernel1);
		imshow("Peaks",dist);


		// Step5: 寻找轮廓,并且标记出来,以便后续处理
		Mat dist_8u;
		dist.convertTo(dist_8u, CV_8U);

		vector> contours;											 //查找轮廓
		findContours(dist_8u, contours, RETR_EXTERNAL,CHAIN_APPROX_SIMPLE,Point(0,0));

		Mat markers = Mat::zeros(dist.size(),CV_32SC1);							//创建一个marker图像,并在其上进行绘制轮廓
		for (size_t i = 0; i < contours.size(); i++) {
			drawContours(markers, contours, static_cast(i), Scalar::all(static_cast(i) + 1), -1); //注意,-1表示内部填充,>0表示填充轮廓
		}
		circle(markers, Point(5, 5), 3, Scalar(255, 255, 255), -1);				//
		imshow("my markers", markers * 1000);



		// Step6: 使用分水岭变换,查找并显示
		watershed(src, markers);
		Mat mark = Mat::zeros(markers.size(), CV_8UC1);
		markers.convertTo(mark, CV_8UC1);
		bitwise_not(mark, mark, Mat());
		imshow("watershed image", mark);



		// generate random color
		vector colors;
		for (size_t i = 0; i < contours.size(); i++) {
			int r = theRNG().uniform(0, 255);
			int g = theRNG().uniform(0, 255);
			int b = theRNG().uniform(0, 255);
			colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
		}

		// fill with color and display final result
		Mat dst = Mat::zeros(markers.size(), CV_8UC3);
		for (int row = 0; row < markers.rows; row++) {
			for (int col = 0; col < markers.cols; col++) {
				int index = markers.at(row, col);
				if (index > 0 && index <= static_cast(contours.size())) {
					dst.at(row, col) = colors[index - 1];
				}
				else {
					dst.at(row, col) = Vec3b(0, 0, 0);
				}
			}
		}
		imshow("Final Result", dst);

		waitKey(0);
		return 0;
}

 

3.运行效果如下

OpenCV-学习历程33 - 基于距离变换与分水岭的图像分割_第17张图片

 

 

你可能感兴趣的:(Opencv,OPENCV学习记录)