【OpenCV学习笔记】三十二、分水岭算法及图像修补

分水岭算法及图像修补

1.分水岭算法——watershed()

2.图像修补——inpaint()

先上ppt:

代码:1.分水岭算法

///分水岭算法
#include "opencv2/opencv.hpp"
using namespace cv;
int main()
{
	Mat srcImg = imread("bird.jpg",CV_LOAD_IMAGE_COLOR);
	imshow("srcImg", srcImg);
	Mat copyImg = srcImg.clone();
	//1.定义标记图像markers
	Mat markers(srcImg.size(),CV_8UC1,Scalar(0));
	//标记背景
	rectangle(markers,Point(1,1),Point(srcImg.cols-2,srcImg.rows-2),Scalar(255),1,8);
	//标记鸟
	rectangle(markers, Point(srcImg.cols / 2 - 20, srcImg.rows / 2 - 20), Point(srcImg.cols / 2 +20, srcImg.rows / 2 + 20), Scalar(128), -1, 8);
	//标记石头
	rectangle(markers, Point(srcImg.cols / 2 - 30, srcImg.rows - 50), Point(srcImg.cols / 2 + 60, srcImg.rows - 10), Scalar(64), -1, 8);
	imshow("markers-input",markers);
	//2.基于标记图像的分水岭算法
	//将markers转换成32位单通道图像(分水岭函数要求)
	markers.convertTo(markers,CV_32S);
	//分水岭算法
	watershed(srcImg,markers);
	//将markers转换成8位单通道
	markers.convertTo(markers, CV_8UC1);
	imshow("markers-output", markers);
	//3.提取轮廓并绘制轮廓
	Mat mark1, mark2,mark3;
	mark1 = markers.clone();//提取鸟的轮廓
	mark2 = markers.clone();//提取石头轮廓
	mark3 = markers.clone();//提取背景轮廓
	//阈值化,黑中找白,找鸟
	threshold(mark1,mark1,129,255,CV_THRESH_TOZERO_INV);
	threshold(mark1,mark1,120,255,CV_THRESH_TOZERO);
	//阈值化,黑中找白,找石头
	threshold(mark2, mark2, 65, 255, CV_THRESH_TOZERO_INV);
	//阈值化,黑中找白,找背景
	threshold(mark3, mark3, 129, 255, CV_THRESH_BINARY);
	imshow("mark1", mark1);
	imshow("mark2", mark2);
	imshow("mark3", mark3);
	//寻找背景轮廓并绘制
	vector<vector<Point>> contours3;
	findContours(mark3, contours3, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
	drawContours(copyImg, contours3, -1, Scalar(0, 0, 255), -1, 8);
	//寻找鸟轮廓并绘制
	vector<vector<Point>> contours1;
	findContours(mark1,contours1,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
	drawContours(copyImg,contours1,-1,Scalar(255,0,0),-1,8);
	//寻找石头轮廓并绘制
	vector<vector<Point>> contours2;
	findContours(mark2, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
	drawContours(copyImg, contours2, -1, Scalar(0, 255, 0), -1, 8);
	imshow("copyImg",copyImg);
	//4.与原图像叠加
	Mat result = srcImg*0.5 + copyImg*0.5;
	imshow("result", result);
	waitKey(0);
	return 0;
}

运行结果:

代码:2.图像修补

///图像修补
#include "opencv2/opencv.hpp"
using namespace cv;
//定义原图像srcImg和目标图像dstImg
Mat srcImg = imread("face.JPG", CV_LOAD_IMAGE_COLOR);
Mat dstImg = srcImg.clone();
//定义掩码inpaintMask,同srcImg一样大小,类型为8位单通道,初始化为纯黑(掩码非0部分起作用)
Mat inpaintMask(srcImg.size(), CV_8UC1, Scalar(0));
//定义鼠标左键是否按下的标志flag
bool flag=false;
//记录鼠标左键按下时的初始坐标
int xStart, yStart;
void onMouse(int event,int x,int y,int flags,void* param)
{
	switch (event)
	{
	case CV_EVENT_LBUTTONDOWN:
		flag = true;//鼠标左键按下,flag置为true
		xStart = x;//记录鼠标左键按下时的坐标
		yStart = y;
		break;
	case CV_EVENT_MOUSEMOVE:
		if (flag)
		{
			//在srcImg中画矩形,白色,向内填充
			rectangle(srcImg, Point(xStart, yStart), Point(x, y), Scalar(255, 255, 255), -1, 8);
			//在inpaintMask中画矩形,白色,向内填充
			rectangle(inpaintMask, Point(xStart, yStart), Point(x, y), Scalar(255, 255, 255), -1, 8);
		}
		break;
	case CV_EVENT_LBUTTONUP:
		flag = false;//鼠标左键抬起,flag置为false
		break;
	default:
		break;
	}
	//重新显示原图srcImg
	imshow("inpaint", srcImg);
	//重新显示掩码图像inpaintMask
	imshow("inpaintMask", inpaintMask);
}

int main()
{	
	imshow("srcImg", srcImg);
	//定义窗口"inpaint"
	namedWindow("inpaint",CV_WINDOW_AUTOSIZE);
	//设置鼠标回调函数
	setMouseCallback("inpaint",onMouse);
	//使得一开始就显示窗口"inpaint",显示原图srcImg
	imshow("inpaint", srcImg);
	//使得一开始就显示窗口"inpaintMask",显示掩码图像inpaintMask
	imshow("inpaintMask", inpaintMask);
	//使得一开始就显示窗口"dstImg",显示目标图像dstImg
	imshow("dstImg", dstImg);
	//无限循环,若按下空格键(ASCII码为32),则调用inpait()函数,重新显示目标图像dstImg
	while (1)
	{
		if (waitKey(0) == 32)//若按下空格键
		{
			//调用inpait()函数, 重新显示目标图像dstImg
			inpaint(srcImg, inpaintMask, dstImg, 4, CV_INPAINT_NS);
			imshow("dstImg", dstImg);
		}
	}
	waitKey(0);
	return 0;
}

运行结果:

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值