数据图像处理工程项目:基于距离变换的分水岭算法

#include<iostream>
#include<opencv2/opencv.hpp>

int max(int& a, int& b, int& c)
{
	int max = a;
	if (b > max)
	{
		max = b;
	}
	if (c > max)
	{
		max = c;
	}
	return max;
}
int min(int& a, int& b, int& c)
{
	int min = a;
	if (b < min)
	{
		min = b;
	}
	if (c < min)
	{
		min = c;
	}
	return min;
}

// 将红色的hsv提取出来
void Rgb2Hsv(float R, float G, float B, float& H, float& S, float& V)
{
	// r,g,b values are from 0 to 1
	// h = [0,360], s = [0,1], v = [0,1]
	// if s == 0, then h = -1 (undefined)
	float min, max, delta, tmp;
	tmp = R > G ? G : R;
	min = tmp > B ? B : tmp;
	tmp = R > G ? R : G;
	max = tmp > B ? tmp : B;
	V = max; // v
	delta = max - min;
	if (max != 0)
		S = delta / max; // s
	else
	{
		// r = g = b = 0 // s = 0, v is undefined
		S = 0;
		H = 0;
		return;
	}
	if (delta == 0) {
		H = 0;
		return;
	}
	else if (R == max) {
		if (G >= B)
			H = (G - B) / delta; // between yellow & magenta
		else
			H = (G - B) / delta + 6.0;
	}
	else if (G == max)
		H = 2.0 + (B - R) / delta; // between cyan & yellow
	else if (B == max)
		H = 4.0 + (R - G) / delta; // between magenta & cyan
	H *= 60.0; // degrees
}

using namespace std;
using namespace cv;
int main()
{
	//原图
	Mat scrImg1280 = imread("E:\\哈工智能\\fenge\\watershedone\\watershedone\\dst_ct.jpg");
	float mymax = 0.0;
	double minv = 0.0, maxv = 0.0;
	double* minp = &minv;
	double* maxp = &maxv;
	//获取图像的最大值最小值,返回的是指针
	minMaxIdx(scrImg1280, minp, maxp);
	cout << *minp << endl << *maxp << endl;
	/*Mat cropImg;*/
	Rect cropRect1280(455, 70, 360, 395);//dawei 1280*960裁剪尺寸
	//裁取感兴趣区域
	cropImg = scrImg1280(cropRect1280);
	float H, S, V;
	Mat redImg(cropImg.rows, cropImg.cols, CV_8UC3, Scalar::all(0));
	for (int i = 0; i < cropImg.rows; i++)
	{
		for (int j = 0; j < cropImg.cols; j++)
		{
			Rgb2Hsv(cropImg.ptr<Vec3b>(i)[j][2], cropImg.ptr<Vec3b>(i)[j][1], cropImg.ptr<Vec3b>(i)[j][0], H, S, V);
			if ((((312 < H) && (H < 360)) || ((0 < H) && (H < 50))) && (S > 0.5))//&&((V>0)&&(V<0.8))
			{
				redImg.ptr<Vec3b>(i)[j][0] = cropImg.ptr<Vec3b>(i)[j][0];
				redImg.ptr<Vec3b>(i)[j][1] = cropImg.ptr<Vec3b>(i)[j][1];
				redImg.ptr<Vec3b>(i)[j][2] = cropImg.ptr<Vec3b>(i)[j][2];
			}
			else
			{
				redImg.ptr<Vec3b>(i)[j][0] = 0;
				redImg.ptr<Vec3b>(i)[j][1] = 0;
				redImg.ptr<Vec3b>(i)[j][2] = 0;
			}
		}
	}
	//原图提取的灰度图

	Mat grayImage;
	cvtColor(redImg, grayImage, COLOR_BGR2GRAY);
	//灰度图二值化并填充小孔
	Mat threshold_img;
	threshold(grayImage, threshold_img, 0, 255, THRESH_OTSU);
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
	morphologyEx(threshold_img, threshold_img, MORPH_CLOSE, element, Point(-1, -1));
	imshow("morph", threshold_img);
	//生成前景图像sure_fg
	Mat dist;
	distanceTransform(threshold_img, dist, DIST_L2, 5);
	normalize(dist, dist, 0, 255, cv::NORM_MINMAX);
	double my_minv = 0.0, my_maxv = 0.0;
	minMaxIdx(dist, &my_minv, &my_maxv);
	Mat sure_fg;
	threshold(dist, sure_fg, 0.8 * my_maxv, 255, THRESH_BINARY);
	dilate(sure_fg, sure_fg, element, Point(-1, -1), 17);
	sure_fg.convertTo(sure_fg, CV_8U);
	imshow("sure_fg", sure_fg);
	//制作markers方法二:
	//生成背景图像
	Mat element1 = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
	Mat sure_bg;
	dilate(threshold_img, sure_bg, element, Point(-1, -1));
	imshow("sure_bg", sure_bg);
	//确定未知区域
	Mat unkonwn = Mat(threshold_img.size(), CV_8U);
	unkonwn = sure_bg-sure_fg;
	imshow("unkonwn",unkonwn);
	//markers
	Mat label_img = Mat(threshold_img.size(), CV_32S);
	int num = connectedComponents(sure_fg, label_img, 8);
	label_img = label_img +1;
	for (int i = 0; i < unkonwn.rows; i++)
	{
		for (int j = 0; j < unkonwn.cols; j++)
		{
			if (((int)unkonwn.at<uchar>(i, j)) == 255)
			{
				label_img.at<signed int>(i, j) = 0;
			}
		}
	}
	watershed(redImg, label_img);
	Mat v1 = Mat(redImg.size(), CV_8UC3);
	for (int i = 0; i < sure_bg.rows; i++)
	{
		for (int j = 0; j < sure_bg.cols; j++)
		{
			
			if (label_img.at<signed int>(i, j)==-1)
			{
				redImg.at<Vec3b>(i, j)[0] = 0;
				redImg.at<Vec3b>(i, j)[1] = 255;
				redImg.at<Vec3b>(i, j)[2] = 255;
			}
		}
	}
	imshow("src", redImg);
	waitKey(0);
	return 0;
}
//制作markers方法一
	//vector<vector<Point>> contours;
	//vector<Vec4i> hierarchy;
	//findContours(sure_fg, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());

	//Mat imageContours = Mat::zeros(sure_fg.size(), CV_8UC1);  //轮廓
	//Mat marks(sure_fg.size(), CV_32S);   //Opencv分水岭第二个矩阵参数
	//marks = Scalar::all(0);
	//int index = 0;
	//int compCount = 0;
	//for (; index >= 0; index = hierarchy[index][0], compCount++)
	//{
	//	// 4、对marks进行标记,对不同区域的轮廓进行编号,相当于设置注水点,有多少轮廓,就有多少注水点
	//	drawContours(marks, contours, index, Scalar::all(compCount + 1), 1, 8, hierarchy);     // 每个轮廓的标记点不一样
	//	drawContours(imageContours, contours, index, Scalar(255), 1, 8, hierarchy);
	//}
	/*watershed(redImg, label_img);
	for (int i = 0; i < sure_bg.rows; i++)
	{
		for (int j = 0; j < sure_bg.cols; j++)
		{

			if (label_img.at<signed int>(i, j) == -1)
			{
				redImg.at<Vec3b>(i, j)[0] = 0;
				redImg.at<Vec3b>(i, j)[1] = 255;
				redImg.at<Vec3b>(i, j)[2] = 255;
			}
		}
	}
	imshow("src", redImg);*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值